PluginProbe
Cookie Consent – GDPR & CCPA Cookie Banner & Consent Manager / 0.0.3
Cookie Consent – GDPR & CCPA Cookie Banner & Consent Manager v0.0.3
0.0.11 0.0.10 0.0.9 0.0.8 0.0.7 0.0.6 trunk 0.0.1 0.0.2 0.0.3 0.0.4 0.0.5
cookiez / modules / scanner / rest / scan-webhook.php

scan-webhook.php in Cookie Consent – GDPR & CCPA Cookie Banner & Consent Manager 0.0.3, at modules/scanner/rest/scan-webhook.php

102 lines 2.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Cookiez\Modules\Scanner\Rest;
4
5 use Cookiez\Classes\Logger;
6 use Cookiez\Classes\Services\Webhook_Token;
7 use Cookiez\Modules\Scanner\Classes\{
8 Route_Base,
9 Service\Exceptions\Scan_Service_Client_Exception,
10 Service\Exceptions\Scan_Transport_Exception,
11 };
12 use Cookiez\Modules\Scanner\Components\Scanner;
13 use Throwable;
14 use WP_REST_Request;
15 use WP_REST_Response;
16
17 if ( ! defined( 'ABSPATH' ) ) {
18 exit;
19 }
20
21 /**
22 * Class Scan_Webhook
23 * Receives scan final-state notifications posted by the external scanning
24 * service. Authentication is a per-site token embedded in the URL that the
25 * service stored at registration time; see Webhook_Token.
26 *
27 * The payload itself is treated as a push hint only — the handler pulls a
28 * fresh snapshot via GET /scans/{id} so a forged payload cannot corrupt
29 * local state.
30 */
31 class Scan_Webhook extends Route_Base {
32 public string $path = 'webhook';
33
34 /**
35 * Server-to-server endpoint — WP user auth does not apply. Token check
36 * lives in POST_permission_callback.
37 *
38 * @var bool
39 */
40 protected $auth = false;
41
42 public function get_methods(): array {
43 return [ 'POST' ];
44 }
45
46 public function get_name(): string {
47 return 'scan-webhook';
48 }
49
50 protected function sanitize_fields(): array {
51 return [];
52 }
53
54 /**
55 * Gate the webhook on a constant-time token match. Token is supplied as
56 * a query parameter because the service does not attach custom headers.
57 */
58 public function POST_permission_callback( WP_REST_Request $request ): bool {
59 $provided = (string) $request->get_param( 'token' );
60 $expected = Webhook_Token::get();
61
62 return '' !== $provided
63 && '' !== $expected
64 && hash_equals( $expected, $provided );
65 }
66
67 /**
68 * @return WP_REST_Response
69 */
70 public function POST(): WP_REST_Response {
71 $api_id = isset( $this->params['scanApiId'] ) ? (string) $this->params['scanApiId'] : '';
72 $status = isset( $this->params['status'] ) ? (string) $this->params['status'] : '';
73
74 if ( '' === $api_id || '' === $status ) {
75 return $this->respond_error_json( [
76 'message' => esc_html__( 'Malformed webhook payload', 'cookiez' ),
77 'code' => 'invalid_payload',
78 ], 400 );
79 }
80
81 try {
82 ( new Scanner() )->handle_webhook_call( $api_id );
83 } catch ( Scan_Transport_Exception $e ) {
84 return $this->respond_error_json( [
85 'message' => esc_html__( 'Reconciliation failed', 'cookiez' ),
86 'code' => 'reconciliation_failed',
87 ], 502 );
88 } catch ( Scan_Service_Client_Exception $ssce ) {
89 Logger::error( $ssce->getMessage() );
90 } catch ( Throwable $t ) {
91 Logger::error( $t->getMessage() );
92
93 return $this->respond_error_json( [
94 'message' => esc_html__( 'Internal error', 'cookiez' ),
95 'code' => 'internal_server_error',
96 ], 500 );
97 }
98
99 return $this->respond_success_json( [ 'ok' => true ] );
100 }
101 }
102