| | |
| | | <?php |
| | | namespace JVBase\rest\routes; |
| | | |
| | | use JVBase\rest\RestRouteManager; |
| | | use JVBase\rest\Rest; |
| | | use JVBase\rest\Route; |
| | | use WP_REST_Request; |
| | | use WP_REST_Response; |
| | | use Exception; |
| | |
| | | exit; // Exit if accessed directly |
| | | } |
| | | |
| | | class IntegrationsRoutes extends RestRouteManager |
| | | class IntegrationsRoutes extends Rest |
| | | { |
| | | |
| | | /** |
| | |
| | | */ |
| | | public function registerRoutes(): void |
| | | { |
| | | register_rest_route($this->namespace, '/integrations', [ |
| | | 'methods' => 'POST', |
| | | 'callback' => [$this, 'handleAction'], |
| | | 'permission_callback' => [$this, 'checkPermission'], |
| | | 'args' => [ |
| | | 'service' => [ |
| | | 'required' => true, |
| | | 'type' => 'string', |
| | | 'enum' => JVB()->getAvailableServices() |
| | | ], |
| | | 'action' => [ |
| | | 'required' => true, |
| | | 'sanitize_callback' => 'sanitize_text_field', |
| | | ], |
| | | 'user_id' => [ |
| | | 'required' => false, |
| | | 'sanitize_callback' => 'absint', |
| | | ], |
| | | 'context' => [ |
| | | 'required' => false, |
| | | 'default' => 'user', |
| | | 'sanitize_callback' => 'sanitize_text_field', |
| | | 'validate_callback' => function($param) { |
| | | return in_array($param, ['admin', 'user']); |
| | | } |
| | | ], |
| | | 'data' => [ |
| | | 'required' => false, |
| | | 'default' => [], |
| | | ] |
| | | ] |
| | | ]); |
| | | |
| | | // register_rest_route($this->namespace, '/oauth/callback', [ |
| | | // 'methods' => 'GET', |
| | | // 'callback' => [$this, 'handleOAuthCallback'], |
| | | // 'permission_callback' => '__return_true', // External service callback |
| | | // 'args' => [ |
| | | // 'service' => [ |
| | | // 'required' => true, |
| | | // 'sanitize_callback' => 'sanitize_text_field', |
| | | // ], |
| | | // 'code' => [ |
| | | // 'required' => false, |
| | | // 'sanitize_callback' => 'sanitize_text_field', |
| | | // ], |
| | | // 'state' => [ |
| | | // 'required' => false, |
| | | // 'sanitize_callback' => 'sanitize_text_field', |
| | | // ], |
| | | // 'error' => [ |
| | | // 'required' => false, |
| | | // 'sanitize_callback' => 'sanitize_text_field', |
| | | // ] |
| | | // ] |
| | | // ]); |
| | | |
| | | // Add OAuth initiation route (for AJAX calls) |
| | | register_rest_route($this->namespace, '/oauth/connect', [ |
| | | 'methods' => 'POST', |
| | | 'callback' => [$this, 'initiateOAuth'], |
| | | 'permission_callback' => [$this, 'checkPermissions'], |
| | | 'args' => [ |
| | | 'service' => [ |
| | | 'required' => true, |
| | | 'sanitize_callback' => 'sanitize_text_field', |
| | | ], |
| | | 'user_id' => [ |
| | | 'required' => false, |
| | | 'sanitize_callback' => 'absint', |
| | | ], |
| | | 'return_url' => [ |
| | | 'required' => false, |
| | | 'sanitize_callback' => 'esc_url_raw', |
| | | ] |
| | | ] |
| | | ]); |
| | | } |
| | | |
| | | /** |
| | | * Check permissions based on context |
| | | */ |
| | | public function checkPermission(\WP_REST_Request $request): bool |
| | | { |
| | | parent::checkPermission($request); |
| | | $context = $request->get_param('context') ?? 'user'; |
| | | $user_id = $request->get_param('user_id'); |
| | | |
| | | // Admin context requires manage_options |
| | | if ($context === 'admin') { |
| | | return current_user_can('manage_options'); |
| | | } |
| | | |
| | | // User context |
| | | if (!is_user_logged_in()) { |
| | | return false; |
| | | } |
| | | |
| | | $current_user_id = get_current_user_id(); |
| | | |
| | | // If user_id provided, verify it matches current user |
| | | // OR current user is admin |
| | | if ($user_id && $user_id != $current_user_id) { |
| | | return current_user_can('manage_options'); |
| | | } |
| | | |
| | | return true; |
| | | Route::for('integrations') |
| | | ->post([$this, 'handleAction']) |
| | | ->args([ |
| | | 'service' => 'string|required|enum:'.implode(',',JVB()->getAvailableServices()), |
| | | 'action' => 'string|required', |
| | | 'user_id' => 'int', |
| | | 'context' => 'string|enum:admin,user', |
| | | 'data' => 'array' |
| | | ]) |
| | | ->auth('user') |
| | | ->rateLimit(20) |
| | | ->register(); |
| | | Route::for('oath/connect') |
| | | ->post([$this, 'initiateOAuth']) |
| | | ->auth('user') |
| | | ->rateLimit(20) |
| | | ->args([ |
| | | 'service' => 'string|required', |
| | | 'user_id' => 'int', |
| | | 'return_url'=> 'url' |
| | | ]) |
| | | ->register(); |
| | | } |
| | | |
| | | /** |
| | |
| | | $service = $request->get_param('service'); |
| | | $action = $request->get_param('action'); |
| | | |
| | | // Get the integration instance |
| | | $userID = absint($request->get_param('user_id')); |
| | | if (!$this->userCheck($userID)) { |
| | | return new WP_REST_Response([ |
| | | 'success' => false, |
| | | 'message' => 'Invalid User' |
| | | ]); |
| | | } |
| | | |
| | | $theUserID = (user_can($userID, 'manage_options')) ? null : $userID; |
| | | $theUserID = (user_can($request->get_param('user'), 'manage_options')) ? null : $request->get_param('user'); |
| | | $integration = JVB()->connect($service, $theUserID); |
| | | |
| | | if (!$integration) { |
| | | return new WP_REST_Response([ |
| | | 'success' => false, |
| | | 'message' => 'Service not found' |
| | | ], 404); |
| | | return $this->validationError(['message'=>'Invalid service']); |
| | | } |
| | | |
| | | |
| | | $integration->getCredentials(); |
| | | |
| | | // Handle the action |
| | | try { |
| | | // Get data parameter - DON'T convert empty array to null |
| | | $data = $request->get_param('data'); |
| | | |
| | | // Only set to null if it's truly empty or not provided |
| | | if (!is_array($data) && empty($data)) { |
| | | $data = null; |
| | | } |
| | | |
| | | error_log('[IntegrationsRoutes] Calling processAction with data: ' . print_r($data, true)); |
| | | |
| | | $result = $integration->processAction($action, $data); |
| | | |
| | | return new WP_REST_Response($result, 200); |
| | | return $this->success($result); |
| | | |
| | | } catch (Exception $e) { |
| | | return new WP_REST_Response([ |
| | | 'success' => false, |
| | | 'message' => $e->getMessage() |
| | | ], 400); |
| | | return $this->error($e->getMessage()); |
| | | } |
| | | } |
| | | |
| | | public function initiateOAuth(WP_REST_Request $request): WP_REST_Response |
| | | { |
| | | $service = $request->get_param('service'); |
| | | $user_id = $request->get_param('user_id') ?: get_current_user_id(); |
| | | $user_id = $request->get_param('user_id'); |
| | | $return_url = $request->get_param('return_url'); |
| | | |
| | | $integration = JVB()->connect($service, $user_id); |
| | | |
| | | if (!$integration || !$integration->isOAuthService) { |
| | | return new WP_REST_Response([ |
| | | 'success' => false, |
| | | 'message' => 'Invalid OAuth service' |
| | | ], 400); |
| | | return $this->validationError(['message'=>'Invalid service']); |
| | | } |
| | | |
| | | $auth_url = $integration->getOAuthUrl($return_url); |
| | | |
| | | if ($auth_url) { |
| | | return new WP_REST_Response([ |
| | | 'success' => true, |
| | | 'auth_url' => $auth_url, |
| | | 'popup' => true |
| | | ], 200); |
| | | return $this->success($auth_url); |
| | | } |
| | | |
| | | return new WP_REST_Response([ |
| | | 'success' => false, |
| | | 'message' => 'Failed to generate authorization URL' |
| | | ], 400); |
| | | } |
| | | |
| | | /** |
| | | * Handle OAuth callback from external service |
| | | */ |
| | | public function handleOAuthCallback(WP_REST_Request $request): WP_REST_Response |
| | | { |
| | | $service = $request->get_param('service'); |
| | | $code = $request->get_param('code'); |
| | | $state = $request->get_param('state'); |
| | | $error = $request->get_param('error'); |
| | | |
| | | error_log('OAuth Callback - Service: ' . $request->get_param('service')); |
| | | error_log('OAuth Callback - Code: ' . $request->get_param('code')); |
| | | error_log('OAuth Callback - State: ' . $request->get_param('state')); |
| | | error_log('OAuth Callback - Error: ' . $request->get_param('error')); |
| | | |
| | | |
| | | $state_parts = explode('|', $state); |
| | | $state_key = $state_parts[0] ?? ''; |
| | | $user_id = intval($state_parts[1] ?? 0); |
| | | $user_id = ($user_id === 0) ? null : $user_id; |
| | | $return_url = isset($state_parts[2]) ? base64_decode($state_parts[2]) : admin_url('admin.php?page=jvb-integrations'); |
| | | |
| | | |
| | | $state_data = get_transient('oauth_state_' . $state_key); |
| | | error_log('State Data: '.print_r($state_data, true)); |
| | | if (!$state_data || $state_data['service'] !== $service) { |
| | | wp_die('Invalid state parameter', 'OAuth Error'); |
| | | } |
| | | |
| | | // Delete the transient to prevent reuse |
| | | delete_transient('oauth_state_' . $state_key); |
| | | error_log('Return URL: '.print_r($return_url, true)); |
| | | // Handle error from OAuth provider |
| | | if ($error) { |
| | | $error_description = $request->get_param('error_description') ?? 'Authorization denied'; |
| | | |
| | | wp_redirect(add_query_arg([ |
| | | 'page' => 'jvb-integrations', |
| | | 'error' => 'OAuth authorization denied: ' . $error_description |
| | | ], $return_url)); |
| | | exit; |
| | | } |
| | | |
| | | // Get integration instance |
| | | error_log('User ID: '.print_r($user_id, true)); |
| | | error_log('Service: '.print_r($service, true)); |
| | | $integration = JVB()->connect($service, $user_id); |
| | | |
| | | if (!$integration) { |
| | | wp_die('Invalid service: ' . esc_html($service), 'OAuth Error'); |
| | | } |
| | | |
| | | |
| | | // Exchange code for tokens |
| | | $result = $integration->handleOAuthCode($code, $state); |
| | | |
| | | // Redirect back with result |
| | | if ($result['success']) { |
| | | wp_redirect(add_query_arg([ |
| | | 'page' => 'jvb-integrations', |
| | | 'success' => 'Successfully connected to ' . $integration->title |
| | | ], $return_url)); |
| | | } else { |
| | | // Handle failure |
| | | $error_message = $result['message'] ?? 'Failed to complete OAuth authorization'; |
| | | |
| | | wp_redirect(add_query_arg([ |
| | | 'page' => 'jvb-integrations', |
| | | 'error' => $error_message |
| | | ], $return_url)); |
| | | } |
| | | exit; |
| | | return $this->error('Failed to generate authorization URL'); |
| | | } |
| | | } |