| @@ -163,15 +163,40 @@ | ||
| 163 | 163 | ); |
| 164 | 164 | } |
| 165 | 165 | |
| 166 | 166 | /** |
| 167 | - * Capability check. | |
| 167 | + * Capability check. Write requests (POST/PUT/PATCH/DELETE) additionally | |
| 168 | + * require a valid wp_rest nonce, matching Donors_API — these endpoints bulk | |
| 169 | + * import into custom tables, so the write boundary is pinned explicitly. | |
| 168 | 170 | * |
| 169 | - * @return bool | |
| 171 | + * @param \WP_REST_Request<array<string,mixed>>|null $request Current request. | |
| 172 | + * @return bool|\WP_Error | |
| 170 | 173 | * @since 1.0.0 |
| 171 | 174 | */ |
| 172 | - public function check_permissions() { | |
| 173 | - return current_user_can( 'manage_options' ); | |
| 175 | + public function check_permissions( $request = null ) { | |
| 176 | + if ( ! current_user_can( 'manage_options' ) ) { | |
| 177 | + return false; | |
| 178 | + } | |
| 179 | + | |
| 180 | + if ( $request instanceof \WP_REST_Request ) { | |
| 181 | + $method = strtoupper( $request->get_method() ); | |
| 182 | + if ( in_array( $method, [ 'POST', 'PUT', 'PATCH', 'DELETE' ], true ) ) { | |
| 183 | + $nonce = $request->get_header( 'X-WP-Nonce' ); | |
| 184 | + if ( empty( $nonce ) ) { | |
| 185 | + $nonce_param = $request->get_param( '_wpnonce' ); | |
| 186 | + $nonce = is_string( $nonce_param ) ? $nonce_param : ''; | |
| 187 | + } | |
| 188 | + if ( empty( $nonce ) || ! wp_verify_nonce( $nonce, 'wp_rest' ) ) { | |
| 189 | + return new \WP_Error( | |
| 190 | + 'rest_forbidden', | |
| 191 | + __( 'Invalid or missing nonce.', 'suredonation' ), | |
| 192 | + [ 'status' => 403 ] | |
| 193 | + ); | |
| 194 | + } | |
| 195 | + } | |
| 196 | + } | |
| 197 | + | |
| 198 | + return true; | |
| 174 | 199 | } |
| 175 | 200 | |
| 176 | 201 | /** |
| 177 | 202 | * GET /import/givewp/counts |