| @@ -466,20 +466,8 @@ | ||
| 466 | 466 | } |
| 467 | 467 | |
| 468 | 468 | return false; |
| 469 | 469 | } |
| 470 | - public static function remove_old_notice(){ | |
| 471 | - global $wp_filter; | |
| 472 | - if( isset( $wp_filter['admin_notices']->callbacks[10] ) && is_array( $wp_filter['admin_notices']->callbacks[10] ) ) { | |
| 473 | - foreach( $wp_filter['admin_notices']->callbacks[10] as $hash => $callbacks ) { | |
| 474 | - if( is_array( $callbacks['function'] ) && ! empty( $callbacks['function'][0] ) && is_object( $callbacks['function'][0] ) && $callbacks['function'][0] instanceof \NotificationX_Licensing ) { | |
| 475 | - remove_action( 'admin_notices', $hash ); | |
| 476 | - break; | |
| 477 | - } | |
| 478 | - } | |
| 479 | - } | |
| 480 | - } | |
| 481 | - | |
| 482 | 470 | public static function remote_get($url, $args = array(), $raw = false, $assoc = null) { |
| 483 | 471 | $defaults = array( |
| 484 | 472 | 'timeout' => 20, |
| 485 | 473 | 'redirection' => 5, |
| @@ -1392,8 +1380,45 @@ | ||
| 1392 | 1380 | return strpos(strtolower($name), $search) !== false; |
| 1393 | 1381 | }); |
| 1394 | 1382 | } |
| 1395 | 1383 | return $countries; |
| 1384 | + } | |
| 1385 | + | |
| 1386 | + | |
| 1387 | + /** | |
| 1388 | + * Delete a design document that NotificationX itself owns. | |
| 1389 | + * | |
| 1390 | + * The ID reaching the callers of this method arrives in a REST payload, so | |
| 1391 | + * it is attacker-controlled. Without a post-type check, any user holding | |
| 1392 | + * `edit_notificationx` could pass an arbitrary ID and force-delete any post | |
| 1393 | + * on the site -- pages, products, orders -- with no trash to recover from. | |
| 1394 | + * Only documents of a post type NotificationX creates may be removed here. | |
| 1395 | + * | |
| 1396 | + * A `current_user_can( 'delete_post' )` check is deliberately NOT applied. | |
| 1397 | + * These post types register with `capability_type => 'post'`, so that meta | |
| 1398 | + * cap resolves to the primitive `delete_posts`. A custom role delegated only | |
| 1399 | + * "Who Can Create Notification?" does not hold `delete_posts`, and gating on | |
| 1400 | + * it would stop that role from removing its own designs -- breaking exactly | |
| 1401 | + * the delegated workflow this boundary exists to support. Actor authority is | |
| 1402 | + * already established by the route's `edit_notificationx` permission | |
| 1403 | + * callback; what was missing, and what this restores, is object authority. | |
| 1404 | + * | |
| 1405 | + * @param int|string $post_id Candidate post ID, untrusted. | |
| 1406 | + * @param string $expected_type Post type NotificationX owns. | |
| 1407 | + * @return bool True when a post was deleted. | |
| 1408 | + */ | |
| 1409 | + public static function delete_owned_post( $post_id, $expected_type ) { | |
| 1410 | + $post_id = absint( $post_id ); | |
| 1411 | + if ( ! $post_id ) { | |
| 1412 | + return false; | |
| 1413 | + } | |
| 1414 | + | |
| 1415 | + $post = get_post( $post_id ); | |
| 1416 | + if ( ! $post || $expected_type !== $post->post_type ) { | |
| 1417 | + return false; | |
| 1418 | + } | |
| 1419 | + | |
| 1420 | + return (bool) wp_delete_post( $post_id, true ); | |
| 1396 | 1421 | } |
| 1397 | 1422 | |
| 1398 | 1423 | |
| 1399 | 1424 | } |