fix permission check for items considering collection #241

This commit is contained in:
leogermani 2019-07-16 18:06:02 -03:00
parent 8234540ec8
commit f30365c9b9
3 changed files with 139 additions and 5 deletions

View File

@ -27,6 +27,7 @@ class Items extends Repository {
add_filter( 'posts_where', array( &$this, 'content_in_posts_where' ), 10, 2 );
add_filter( 'comments_open', [$this, 'hook_comments_open'], 10, 2);
add_action( 'tainacan-api-item-updated', array( &$this, 'hook_api_updated_item' ), 10, 2 );
add_filter( 'map_meta_cap', array( $this, 'map_meta_cap' ), 10, 4 );
}
public function get_map() {
@ -552,4 +553,82 @@ class Items extends Repository {
return $open_comment;
}
/**
* Filter to handle special permissions
*
* @see https://developer.wordpress.org/reference/hooks/map_meta_cap/
*
*/
public function map_meta_cap( $caps, $cap, $user_id, $args ) {
// Filters meta caps edit_tainacan-collection and check if user is moderator
if ( $cap == 'read_post' && is_array( $args ) && array_key_exists( 0, $args ) ) {
$entity = $args[0];
if ( is_numeric( $entity ) || $entity instanceof Entities\Item ) {
if ( is_numeric( $entity ) ) {
$entity = $this->fetch( (int) $entity );
}
if ( $entity instanceof Entities\Item ) {
$collection = $entity->get_collection();
if ( $collection instanceof Entities\Collection ) {
$status_obj = get_post_status_object( $collection->get_status() );
if ( ! $status_obj->public ) {
$caps[] = $entity->get_capabilities()->read_private_posts;
}
}
}
}
}
return $caps;
}
/**
* Check if $user can read the item
*
* @param Entities\Entity $entity
* @param int|\WP_User|null $user default is null for the current user
*
* @return boolean
* @throws \Exception
*/
public function can_read( Entities\Entity $entity, $user = null ) {
if ( ! $entity instanceof Entities\Item) {
throw new InvalidArgumentException('Items::can_read() expects an Item entity as the first parameter');
}
$can_read = parent::can_read($entity, $user);
if ( $can_read ) {
$collection = $entity->get_collection();
$status_obj = get_post_status_object( $collection->get_status() );
if ( $status_obj->public ) {
return $can_read;
}
}
if ( is_null( $user ) ) {
return false;
} elseif ( is_object( $user ) ) {
$user = $user->ID;
}
$entity_cap = $entity->get_capabilities();
return user_can( $user, $entity_cap->read_private_posts, $entity->get_id() );
}
}

View File

@ -693,7 +693,7 @@ abstract class Repository {
* @return boolean
* @throws \Exception
*/
public function can_read( $entity, $user = null ) {
public function can_read( Entities\Entity $entity, $user = null ) {
if ( is_null( $user ) ) {
$user = get_current_user_id();
@ -716,7 +716,7 @@ abstract class Repository {
return false;
}
return user_can( $user, $entity_cap->read, $entity->get_id() );
return user_can( $user, $entity_cap->read_post, $entity->get_id() );
}
/**

View File

@ -24,6 +24,7 @@ class Permissions extends TAINACAN_UnitTestCase {
array(
'name' => 'testePerms',
'description' => 'adasdasdsa',
'status' => 'publish'
),
true
);
@ -63,10 +64,11 @@ class Permissions extends TAINACAN_UnitTestCase {
true
);
$this->assertTrue(user_can($new_admin_user, $collection->cap->read_post, $collection->get_id()), 'admin should be able read private collection');
$this->assertTrue(user_can($new_admin_user, $collection->cap->read_post, $privateCollection->get_id()), 'admin should be able read private collection');
// subsciber should not be able to
$this->assertFalse(user_can($new_user, $collection->cap->read_post, $collection->get_id()), 'subscriber should not be able read private collection');
$x = user_can($new_user, $collection->cap->read_post, $collection->get_id());
$this->assertFalse(user_can($new_user, $collection->cap->read_post, $privateCollection->get_id()), 'subscriber should not be able read private collection');
}
/**
@ -205,4 +207,57 @@ class Permissions extends TAINACAN_UnitTestCase {
}
function test_read_item() {
$ItemRepo = \Tainacan\Repositories\Items::get_instance();
$ColRepo = \Tainacan\Repositories\Collections::get_instance();
$collection = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'teste1',
'description' => 'adasdasdsa',
'status' => 'publish'
),
true
);
$item = $this->tainacan_entity_factory->create_entity(
'item',
array(
'title' => 'testeItem',
'collection' => $collection,
'status' => 'publish'
),
true
);
$subscriber = $this->factory()->user->create(array( 'role' => 'subscriber' ));
wp_set_current_user($subscriber);
wp_logout();
$this->assertTrue($item->can_read());
$item->set_status('private');
$item->validate();
$item = $ItemRepo->insert($item);
$this->assertFalse($item->can_read());
$item->set_status('publish');
$item->validate();
$item = $ItemRepo->insert($item);
$this->assertTrue($item->can_read());
$collection->set_status('private');
$collection->validate();
$collection = $ColRepo->insert($collection);
$this->assertFalse($item->can_read());
}
}