Completed
Push — 6.7 ( 044712...96c013 )
by André
14:02
created

ObjectStateLimitationTest::addPolicyToNewRole()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 6

Duplication

Lines 9
Ratio 100 %

Importance

Changes 0
Metric Value
cc 2
eloc 6
nc 2
nop 4
dl 9
loc 9
rs 9.6666
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File containing the ObjectStateLimitationTest class.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 */
9
namespace eZ\Publish\API\Repository\Tests\Values\User\Limitation;
10
11
use eZ\Publish\API\Repository\Values\Content\Query;
12
use eZ\Publish\API\Repository\Values\Content\Query\Criterion;
13
use eZ\Publish\API\Repository\Values\ObjectState\ObjectStateGroup;
14
use eZ\Publish\API\Repository\Values\User\Limitation\ObjectStateLimitation;
15
use eZ\Publish\API\Repository\Values\User\RoleCreateStruct;
16
17
/**
18
 * Test case for the {@link \eZ\Publish\API\Repository\Values\User\Limitation\ObjectStateLimitation}
19
 * class.
20
 *
21
 * @see eZ\Publish\API\Repository\Values\User\Limitation
22
 * @see eZ\Publish\API\Repository\Values\User\Limitation\ObjectStateLimitation
23
 * @group integration
24
 * @group limitation
25
 */
26
class ObjectStateLimitationTest extends BaseLimitationTest
27
{
28
    /**
29
     * Tests a ObjectStateLimitation.
30
     *
31
     * @see eZ\Publish\API\Repository\Values\User\Limitation\ObjectStateLimitation
32
     *
33
     * @throws \ErrorException
34
     */
35 View Code Duplication
    public function testObjectStateLimitationAllow()
36
    {
37
        $repository = $this->getRepository();
38
        $notLockedState = $this->generateId('objectstate', 2);
39
40
        $contentService = $repository->getContentService();
41
        /* BEGIN: Use Case */
42
        $user = $this->createUserVersion1();
43
44
        $roleService = $repository->getRoleService();
45
46
        $role = $roleService->loadRoleByIdentifier('Editor');
47
48
        $removePolicy = null;
49
        foreach ($role->getPolicies() as $policy) {
50
            if ('content' != $policy->module || 'remove' != $policy->function) {
51
                continue;
52
            }
53
            $removePolicy = $policy;
54
            break;
55
        }
56
57
        if (null === $removePolicy) {
58
            throw new \ErrorException('No content:remove policy found.');
59
        }
60
61
        // Only allow deletion of content with default state
62
        $policyUpdate = $roleService->newPolicyUpdateStruct();
63
        $policyUpdate->addLimitation(
64
            new ObjectStateLimitation(
65
                array(
66
                    'limitationValues' => array(
67
                        $notLockedState,
68
                    ),
69
                )
70
            )
71
        );
72
        $roleService->updatePolicy($removePolicy, $policyUpdate);
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...Service::updatePolicy() has been deprecated with message: since 6.0, use {@link updatePolicyByRoleDraft()} instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
73
74
        // Allow user to create everything
75
        $policyCreate = $roleService->newPolicyCreateStruct('content', 'create');
76
        $roleService->addPolicy($role, $policyCreate);
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repository\RoleService::addPolicy() has been deprecated with message: since 6.0, use {@see addPolicyByRoleDraft}

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
77
78
        $roleService->assignRoleToUser($role, $user);
79
80
        $repository->setCurrentUser($user);
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...itory::setCurrentUser() has been deprecated with message: since 6.6, to be removed. Use PermissionResolver::setCurrentUserReference() instead. Sets the current user to the given $user.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
81
82
        $draft = $this->createWikiPageDraft();
83
84
        $contentService->deleteContent($draft->contentInfo);
85
        /* END: Use Case */
86
87
        $this->setExpectedException('\\eZ\\Publish\\API\\Repository\\Exceptions\\NotFoundException');
88
        $contentService->loadContent($draft->id);
89
    }
90
91
    /**
92
     * Tests a ObjectStateLimitation.
93
     *
94
     * @see eZ\Publish\API\Repository\Values\User\Limitation\ObjectStateLimitation
95
     *
96
     * @throws \ErrorException
97
     * @expectedException \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
98
     */
99
    public function testObjectStateLimitationForbid()
100
    {
101
        $repository = $this->getRepository();
102
        $lockedState = $this->generateId('objectstate', 1);
103
104
        $contentService = $repository->getContentService();
105
        /* BEGIN: Use Case */
106
        $user = $this->createUserVersion1();
107
108
        $roleService = $repository->getRoleService();
109
110
        $role = $roleService->loadRoleByIdentifier('Editor');
111
112
        $removePolicy = null;
113
        foreach ($role->getPolicies() as $policy) {
114
            if ('content' != $policy->module || 'remove' != $policy->function) {
115
                continue;
116
            }
117
            $removePolicy = $policy;
118
            break;
119
        }
120
121
        if (null === $removePolicy) {
122
            throw new \ErrorException('No content:remove policy found.');
123
        }
124
125
        // Only allow deletion of content with default state
126
        $policyUpdate = $roleService->newPolicyUpdateStruct();
127
        $policyUpdate->addLimitation(
128
            new ObjectStateLimitation(
129
                array(
130
                    'limitationValues' => array(
131
                        $lockedState,
132
                    ),
133
                )
134
            )
135
        );
136
        $roleService->updatePolicy($removePolicy, $policyUpdate);
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...Service::updatePolicy() has been deprecated with message: since 6.0, use {@link updatePolicyByRoleDraft()} instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
137
138
        // Allow user to create everything
139
        $policyCreate = $roleService->newPolicyCreateStruct('content', 'create');
140
        $roleService->addPolicy($role, $policyCreate);
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repository\RoleService::addPolicy() has been deprecated with message: since 6.0, use {@see addPolicyByRoleDraft}

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
141
142
        $roleService->assignRoleToUser($role, $user);
143
144
        $repository->setCurrentUser($user);
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...itory::setCurrentUser() has been deprecated with message: since 6.6, to be removed. Use PermissionResolver::setCurrentUserReference() instead. Sets the current user to the given $user.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
145
146
        $draft = $this->createWikiPageDraft();
147
148
        $contentService->deleteContent($draft->contentInfo);
149
        /* END: Use Case */
150
    }
151
152
    /**
153
     * Tests an ObjectStateLimitation.
154
     *
155
     * Checks if the action is correctly forbidden when using ObjectStateLimitation
156
     * with limitation values from two different StateGroups.
157
     *
158
     * @see \eZ\Publish\API\Repository\Values\User\Limitation\ObjectStateLimitation
159
     *
160
     * @throws \ErrorException
161
     * @expectedException \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
162
     * @expectedExceptionMessage 'remove' 'content'
163
     */
164
    public function testObjectStateLimitationForbidVariant()
165
    {
166
        $repository = $this->getRepository();
167
        $objectStateGroup = $this->createObjectStateGroup();
168
        $objectState = $this->createObjectState($objectStateGroup);
169
170
        $lockedState = $this->generateId('objectstate', 1);
171
        $defaultStateFromAnotherGroup = $this->generateId('objectstate', $objectState->id);
172
173
        $contentService = $repository->getContentService();
174
        /* BEGIN: Use Case */
175
        $user = $this->createUserVersion1();
176
177
        $roleService = $repository->getRoleService();
178
179
        $role = $roleService->loadRoleByIdentifier('Editor');
180
181
        $removePolicy = null;
182
        foreach ($role->getPolicies() as $policy) {
183
            if ('content' !== $policy->module || 'remove' !== $policy->function) {
184
                continue;
185
            }
186
            $removePolicy = $policy;
187
            break;
188
        }
189
190
        $this->assertNotNull($removePolicy);
191
192
        // Only allow deletion of content with locked state and the default state from another State Group
193
        $policyUpdate = $roleService->newPolicyUpdateStruct();
194
        $policyUpdate->addLimitation(
195
            new ObjectStateLimitation(
196
                [
197
                    'limitationValues' => [
198
                        $lockedState,
199
                        $defaultStateFromAnotherGroup,
200
                    ],
201
                ]
202
            )
203
        );
204
        $roleService->updatePolicy($removePolicy, $policyUpdate);
0 ignored issues
show
Bug introduced by
It seems like $removePolicy defined by null on line 181 can be null; however, eZ\Publish\API\Repositor...Service::updatePolicy() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...Service::updatePolicy() has been deprecated with message: since 6.0, use {@link updatePolicyByRoleDraft()} instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
205
206
        // Allow user to create everything
207
        $policyCreate = $roleService->newPolicyCreateStruct('content', 'create');
208
        $roleService->addPolicy($role, $policyCreate);
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repository\RoleService::addPolicy() has been deprecated with message: since 6.0, use {@see addPolicyByRoleDraft}

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
209
210
        $roleService->assignRoleToUser($role, $user);
211
212
        $repository->getPermissionResolver()->setCurrentUserReference($user);
213
214
        $draft = $this->createWikiPageDraft();
215
216
        $contentService->deleteContent($draft->contentInfo);
217
        /* END: Use Case */
218
    }
219
220
    /**
221
     * Create new State Group.
222
     *
223
     * @return \eZ\Publish\API\Repository\Values\ObjectState\ObjectStateGroup
224
     */
225
    private function createObjectStateGroup()
226
    {
227
        $objectStateService = $this->getRepository()->getObjectStateService();
228
229
        $objectStateGroupCreateStruct = $objectStateService->newObjectStateGroupCreateStruct('second_group');
230
        $objectStateGroupCreateStruct->defaultLanguageCode = 'eng-US';
231
        $objectStateGroupCreateStruct->names = ['eng-US' => 'Second Group'];
0 ignored issues
show
Documentation Bug introduced by
It seems like array('eng-US' => 'Second Group') of type array<string,string,{"eng-US":"string"}> is incompatible with the declared type array<integer,string> of property $names.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
232
233
        return $objectStateService->createObjectStateGroup($objectStateGroupCreateStruct);
234
    }
235
236
    /**
237
     * Create new State and assign it to the $objectStateGroup.
238
     *
239
     * @param \eZ\Publish\API\Repository\Values\ObjectState\ObjectStateGroup $objectStateGroup
240
     *
241
     * @return \eZ\Publish\API\Repository\Values\ObjectState\ObjectState
242
     */
243
    private function createObjectState(ObjectStateGroup $objectStateGroup)
244
    {
245
        $objectStateService = $this->getRepository()->getObjectStateService();
246
247
        $objectStateCreateStruct = $objectStateService->newObjectStateCreateStruct('default_state');
248
        $objectStateCreateStruct->defaultLanguageCode = 'eng-US';
249
        $objectStateCreateStruct->names = ['eng-US' => 'Default state'];
0 ignored issues
show
Documentation Bug introduced by
It seems like array('eng-US' => 'Default state') of type array<string,string,{"eng-US":"string"}> is incompatible with the declared type array<integer,string> of property $names.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
250
251
        return $objectStateService->createObjectState($objectStateGroup, $objectStateCreateStruct);
252
    }
253
254
    /**
255
     * Tests an ObjectStateLimitation.
256
     *
257
     * Checks if the search results are correctly filtered when using ObjectStateLimitation
258
     * with limitation values from two different StateGroups.
259
     *
260
     * @see \eZ\Publish\API\Repository\Values\User\Limitation\ObjectStateLimitation
261
     */
262
    public function testObjectStateLimitationSearch()
263
    {
264
        $repository = $this->getRepository();
265
        $objectStateGroup = $this->createObjectStateGroup();
266
        $objectState = $this->createObjectState($objectStateGroup);
267
268
        $lockedState = $this->generateId('objectstate', 1);
269
        $defaultStateFromAnotherGroup = $this->generateId('objectstate', $objectState->id);
270
271
        $roleService = $repository->getRoleService();
272
        $roleName = 'role_with_object_state_limitation';
273
        $roleCreateStruct = $roleService->newRoleCreateStruct($roleName);
274
        $this->addPolicyToNewRole($roleCreateStruct, 'content', 'read', [
275
            new ObjectStateLimitation([
276
                'limitationValues' => [$lockedState, $defaultStateFromAnotherGroup],
277
            ]),
278
        ]);
279
        $roleService->publishRoleDraft(
280
            $roleService->createRole($roleCreateStruct)
281
        );
282
283
        $permissionResolver = $repository->getPermissionResolver();
284
        $user = $this->createCustomUserVersion1('Test group', $roleName);
285
        $adminUser = $permissionResolver->getCurrentUserReference();
286
287
        $wikiPage = $this->createWikiPage();
288
289
        $permissionResolver->setCurrentUserReference($user);
290
291
        $query = new Query();
292
        $query->filter = new Criterion\MatchAll();
293
        $query->limit = 50;
294
295
        $this->refreshSearch($repository);
296
        $searchResultsBefore = $repository->getSearchService()->findContent($query);
297
298
        $permissionResolver->setCurrentUserReference($adminUser);
299
300
        //change the Object State to the one that doesn't match the Limitation
301
        $stateService = $repository->getObjectStateService();
302
        $stateService->setContentState(
303
            $wikiPage->contentInfo,
304
            $stateService->loadObjectStateGroup(2),
305
            $stateService->loadObjectState(2)
306
        );
307
308
        $permissionResolver->setCurrentUserReference($user);
309
310
        $this->refreshSearch($repository);
311
        $searchResultsAfter = $repository->getSearchService()->findContent($query);
312
313
        $this->assertEquals($searchResultsBefore->totalCount - 1, $searchResultsAfter->totalCount);
314
    }
315
316
    /**
317
     * Add policy to a new role.
318
     *
319
     * @param \eZ\Publish\API\Repository\Values\User\RoleCreateStruct $roleCreateStruct
320
     * @param string $module
321
     * @param string $function
322
     * @param \eZ\Publish\API\Repository\Values\User\Limitation[] $limitations
323
     */
324 View Code Duplication
    private function addPolicyToNewRole(RoleCreateStruct $roleCreateStruct, $module, $function, array $limitations)
325
    {
326
        $roleService = $this->getRepository()->getRoleService();
327
        $policyCreateStruct = $roleService->newPolicyCreateStruct($module, $function);
328
        foreach ($limitations as $limitation) {
329
            $policyCreateStruct->addLimitation($limitation);
330
        }
331
        $roleCreateStruct->addPolicy($policyCreateStruct);
332
    }
333
}
334