This repository has been archived by the owner on Jan 11, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 18
/
PermissionsCriterionHandler.php
166 lines (153 loc) · 6.31 KB
/
PermissionsCriterionHandler.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
<?php
/**
* File containing the eZ\Publish\Core\Repository\PermissionsCriterionHandler class.
*
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
* @version //autogentag//
*/
namespace eZ\Publish\Core\Repository;
use eZ\Publish\API\Repository\Values\Content\Query\Criterion;
use eZ\Publish\API\Repository\Values\Content\Query\Criterion\LogicalAnd;
use eZ\Publish\API\Repository\Values\Content\Query\Criterion\LogicalOr;
use eZ\Publish\API\Repository\Values\User\Limitation;
use eZ\Publish\API\Repository\Repository as RepositoryInterface;
use RuntimeException;
/**
* Handler for permissions Criterion
*
* @package eZ\Publish\Core\Repository
*/
class PermissionsCriterionHandler
{
/**
* Constructor
*
* @param \eZ\Publish\API\Repository\Repository $repository
*/
public function __construct( RepositoryInterface $repository )
{
$this->repository = $repository;
}
/**
* Adds content, read Permission criteria if needed and return false if no access at all
*
* @access private Temporarily made accessible until Location service stops using searchHandler()
* @uses getPermissionsCriterion()
*
* @param \eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterion
*
* @return boolean|\eZ\Publish\API\Repository\Values\Content\Query\Criterion
*/
public function addPermissionsCriterion( Criterion &$criterion )
{
$permissionCriterion = $this->getPermissionsCriterion();
if ( $permissionCriterion === true || $permissionCriterion === false )
{
return $permissionCriterion;
}
// Merge with original $criterion
if ( $criterion instanceof LogicalAnd )
{
$criterion->criteria[] = $permissionCriterion;
}
else
{
$criterion = new LogicalAnd(
array(
$criterion,
$permissionCriterion
)
);
}
return true;
}
/**
* Get content-read Permission criteria if needed and return false if no access at all
*
* @uses \eZ\Publish\API\Repository::hasAccess()
* @throws \RuntimeException If empty array of limitations are provided from hasAccess()
*
* @param string $module
* @param string $function
*
* @return boolean|\eZ\Publish\API\Repository\Values\Content\Query\Criterion
*/
public function getPermissionsCriterion( $module = 'content', $function = 'read' )
{
$permissionSets = $this->repository->hasAccess( $module, $function );
if ( $permissionSets === false || $permissionSets === true )
{
return $permissionSets;
}
if ( empty( $permissionSets ) )
throw new RuntimeException( "Got an empty array of limitations from hasAccess( '{$module}', '{$function}' )" );
/**
* RoleAssignment is a OR condition, so is policy, while limitations is a AND condition
*
* If RoleAssignment has limitation then policy OR conditions are wrapped in a AND condition with the
* role limitation, otherwise it will be merged into RoleAssignment's OR condition.
*/
$currentUser = $this->repository->getCurrentUser();
$roleAssignmentOrCriteria = array();
$roleService = $this->repository->getRoleService();
foreach ( $permissionSets as $permissionSet )
{
// $permissionSet is a RoleAssignment, but in the form of role limitation & role policies hash
$policyOrCriteria = array();
/**
* @var \eZ\Publish\API\Repository\Values\User\Policy $policy
*/
foreach ( $permissionSet['policies'] as $policy )
{
$limitations = $policy->getLimitations();
if ( $limitations === '*' || empty( $limitations ) )
continue;
$limitationsAndCriteria = array();
foreach ( $limitations as $limitation )
{
$type = $roleService->getLimitationType( $limitation->getIdentifier() );
$limitationsAndCriteria[] = $type->getCriterion( $limitation, $currentUser );
}
$policyOrCriteria[] = isset( $limitationsAndCriteria[1] ) ?
new LogicalAnd( $limitationsAndCriteria ) :
$limitationsAndCriteria[0];
}
/**
* Apply role limitations if there is one
* @var \eZ\Publish\API\Repository\Values\User\Limitation[] $permissionSet
*/
if ( $permissionSet['limitation'] instanceof Limitation )
{
// We need to match both the limitation AND *one* of the policies, aka; roleLimit AND policies(OR)
$type = $roleService->getLimitationType( $permissionSet['limitation']->getIdentifier() );
if ( !empty( $policyOrCriteria ) )
{
$roleAssignmentOrCriteria[] = new LogicalAnd(
array(
$type->getCriterion( $permissionSet['limitation'], $currentUser ),
isset( $policyOrCriteria[1] ) ? new LogicalOr( $policyOrCriteria ) : $policyOrCriteria[0]
)
);
}
else
{
$roleAssignmentOrCriteria[] = $type->getCriterion( $permissionSet['limitation'], $currentUser );
}
}
// Otherwise merge $policyOrCriteria into $roleAssignmentOrCriteria
else if ( !empty( $policyOrCriteria ) )
{
// There is no role limitation, so any of the policies can globally match in the returned OR criteria
$roleAssignmentOrCriteria = empty( $roleAssignmentOrCriteria ) ?
$policyOrCriteria :
array_merge( $roleAssignmentOrCriteria, $policyOrCriteria );
}
}
if ( empty( $roleAssignmentOrCriteria ) )
return false;
return isset( $roleAssignmentOrCriteria[1] ) ?
new LogicalOr( $roleAssignmentOrCriteria ) :
$roleAssignmentOrCriteria[0];
}
}