PluginProbe
Yatra – Travel Booking & Tour Operator Software / trunk
Yatra – Travel Booking & Tour Operator Software vtrunk
3.0.14 3.0.14.1 3.0.14.2 3.0.12 3.0.13 3.0.11 3.0.10 3.0.9 3.0.8 3.0.7 3.0.6 3.0.5 3.0.5.1 3.0.4 3.0.3 3.0.2.9 3.0.2.7 3.0.2.8 3.0.2.6 trunk 1.0.0 2.0.0 2.0.1 2.0.10 2.0.11 All 82 releases
← All changes | app/Controllers/ModuleController.php +59 -7 3.0.3trunk View file →
@@ -51,19 +51,24 @@
51 51 ],
52 52 ]);
53 53 }
54 54
55 + /**
56 + * Module toggle — critical-sensitivity cap. Enabling or disabling
57 + * a Pro module flips significant feature surfaces (Webhooks,
58 + * Channel Manager, Team & Access, etc.) on or off, so only the
59 + * Owner role holds `yatra_manage_modules` by default. The
60 + * previous implementation gated this on `yatra_edit_trips` which
61 + * meant any trip editor could toggle modules — that was the wrong
62 + * cap entirely. WP admins pass via the Team module's admin-
63 + * fallback filter.
64 + */
55 65 public function check_permission(?WP_REST_Request $request = null): bool
56 66 {
57 67 if (!is_user_logged_in()) {
58 68 return false;
59 69 }
60 -
61 - if (current_user_can('manage_options')) {
62 - return true;
63 - }
64 -
65 - return current_user_can('yatra_edit_trips');
70 + return current_user_can('yatra_manage_modules');
66 71 }
67 72
68 73 public function get_modules(): WP_REST_Response
69 74 {
@@ -100,8 +105,9 @@
100 105 // Check if trying to enable a premium module without Pro
101 106 if ($enabled && !empty($target_module['is_premium']) && !$target_module['is_available']) {
102 107 return $this->error_response(
103 108 sprintf(
109 + /* translators: %s: module name. */
104 110 __('%s is a premium module. Yatra Pro is required to enable this module.', 'yatra'),
105 111 $target_module['name']
106 112 ),
107 113 403
@@ -113,8 +119,9 @@
113 119 $pro_active = apply_filters('yatra_is_pro_active', false);
114 120 if (!$pro_active) {
115 121 return $this->error_response(
116 122 sprintf(
123 + /* translators: %s: module name. */
117 124 __('%s requires Yatra Pro. Please install and activate Yatra Pro to enable this module.', 'yatra'),
118 125 $target_module['name']
119 126 ),
120 127 403
@@ -121,8 +128,37 @@
121 128 );
122 129 }
123 130 }
124 131
132 + // Agency-tier gate: even with Pro active, the white-label/agency-only
133 + // modules need an Agency Yearly or Lifetime license.
134 + if ($enabled && !empty($target_module['requires_agency'])) {
135 + if (!apply_filters('yatra_is_agency_active', false)) {
136 + return $this->error_response(
137 + sprintf(
138 + /* translators: %s: module name. */
139 + __('%s is available on the Yatra Pro Scale plan only. Upgrade your license to enable it.', 'yatra'),
140 + $target_module['name']
141 + ),
142 + 403
143 + );
144 + }
145 + }
146 +
147 + // Growth-or-Agency gate (e.g. AI Assistant).
148 + if ($enabled && !empty($target_module['requires_growth_or_agency'])) {
149 + if (!apply_filters('yatra_is_ai_eligible', false)) {
150 + return $this->error_response(
151 + sprintf(
152 + /* translators: %s: module name. */
153 + __('%s requires a Growth or Scale license. Upgrade your plan to enable it.', 'yatra'),
154 + $target_module['name']
155 + ),
156 + 403
157 + );
158 + }
159 + }
160 +
125 161 $updated = ModuleManager::setModuleStatus($slug, (bool) $enabled);
126 162
127 163 return $this->success_response([
128 164 'data' => $updated,
@@ -177,8 +213,22 @@
177 213 continue;
178 214 }
179 215 }
180 216
217 + if ($enabled && !empty($target_module['requires_agency'])) {
218 + if (!apply_filters('yatra_is_agency_active', false)) {
219 + $blocked_modules[] = $target_module['name'];
220 + continue;
221 + }
222 + }
223 +
224 + if ($enabled && !empty($target_module['requires_growth_or_agency'])) {
225 + if (!apply_filters('yatra_is_ai_eligible', false)) {
226 + $blocked_modules[] = $target_module['name'];
227 + continue;
228 + }
229 + }
230 +
181 231 $sanitized[] = [
182 232 'slug' => $slug,
183 233 'enabled' => (bool) $enabled,
184 234 ];
@@ -186,8 +236,9 @@
186 236
187 237 if (empty($sanitized) && !empty($blocked_modules)) {
188 238 return $this->error_response(
189 239 sprintf(
240 + /* translators: %s: comma-separated list of module names. */
190 241 __('The following modules require Yatra Pro: %s', 'yatra'),
191 242 implode(', ', $blocked_modules)
192 243 ),
193 244 403
@@ -196,12 +247,13 @@
196 247
197 248 if (!empty($blocked_modules)) {
198 249 // Partial success - some modules processed, some blocked
199 250 $updated = ModuleManager::setMultipleStatuses($sanitized);
200 -
251 +
201 252 return $this->success_response([
202 253 'data' => $updated,
203 254 'message' => sprintf(
255 + /* translators: %s: comma-separated list of module names. */
204 256 __('Some modules were skipped because they require Yatra Pro: %s', 'yatra'),
205 257 implode(', ', $blocked_modules)
206 258 ),
207 259 ]);