PluginProbe ʕ •ᴥ•ʔ
OttoKit: All-in-One Automation Platform / 1.0.75
OttoKit: All-in-One Automation Platform v1.0.75
1.1.31 1.1.30 1.1.29 1.1.28 1.1.27 1.1.9 trunk 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 1.0.18 1.0.19 1.0.20 1.0.21 1.0.22 1.0.23 1.0.24 1.0.25 1.0.26 1.0.27 1.0.28 1.0.29 1.0.30 1.0.31 1.0.32 1.0.33 1.0.34 1.0.35 1.0.36 1.0.37 1.0.38 1.0.39 1.0.40 1.0.41 1.0.42 1.0.43 1.0.44 1.0.45 1.0.46 1.0.47 1.0.48 1.0.49 1.0.50 1.0.51 1.0.52 1.0.53 1.0.54 1.0.55 1.0.56 1.0.57 1.0.58 1.0.59 1.0.60 1.0.61 1.0.62 1.0.63 1.0.64 1.0.65 1.0.66 1.0.67 1.0.68 1.0.69 1.0.7 1.0.70 1.0.71 1.0.72 1.0.73 1.0.74 1.0.75 1.0.76 1.0.77 1.0.78 1.0.79 1.0.8 1.0.80 1.0.81 1.0.82 1.0.83 1.0.84 1.0.85 1.0.86 1.0.87 1.0.88 1.0.89 1.0.9 1.0.90 1.1.0 1.1.1 1.1.10 1.1.11 1.1.12 1.1.13 1.1.14 1.1.15 1.1.16 1.1.17 1.1.18 1.1.19 1.1.2 1.1.20 1.1.21 1.1.22 1.1.23 1.1.24 1.1.25 1.1.26 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8
suretriggers / src / Controllers / RestController.php
suretriggers / src / Controllers Last commit date
AuthController.php 1 year ago AutomationController.php 3 years ago EventController.php 3 years ago GlobalSearchController.php 1 year ago IntegrationsController.php 2 years ago OptionController.php 3 years ago RestController.php 1 year ago RoutesController.php 1 year ago SettingsController.php 3 years ago WebhookRequestsController.php 1 year ago
RestController.php
537 lines
1 <?php
2 /**
3 * RestController.
4 * php version 5.6
5 *
6 * @category RestController
7 * @package SureTriggers
8 * @author BSF <username@example.com>
9 * @license https://www.gnu.org/licenses/gpl-3.0.html GPLv3
10 * @link https://www.brainstormforce.com/
11 * @since 1.0.0
12 */
13
14 namespace SureTriggers\Controllers;
15
16 use Exception;
17 use SureTriggers\Integrations\WordPress\WordPress;
18 use SureTriggers\Traits\SingletonLoader;
19 use SureTriggers\Models\SaasApiToken;
20 use WP_REST_Request;
21 use WP_REST_Response;
22 use WP_Error;
23
24 /**
25 * RestController
26 *
27 * @category RestController
28 * @package SureTriggers
29 * @author BSF <username@example.com>
30 * @license https://www.gnu.org/licenses/gpl-3.0.html GPLv3
31 * @link https://www.brainstormforce.com/
32 * @since 1.0.0
33 */
34 class RestController {
35
36 /**
37 * Access token for authentication.
38 *
39 * @var string $acccess_token
40 */
41 private $secret_key;
42
43 use SingletonLoader;
44
45 /**
46 * Initialise data.
47 */
48 public function __construct() {
49 $this->secret_key = SaasApiToken::get();
50 add_filter( 'determine_current_user', [ $this, 'basic_auth_handler' ], 20 );
51 add_filter( 'debug_information', [ $this, 'sure_triggers_connection_info' ] );
52 }
53
54 /**
55 * Permission callback for rest api after determination of current user.
56 *
57 * @param WP_REST_Request $request Request.
58 */
59 public function autheticate_user( $request ) {
60 $secret_key = $request->get_header( 'st_authorization' );
61 list($secret_key) = sscanf( $secret_key, 'Bearer %s' );
62
63 if ( $this->secret_key !== $secret_key ) {
64 return false;
65 }
66
67 return true;
68 }
69
70 /**
71 * Create WP Connection.
72 *
73 * @param WP_REST_Request $request Request data.
74 * @return WP_REST_Response
75 */
76 public function create_wp_connection( $request ) {
77
78 $user_agent = $request->get_header( 'user-agent' );
79 if ( 'SureTriggers' !== $user_agent ) {
80 return new WP_REST_Response(
81 [
82 'success' => false,
83 'data' => 'Unauthorized',
84 ],
85 403
86 );
87 }
88 $params = $request->get_json_params();
89
90 $username = isset( $params['wp-username'] ) ? sanitize_text_field( $params['wp-username'] ) : '';
91 $password = isset( $params['wp-password'] ) ? $params['wp-password'] : '';
92
93 if ( empty( $username ) || empty( $password ) ) {
94 return new WP_REST_Response(
95 [
96 'success' => false,
97 'data' => 'Username and password are required.',
98 ],
99 400
100 );
101 }
102
103 $user = wp_authenticate_application_password( null, $username, $password );
104
105 if ( is_wp_error( $user ) ) {
106 return new WP_REST_Response(
107 [
108 'success' => false,
109 'data' => 'Invalid username or password.',
110 ],
111 403
112 );
113 }
114
115 $connection_status = $request->get_param( 'connection-status' );
116 $access_key = $request->get_param( 'sure-triggers-access-key' );
117 $connected_email = $request->get_param( 'connected_email' );
118
119 if ( false === $connection_status ) {
120 $access_key = 'connection-denied';
121 }
122
123 $connected_email_id = isset( $connected_email ) ? sanitize_email( wp_unslash( $connected_email ) ) : '';
124
125 if ( isset( $access_key ) ) {
126 SaasApiToken::save( $access_key );
127 }
128 OptionController::set_option( 'connected_email_key', $connected_email_id );
129
130 return new WP_REST_Response(
131 [
132 'success' => true,
133 'data' => 'Connected successfully.',
134 ],
135 200
136 );
137 }
138
139 /**
140 * Verify user token.
141 *
142 * @return array|WP_Error $response Response.
143 */
144 public static function verify_user_token() {
145 $args = [
146 'body' => [
147 'token' => SaasApiToken::get(),
148 'saas-token' => SaasApiToken::get(),
149 'base_url' => str_replace( '/wp-json/', '', get_rest_url() ),
150 ],
151 'sslverify' => false,
152 ];
153 $response = wp_remote_post( SURE_TRIGGERS_API_SERVER_URL . '/token/verify', $args );
154
155 return $response;
156 }
157
158 /**
159 * Verify connection.
160 *
161 * @return array|WP_Error $response Response.
162 */
163 public static function suretriggers_verify_wp_connection() {
164 $args = [
165 'body' => [
166 'saas-token' => SaasApiToken::get(),
167 'base_url' => str_replace( '/wp-json/', '', get_rest_url() ),
168 'plugin_version' => SURE_TRIGGERS_VER,
169 ],
170 'sslverify' => false,
171 ];
172 $response = wp_remote_post( SURE_TRIGGERS_API_SERVER_URL . '/connection/wordpress/ping', $args );
173 return $response;
174 }
175
176 /**
177 * Authenticate User for API calls.
178 *
179 * @param array|object $user USer.
180 *
181 * @return int|null
182 */
183 public function basic_auth_handler( $user ) {
184 // Don't authenticate twice.
185 if ( ! empty( $user ) ) {
186 return $user;
187 }
188
189 // Check that we're trying to authenticate.
190 if ( ! isset( $_SERVER['PHP_AUTH_USER'] ) || ! isset( $_SERVER['PHP_AUTH_PW'] ) ) { //phpcs:ignore
191 return $user;
192 }
193
194 $username = sanitize_text_field( wp_unslash( $_SERVER['PHP_AUTH_USER'] ) ); //phpcs:ignore
195 $password = sanitize_text_field( wp_unslash( $_SERVER['PHP_AUTH_PW'] ) ); //phpcs:ignore
196
197 /**
198 * In multi-site, wp_authenticate_spam_check filter is run on authentication. This filter calls.
199 * get_currentuserinfo which in turn calls the determine_current_user filter. This leads to infinite.
200 * recursion and a stack overflow unless the current function is removed from the determine_current_user.
201 * filter during authentication.
202 */
203 remove_filter( 'determine_current_user', [ $this, 'basic_auth_handler' ], 20 );
204
205 $user = wp_authenticate( $username, $password );
206
207 add_filter( 'determine_current_user', [ $this, 'basic_auth_handler' ], 20 );
208
209 if ( is_wp_error( $user ) ) {
210 return null;
211 }
212
213 return $user->ID;
214 }
215
216 /**
217 * Authenticate user for new connection create api.
218 *
219 * @return bool
220 */
221 public function is_current_user() {
222 if ( current_user_can( 'manage_options' ) ) {
223 return true;
224 }
225 return false;
226 }
227
228 /**
229 * Execute action events.
230 *
231 * @param WP_REST_Request $request Request data.
232 * @return WP_REST_Response
233 */
234 public function run_action( $request ) {
235 $request->get_param( 'wp_user_id' );
236
237 $user_id = $request->get_param( 'wp_user_id' );
238 $automation_id = $request->get_param( 'automation_id' );
239 $integration = $request->get_param( 'integration' );
240 $action_type = $request->get_param( 'type_event' );
241 $selected_options = $request->get_param( 'selected_options' );
242 $context = $request->get_param( 'context' );
243 $fields = $request->get_param( 'fields' );
244
245 if ( empty( $user_id ) ) {
246 $user_id = isset( $context['pluggable_data']['wp_user_id'] ) ? sanitize_text_field( $context['pluggable_data']['wp_user_id'] ) : '';
247 }
248
249 if ( empty( $integration ) || empty( $action_type ) ) {
250 return self::error_message( 'Integration or action type is missing' );
251 }
252
253 if ( isset( $selected_options['wp_user_email'] ) && ! ( 'EDD' === $integration && 'find_user_purchased_download' === $action_type ) ) {
254 $is_valid = WordPress::validate_email( $selected_options['wp_user_email'] );
255
256 if ( ! $is_valid->valid ) {
257 if ( $is_valid->multiple ) {
258 return self::error_message( 'One or more email address is not valid.' );
259 } else {
260 return self::error_message( 'Email address is not valid.' );
261 }
262 }
263
264 if ( str_contains( $selected_options['wp_user_email'], ',' ) ) {
265 $email_list = explode( ',', $selected_options['wp_user_email'] );
266
267 foreach ( $email_list as $single_email ) {
268 if ( ! email_exists( trim( $single_email ) ) ) {
269 return self::error_message( 'User with email ' . $single_email . ' does not exists.' );
270 }
271 }
272 } else {
273 if ( ! email_exists( $selected_options['wp_user_email'] ) ) {
274 return self::error_message( 'User with email ' . $selected_options['wp_user_email'] . ' does not exists.' );
275 }
276 }
277 }
278 $registered_actions = EventController::get_instance()->actions;
279 $action_event = $registered_actions[ $integration ][ $action_type ];
280
281 $fun_params = [
282 $user_id,
283 $automation_id,
284 $fields,
285 $selected_options,
286 $context,
287 ];
288
289 try {
290 $result = call_user_func_array(
291 $action_event['function'],
292 $fun_params
293 );
294 return self::success_message( $result );
295 } catch ( Exception $e ) {
296 return self::error_message( $e->getMessage(), 400 );
297 }
298 }
299
300 /**
301 * Error message format.
302 *
303 * @param string $message Error message.
304 * @param string $status Error message.
305 *
306 * @return object
307 */
308 public static function error_message( $message, $status = 401 ) {
309 return new WP_REST_Response(
310 [
311 'success' => false,
312 'data' => [
313 'errors' => $message,
314 ],
315 ],
316 $status
317 );
318 }
319
320 /**
321 * Success message format.
322 *
323 * @param array $data response data to be sent.
324 *
325 * @return object
326 */
327 public static function success_message( $data = [] ) {
328 $result = [];
329
330 if ( ! empty( $data ) ) {
331 $result['result'] = $data;
332 }
333
334 return new WP_REST_Response(
335 [
336 'success' => true,
337 'data' => $result,
338 ],
339 200
340 );
341
342 }
343
344 /**
345 * Add/Remove/Update the triggers..
346 * When new/update/remove automation on Sass then execute this endpoint to update the automation.
347 *
348 * @param WP_REST_Request $request Request data.
349 * @return WP_REST_Response
350 */
351 public function manage_triggers( $request ) {
352 $events = $request->get_param( 'events' ) ? json_decode( stripslashes( $request->get_param( 'events' ) ), true ) : [];
353
354 // Selected field data from the trigger.
355 $data = $request->get_param( 'data' ) ? json_decode( stripslashes( $request->get_param( 'data' ) ), true ) : [];
356
357 // Get the trigger data from the option and append data in trigger data option.
358 $trigger_data = OptionController::get_option( 'trigger_data' );
359 if ( empty( $trigger_data ) ) {
360 $trigger_data = [];
361 }
362
363 if ( is_array( $data ) && is_array( $events ) ) {
364 $index = array_search( $data['trigger'], array_column( $events, 'trigger' ) );
365 if ( is_array( $trigger_data ) && false !== $index && $data['integration'] === $events[ $index ]['integration'] ) {
366 $trigger_data[ $data['integration'] ][ $data['trigger'] ]['selected_options'] = $data['selected_data'];
367 }
368 }
369
370 OptionController::set_option( 'triggers', $events );
371 // Set the new option for the trigger data.
372 OptionController::set_option( 'trigger_data', $trigger_data );
373 $events = array_column( $events, 'trigger' );
374 return self::success_message(
375 [
376 'events' => $events,
377 'data' => $trigger_data,
378 ]
379 );
380 }
381
382 /**
383 * Send response to Saas that trigger is executed.
384 *
385 * @param array $trigger_data Trigger data.
386 *
387 * @return bool
388 */
389 public function trigger_listener( $trigger_data ) {
390 // Pass unique WordPress webhook id.
391 $wordpress_webhook_uuid = str_replace( '-', '', wp_generate_uuid4() );
392 $site_url = esc_url_raw( str_replace( '/wp-json/', '', get_site_url() ) );
393 $site_url = preg_replace( '/^https?:\/\//', '', $site_url );
394 $encoded_site_url = urlencode( (string) $site_url );
395 $trigger_data['wordpress_webhook_uuid'] = $wordpress_webhook_uuid . '_' . $encoded_site_url;
396 $args = [
397 'headers' => [
398 'Authorization' => 'Bearer ' . $this->secret_key,
399 'Referer' => str_replace( '/wp-json/', '', get_site_url() ),
400 'RefererRestUrl' => str_replace( '/wp-json/', '', get_rest_url() ),
401 ],
402 'body' => json_decode( wp_json_encode( $trigger_data ), 1 ),
403 'sslverify' => false,
404 ];
405
406 /**
407 *
408 * Ignore line
409 *
410 * @phpstan-ignore-next-line
411 */
412 $response = wp_remote_post( SURE_TRIGGERS_WEBHOOK_SERVER_URL . '/wordpress/webhook', $args );
413 // Store every webhook requests.
414 $error_info = wp_remote_retrieve_body( $response );
415 if ( 405 === wp_remote_retrieve_response_code( $response ) ) {
416 $error_info = wp_remote_retrieve_response_message( $response );
417 }
418 if ( 0 === wp_remote_retrieve_response_code( $response ) ) {
419 $error_info = __( 'Service not available', 'suretriggers' );
420 }
421 unset( $args['headers']['Authorization'] );
422 WebhookRequestsController::suretriggers_log_request( (string) wp_json_encode( $args ), (int) wp_remote_retrieve_response_code( $response ), $error_info );
423
424 if ( wp_remote_retrieve_response_code( $response ) === 200 ) {
425 return true;
426 }
427
428 return false;
429 }
430
431 /**
432 * Update the connection from SAAS.
433 *
434 * @param WP_REST_Request $request Request data.
435 *
436 * @return void
437 */
438 public function connection_update( $request ) {
439 $secret = $request->get_param( 'secret_key' );
440 if ( $secret && is_string( $secret ) ) {
441 SaasApiToken::save( $secret );
442 }
443 }
444
445 /**
446 * Disconnect connection
447 *
448 * @param WP_REST_Request $request Request data.
449 * @return WP_REST_Response
450 */
451 public function connection_disconnect( $request ) {
452 SaasApiToken::save( null );
453 return self::success_message();
454 }
455
456 /**
457 * Test Trigger
458 * When test trigger is initiated on Sass then execute this endpoint to create a transient for identifying trigger event.
459 *
460 * @param WP_REST_Request $request Request data.
461 * @return WP_REST_Response
462 */
463 public function test_triggers( $request ) {
464 $test_triggers = (array) OptionController::get_option( 'test_triggers', [] );
465 $event = [
466 'trigger' => $request->get_param( 'trigger' ),
467 'integration' => $request->get_param( 'integration' ),
468 ];
469
470 // if request is to delete the transient, delete it and return.
471 if ( $request->get_param( 'clear_transient_data' ) === 'yes' ) {
472 $test_triggers = array_filter(
473 $test_triggers,
474 function ( $v ) use ( $event ) {
475 return $v !== $event;
476 }
477 );
478 OptionController::set_option( 'test_triggers', $test_triggers );
479
480 return;
481 }
482
483 $test_triggers[] = $event;
484 $test_triggers = array_unique( $test_triggers, SORT_REGULAR );
485 $tmp_test_triggers = [];
486
487 foreach ( $test_triggers as $test_trigger ) {
488 if ( ! empty( $test_trigger['trigger'] ) ) {
489 $tmp_test_triggers[] = $test_trigger;
490 }
491 }
492
493 OptionController::set_option( 'test_triggers', $tmp_test_triggers );
494 }
495
496 /**
497 * SureTriggers Connection Info
498 *
499 * @param array $debug_info Info data.
500 * @return array
501 */
502 public function sure_triggers_connection_info( $debug_info ) {
503 // Verify if SureTriggers is connected successfully.
504 $response = self::verify_user_token();
505 $connection = ( wp_remote_retrieve_response_code( $response ) === 200 );
506 if ( $connection ) {
507 $connection_status = 'Connection Successfully Set';
508 } else {
509 $connection_status = 'Error in Connection';
510 }
511 $debug_info['suretriggers'] = [
512 'label' => __( 'SureTriggers', 'suretriggers' ),
513 'fields' => [
514 'suretriggers_status' => [
515 'label' => __( 'SureTriggers Status', 'suretriggers' ),
516 'value' => $connection_status,
517 'private' => false,
518 ],
519 'rest_url' => [
520 'label' => __( 'Rest URL', 'suretriggers' ),
521 'value' => esc_url( get_rest_url() ),
522 'private' => false,
523 ],
524 'suretriggers_version' => [
525 'label' => __( 'SureTriggers Version', 'suretriggers' ),
526 'value' => SURE_TRIGGERS_VER,
527 'private' => false,
528 ],
529 ],
530 ];
531 return $debug_info;
532 }
533
534 }
535
536 RestController::get_instance();
537