WP_REST_Server::READABLE, 'callback' => [ $this, 'get_templates' ], 'permission_callback' => [ $this, 'get_permissions_check' ], ], ] ); register_rest_route( '100prints/v1', '/template/(?P[a-zA-Z0-9_-]+)', [ [ 'methods' => WP_REST_Server::READABLE, 'callback' => [ $this, 'get_template' ], 'permission_callback' => [ $this, 'verify_signature' ], ], ] ); } /** * Permission check callback. */ public function get_permissions_check( $request ) { return current_user_can( 'edit_posts' ); } /** * Verify pre-signed request signature. */ public function verify_signature( $request ) { $template_id = $request['id']; $expires = $request->get_param( 'expires' ); $signature = $request->get_param( 'sig' ); // If no signature is provided, fallback to capability check (for editor usage). if ( ! $expires || ! $signature ) { if ( current_user_can( 'edit_posts' ) ) { return true; } return new WP_Error( '100prints_unauthorized', 'Missing signature.', [ 'status' => 403 ] ); } if ( time() > (int) $expires ) { return new WP_Error( '100prints_expired', 'Request expired.', [ 'status' => 403 ] ); } $expected = hash_hmac( 'sha256', $template_id . '|' . $expires . '|fetch', wp_salt( 'auth' ) ); if ( ! hash_equals( $expected, $signature ) ) { return new WP_Error( '100prints_forbidden', 'Invalid signature.', [ 'status' => 403 ] ); } return true; } /** * Get all templates. */ public function get_templates( $request ) { $template_service = new Hundred_Prints_Template_Service(); $templates = $template_service->get_all_templates(); return rest_ensure_response( $templates ); } /** * Get a specific template by ID. */ public function get_template( $request ) { $id = $request['id']; $template_service = new Hundred_Prints_Template_Service(); $template = $template_service->get_template( $id ); if ( is_wp_error( $template ) ) { return $template; } if ( ! $template ) { return new WP_Error( '100prints_not_found', 'Template not found', [ 'status' => 404 ] ); } return rest_ensure_response( $template ); } }