Skip to content
This repository has been archived by the owner on Jan 13, 2022. It is now read-only.

Commit

Permalink
Merge pull request #40 from WP-API/permissions
Browse files Browse the repository at this point in the history
Add permission check
  • Loading branch information
spacedmonkey authored Jan 10, 2020
2 parents f6b19a0 + e257064 commit 2916cdc
Show file tree
Hide file tree
Showing 4 changed files with 207 additions and 0 deletions.
35 changes: 35 additions & 0 deletions lib/class-wp-rest-menu-items-controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,41 @@ protected function get_nav_menu_item( $id ) {
return $nav_item;
}

/**
* Checks if a given request has access to read a menu item if they have access to edit them.
*
* @param WP_REST_Request $request Full details about the request.
* @return bool|WP_Error True if the request has read access for the item, WP_Error object otherwise.
*/
public function get_item_permissions_check( $request ) {
$post = $this->get_post( $request['id'] );
if ( is_wp_error( $post ) ) {
return $post;
}
if ( $post && ! $this->check_update_permission( $post ) ) {
return new WP_Error( 'rest_cannot_view', __( 'Sorry, you cannot view this menu item, unless you have access to permission edit it. ' ), array( 'status' => rest_authorization_required_code() ) );
}

return parent::get_item_permissions_check( $request );
}

/**
* Checks if a given request has access to read menu items if they have access to edit them.
*
* @param WP_REST_Request $request Full details about the request.
* @return true|WP_Error True if the request has read access, WP_Error object otherwise.
*/
public function get_items_permissions_check( $request ) {
$post_type = get_post_type_object( $this->post_type );
if ( ! current_user_can( $post_type->cap->edit_posts ) ) {
if ( 'edit' === $request['context'] ) {
return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to edit posts in this post type.' ), array( 'status' => rest_authorization_required_code() ) );
}
return new WP_Error( 'rest_cannot_view', __( 'Sorry, you cannot view these menu items, unless you have access to permission edit them. ' ), array( 'status' => rest_authorization_required_code() ) );
}
return true;
}

/**
* Creates a single post.
*
Expand Down
40 changes: 40 additions & 0 deletions lib/class-wp-rest-menus-controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,46 @@
*/
class WP_REST_Menus_Controller extends WP_REST_Terms_Controller {

/**
* Checks if a request has access to read terms in the specified taxonomy.
*
* @param WP_REST_Request $request Full details about the request.
* @return bool|WP_Error True if the request has read access, otherwise false or WP_Error object.
*/
public function get_items_permissions_check( $request ) {
$tax_obj = get_taxonomy( $this->taxonomy );
if ( ! $tax_obj || ! $this->check_is_taxonomy_allowed( $this->taxonomy ) ) {
return false;
}
if ( ! current_user_can( $tax_obj->cap->edit_terms ) ) {
if ( 'edit' === $request['context'] ) {
return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to edit terms in this taxonomy.' ), array( 'status' => rest_authorization_required_code() ) );
}
return new WP_Error( 'rest_cannot_view', __( 'Sorry, you cannot view these menus, unless you have access to permission edit them. ' ), array( 'status' => rest_authorization_required_code() ) );
}
return true;
}

/**
* Checks if a request has access to read or edit the specified menu.
*
* @param WP_REST_Request $request Full details about the request.
* @return bool|WP_Error True if the request has read access for the item, otherwise false or WP_Error object.
*/
public function get_item_permissions_check( $request ) {
$term = $this->get_term( $request['id'] );
if ( is_wp_error( $term ) ) {
return $term;
}
if ( ! current_user_can( 'edit_term', $term->term_id ) ) {
if ( 'edit' === $request['context'] ) {
return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to edit this term.' ), array( 'status' => rest_authorization_required_code() ) );
}
return new WP_Error( 'rest_cannot_view', __( 'Sorry, you cannot view this menu, unless you have access to permission edit it. ' ), array( 'status' => rest_authorization_required_code() ) );
}
return true;
}

/**
* Get the term, if the ID is valid.
*
Expand Down
76 changes: 76 additions & 0 deletions tests/test-rest-nav-menu-items-controller.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,32 @@
<?php

class WP_Test_REST_Nav_Menu_Items_Controller extends WP_Test_REST_Controller_Testcase {
/**
* @var int
*/
public $menu_id;

protected static $admin_id;

protected static $subscriber_id;

public static function wpSetUpBeforeClass( $factory ) {
self::$admin_id = $factory->user->create(
array(
'role' => 'administrator',
)
);
self::$subscriber_id = $factory->user->create(
array(
'role' => 'subscriber',
)
);
}

function setUp() {
parent::setUp();
$this->menu_id = wp_create_nav_menu( rand_str() );
}

public function test_register_routes() {
}
Expand Down Expand Up @@ -28,4 +54,54 @@ public function test_prepare_item() {

public function test_get_item_schema() {
}

public function test_get_items_no_permission() {
wp_set_current_user( 0 );
$request = new WP_REST_Request( 'GET', '/wp/v2/menu-items' );
$response = rest_get_server()->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_view', $response, 401 );
}

public function test_get_item_no_permission() {
$post_id = self::factory()->post->create();
$menu_item_id = wp_update_nav_menu_item(
$this->menu_id,
0,
array(
'menu-item-type' => 'post_type',
'menu-item-object' => 'post',
'menu-item-object-id' => $post_id,
'menu-item-status' => 'publish',
)
);
wp_set_current_user( 0 );
$request = new WP_REST_Request( 'GET', '/wp/v2/menu-items/' . $menu_item_id );
$response = rest_get_server()->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_view', $response, 401 );
}

public function test_get_items_wrong_permission() {
wp_set_current_user( self::$subscriber_id );
$request = new WP_REST_Request( 'GET', '/wp/v2/menu-items' );
$response = rest_get_server()->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_view', $response, 403 );
}

public function test_get_item_wrong_permission() {
$post_id = self::factory()->post->create();
$menu_item_id = wp_update_nav_menu_item(
$this->menu_id,
0,
array(
'menu-item-type' => 'post_type',
'menu-item-object' => 'post',
'menu-item-object-id' => $post_id,
'menu-item-status' => 'publish',
)
);
wp_set_current_user( self::$subscriber_id );
$request = new WP_REST_Request( 'GET', '/wp/v2/menu-items/' . $menu_item_id );
$response = rest_get_server()->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_view', $response, 403 );
}
}
56 changes: 56 additions & 0 deletions tests/test-rest-nav-menus-controller.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,32 @@
<?php

class WP_Test_REST_Nav_Menus_Controller extends WP_Test_REST_Controller_Testcase {
/**
* @var int
*/
public $menu_id;

protected static $admin_id;

protected static $subscriber_id;

public static function wpSetUpBeforeClass( $factory ) {
self::$admin_id = $factory->user->create(
array(
'role' => 'administrator',
)
);
self::$subscriber_id = $factory->user->create(
array(
'role' => 'subscriber',
)
);
}

function setUp() {
parent::setUp();
$this->menu_id = wp_create_nav_menu( rand_str() );
}

public function test_register_routes() {
}
Expand Down Expand Up @@ -30,6 +56,8 @@ public function test_get_item_schema() {
}

public function test_get_item_links() {
wp_set_current_user( self::$admin_id );

$nav_menu_id = wp_update_nav_menu_object(
0,
array(
Expand All @@ -52,4 +80,32 @@ public function test_get_item_links() {
$this->assertEquals( $location_url, $links['https://api.w.org/menu-location'][0]['href'] );
}

public function test_get_items_no_permission() {
wp_set_current_user( 0 );
$request = new WP_REST_Request( 'GET', '/wp/v2/menus' );
$response = rest_get_server()->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_view', $response, 401 );
}

public function test_get_item_no_permission() {
wp_set_current_user( 0 );
$request = new WP_REST_Request( 'GET', '/wp/v2/menus/' . $this->menu_id );
$response = rest_get_server()->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_view', $response, 401 );
}

public function test_get_items_wrong_permission() {
wp_set_current_user( self::$subscriber_id );
$request = new WP_REST_Request( 'GET', '/wp/v2/menus' );
$response = rest_get_server()->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_view', $response, 403 );
}

public function test_get_item_wrong_permission() {
wp_set_current_user( self::$subscriber_id );
$request = new WP_REST_Request( 'GET', '/wp/v2/menus/' . $this->menu_id );
$response = rest_get_server()->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_view', $response, 403 );
}

}

0 comments on commit 2916cdc

Please sign in to comment.