| @@ -221,8 +221,19 @@ | ||
| 221 | 221 | */ |
| 222 | 222 | public function ajax_dismiss_notice() { |
| 223 | 223 | check_ajax_referer('metasync_review_notice', 'nonce'); |
| 224 | 224 | |
| 225 | + // The flag is site-wide, so only admins may change it. The nonce is | |
| 226 | + // CSRF protection, not authorization. | |
| 227 | + if (!current_user_can('manage_options')) { | |
| 228 | + wp_send_json_error(['message' => 'Insufficient permissions.']); | |
| 229 | + // The return is unreachable in WordPress (wp_send_json_error | |
| 230 | + // terminates the request) but keeps the handler safe under the | |
| 231 | + // non-terminating stubs the unit tests run with. | |
| 232 | + // @phpstan-ignore-next-line deadCode.unreachable | |
| 233 | + return; | |
| 234 | + } | |
| 235 | + | |
| 225 | 236 | update_option('metasync_review_notice_dismissed', true); |
| 226 | 237 | wp_send_json_success(['message' => 'Notice dismissed']); |
| 227 | 238 | } |
| 228 | 239 | |
| @@ -230,8 +241,15 @@ | ||
| 230 | 241 | * AJAX handler for "remind me later" |
| 231 | 242 | */ |
| 232 | 243 | public function ajax_remind_later() { |
| 233 | 244 | check_ajax_referer('metasync_review_notice', 'nonce'); |
| 245 | + | |
| 246 | + if (!current_user_can('manage_options')) { | |
| 247 | + wp_send_json_error(['message' => 'Insufficient permissions.']); | |
| 248 | + // Same as above: defensive under test stubs, unreachable in WordPress. | |
| 249 | + // @phpstan-ignore-next-line deadCode.unreachable | |
| 250 | + return; | |
| 251 | + } | |
| 234 | 252 | |
| 235 | 253 | $remind_at = time() + (self::REMIND_LATER_DAYS * DAY_IN_SECONDS); |
| 236 | 254 | update_option('metasync_review_notice_remind_later', $remind_at); |
| 237 | 255 | wp_send_json_success(['message' => 'Reminder set']); |