Completed
Push — master ( a5ee66...02276a )
by André
150:34 queued 126:19
created

PermissionTest::createRole()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 20
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 10
nc 2
nop 2
dl 0
loc 20
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
5
 * @license For full copyright and license information view LICENSE file distributed with this source code.
6
 */
7
namespace eZ\Publish\Core\Repository\Tests\Service\Mock;
8
9
use eZ\Publish\API\Repository\Repository;
10
use eZ\Publish\API\Repository\Values\User\Limitation;
11
use eZ\Publish\API\Repository\Values\ValueObject;
12
use eZ\Publish\Core\Repository\Helper\LimitationService;
13
use eZ\Publish\Core\Repository\Permission\PermissionResolver;
14
use eZ\Publish\Core\Repository\Values\User\UserReference;
15
use eZ\Publish\Core\Repository\Repository as CoreRepository;
16
use eZ\Publish\Core\Base\Exceptions\NotFound\LimitationNotFoundException;
17
use eZ\Publish\Core\Repository\Helper\RoleDomainMapper;
18
use eZ\Publish\Core\Repository\Tests\Service\Mock\Base as BaseServiceMockTest;
19
use eZ\Publish\SPI\Limitation\Type;
20
use eZ\Publish\SPI\Persistence\User\RoleAssignment;
21
use eZ\Publish\SPI\Persistence\User\Role;
22
use eZ\Publish\SPI\Persistence\User\Policy;
23
24
/**
25
 * Mock test case for PermissionResolver.
26
 *
27
 * @todo Move to "Tests/Permission/"
28
 */
29
class PermissionTest extends BaseServiceMockTest
30
{
31
    public function providerForTestHasAccessReturnsTrue()
32
    {
33
        return [
34
            [
35
                [
36
                    25 => $this->createRole(
37
                        [
38
                            ['dummy-module', 'dummy-function', 'dummy-limitation'],
39
                            ['dummy-module2', 'dummy-function2', 'dummy-limitation2'],
40
                        ],
41
                        25
42
                    ),
43
                    26 => $this->createRole(
44
                        [
45
                            ['*', 'dummy-function', 'dummy-limitation'],
46
                        ],
47
                        26
48
                    ),
49
                ],
50
                [
51
                    new RoleAssignment(
52
                        [
53
                            'roleId' => 25,
54
                        ]
55
                    ),
56
                    new RoleAssignment(
57
                        [
58
                            'roleId' => 26,
59
                        ]
60
                    ),
61
                ],
62
            ],
63
            [
64
                [
65
                    27 => $this->createRole(
66
                        [
67
                            ['dummy-module', '*', 'dummy-limitation'],
68
                        ],
69
                        27
70
                    ),
71
                ],
72
                [
73
                    new RoleAssignment(
74
                        [
75
                            'roleId' => 27,
76
                        ]
77
                    ),
78
                ],
79
            ],
80
            [
81
                [
82
                    28 => $this->createRole(
83
                        [
84
                            ['dummy-module', 'dummy-function', '*'],
85
                        ],
86
                        28
87
                    ),
88
                ],
89
                [
90
                    new RoleAssignment(
91
                        [
92
                            'roleId' => 28,
93
                        ]
94
                    ),
95
                ],
96
            ],
97
        ];
98
    }
99
100
    /**
101
     * Test for the hasAccess() method.
102
     *
103
     * @dataProvider providerForTestHasAccessReturnsTrue
104
     */
105 View Code Duplication
    public function testHasAccessReturnsTrue(array $roles, array $roleAssignments)
106
    {
107
        /** @var $userHandlerMock \PHPUnit\Framework\MockObject\MockObject */
108
        $userHandlerMock = $this->getPersistenceMock()->userHandler();
109
        $userReferenceMock = $this->getUserReferenceMock();
110
        $mockedService = $this->getPermissionResolverMock(null);
111
112
        $userReferenceMock
113
            ->expects($this->once())
114
            ->method('getUserId')
115
            ->will($this->returnValue(10));
116
117
        $userHandlerMock
118
            ->expects($this->once())
119
            ->method('loadRoleAssignmentsByGroupId')
120
            ->with($this->equalTo(10), $this->equalTo(true))
121
            ->will($this->returnValue($roleAssignments));
122
123
        foreach ($roleAssignments as $at => $roleAssignment) {
124
            $userHandlerMock
125
                ->expects($this->at($at + 1))
126
                ->method('loadRole')
127
                ->with($roleAssignment->roleId)
128
                ->will($this->returnValue($roles[$roleAssignment->roleId]));
129
        }
130
131
        $result = $mockedService->hasAccess('dummy-module', 'dummy-function');
132
133
        self::assertEquals(true, $result);
134
    }
135
136
    public function providerForTestHasAccessReturnsFalse()
137
    {
138
        return [
139
            [[], []],
140
            [
141
                [
142
                    29 => $this->createRole(
143
                        [
144
                            ['dummy-module', 'dummy-function', 'dummy-limitation'],
145
                        ],
146
                        29
147
                    ),
148
                ],
149
                [
150
                    new RoleAssignment(
151
                        [
152
                            'roleId' => 29,
153
                        ]
154
                    ),
155
                ],
156
            ],
157
            [
158
                [
159
                    30 => $this->createRole(
160
                        [
161
                            ['dummy-module', '*', 'dummy-limitation'],
162
                        ],
163
                        30
164
                    ),
165
                ],
166
                [
167
                    new RoleAssignment(
168
                        [
169
                            'roleId' => 30,
170
                        ]
171
                    ),
172
                ],
173
            ],
174
        ];
175
    }
176
177
    /**
178
     * Test for the hasAccess() method.
179
     *
180
     * @dataProvider providerForTestHasAccessReturnsFalse
181
     */
182 View Code Duplication
    public function testHasAccessReturnsFalse(array $roles, array $roleAssignments)
183
    {
184
        /** @var $userHandlerMock \PHPUnit\Framework\MockObject\MockObject */
185
        $userHandlerMock = $this->getPersistenceMock()->userHandler();
186
        $userReferenceMock = $this->getUserReferenceMock();
187
        $service = $this->getPermissionResolverMock(null);
188
189
        $userReferenceMock
190
            ->expects($this->once())
191
            ->method('getUserId')
192
            ->will($this->returnValue(10));
193
194
        $userHandlerMock
195
            ->expects($this->once())
196
            ->method('loadRoleAssignmentsByGroupId')
197
            ->with($this->equalTo(10), $this->equalTo(true))
198
            ->will($this->returnValue($roleAssignments));
199
200
        foreach ($roleAssignments as $at => $roleAssignment) {
201
            $userHandlerMock
202
                ->expects($this->at($at + 1))
203
                ->method('loadRole')
204
                ->with($roleAssignment->roleId)
205
                ->will($this->returnValue($roles[$roleAssignment->roleId]));
206
        }
207
208
        $result = $service->hasAccess('dummy-module2', 'dummy-function2');
209
210
        self::assertEquals(false, $result);
211
    }
212
213
    /**
214
     * Test for the sudo() & hasAccess() method.
215
     */
216
    public function testHasAccessReturnsFalseButSudoSoTrue()
217
    {
218
        /** @var $userHandlerMock \PHPUnit\Framework\MockObject\MockObject */
219
        $userHandlerMock = $this->getPersistenceMock()->userHandler();
220
        $service = $this->getPermissionResolverMock(null);
221
        $repositoryMock = $this->getRepositoryMock();
222
        $repositoryMock
223
            ->expects($this->any())
224
            ->method('getPermissionResolver')
225
            ->will($this->returnValue($service));
226
227
        $userHandlerMock
228
            ->expects($this->never())
229
            ->method($this->anything());
230
231
        $result = $service->sudo(
232
            function (Repository $repo) {
233
                return $repo->hasAccess('dummy-module', 'dummy-function');
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repository\Repository::hasAccess() has been deprecated with message: since 6.6, to be removed. Use PermissionResolver::hasAccess() 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...
234
            },
235
            $repositoryMock
236
        );
237
238
        self::assertEquals(true, $result);
239
    }
240
241
    /**
242
     * @return array
243
     */
244 View Code Duplication
    public function providerForTestHasAccessReturnsPermissionSets()
245
    {
246
        return [
247
            [
248
                [
249
                    31 => $this->createRole(
250
                        [
251
                            ['dummy-module', 'dummy-function', 'test-limitation'],
252
                        ],
253
                        31
254
                    ),
255
                ],
256
                [
257
                    new RoleAssignment(
258
                        [
259
                            'roleId' => 31,
260
                        ]
261
                    ),
262
                ],
263
            ],
264
            [
265
                [
266
                    31 => $this->createRole(
267
                        [
268
                            ['dummy-module', 'dummy-function', 'test-limitation'],
269
                        ],
270
                        31
271
                    ),
272
                    32 => $this->createRole(
273
                        [
274
                            ['dummy-module', 'dummy-function', 'test-limitation2'],
275
                        ],
276
                        32
277
                    ),
278
                ],
279
                [
280
                    new RoleAssignment(
281
                        [
282
                            'roleId' => 31,
283
                        ]
284
                    ),
285
                    new RoleAssignment(
286
                        [
287
                            'roleId' => 32,
288
                        ]
289
                    ),
290
                ],
291
            ],
292
        ];
293
    }
294
295
    /**
296
     * Test for the hasAccess() method.
297
     *
298
     * @dataProvider providerForTestHasAccessReturnsPermissionSets
299
     */
300
    public function testHasAccessReturnsPermissionSets(array $roles, array $roleAssignments)
301
    {
302
        /** @var $userHandlerMock \PHPUnit\Framework\MockObject\MockObject */
303
        $userHandlerMock = $this->getPersistenceMock()->userHandler();
304
        $roleDomainMapper = $this->getRoleDomainMapperMock(['buildDomainPolicyObject']);
305
        $permissionResolverMock = $this->getPermissionResolverMock(['getCurrentUserReference']);
306
307
        $permissionResolverMock
308
            ->expects($this->once())
309
            ->method('getCurrentUserReference')
310
            ->will($this->returnValue(new UserReference(14)));
311
312
        $userHandlerMock
313
            ->expects($this->once())
314
            ->method('loadRoleAssignmentsByGroupId')
315
            ->with($this->isType('integer'), $this->equalTo(true))
316
            ->will($this->returnValue($roleAssignments));
317
318
        foreach ($roleAssignments as $at => $roleAssignment) {
319
            $userHandlerMock
320
                ->expects($this->at($at + 1))
321
                ->method('loadRole')
322
                ->with($roleAssignment->roleId)
323
                ->will($this->returnValue($roles[$roleAssignment->roleId]));
324
        }
325
326
        $permissionSets = [];
327
        $count = 0;
328
        /* @var $roleAssignments \eZ\Publish\SPI\Persistence\User\RoleAssignment[] */
329
        foreach ($roleAssignments as $i => $roleAssignment) {
330
            $permissionSet = ['limitation' => null];
331
            foreach ($roles[$roleAssignment->roleId]->policies as $k => $policy) {
332
                $policyName = 'policy-' . $i . '-' . $k;
333
                $return = $this->returnValue($policyName);
334
                $permissionSet['policies'][] = $policyName;
335
336
                $roleDomainMapper
337
                    ->expects($this->at($count++))
338
                    ->method('buildDomainPolicyObject')
339
                    ->with($policy)
340
                    ->will($return);
341
            }
342
343
            if (!empty($permissionSet['policies'])) {
344
                $permissionSets[] = $permissionSet;
345
            }
346
        }
347
348
        /* @var $repositoryMock \eZ\Publish\Core\Repository\Repository */
349
        self::assertEquals(
350
            $permissionSets,
351
            $permissionResolverMock->hasAccess('dummy-module', 'dummy-function')
352
        );
353
    }
354
355
    /**
356
     * @return array
357
     */
358 View Code Duplication
    public function providerForTestHasAccessReturnsLimitationNotFoundException()
359
    {
360
        return [
361
            [
362
                [
363
                    31 => $this->createRole(
364
                        [
365
                            ['dummy-module', 'dummy-function', 'notfound'],
366
                        ],
367
                        31
368
                    ),
369
                ],
370
                [
371
                    new RoleAssignment(
372
                        [
373
                            'roleId' => 31,
374
                        ]
375
                    ),
376
                ],
377
            ],
378
            [
379
                [
380
                    31 => $this->createRole(
381
                        [
382
                            ['dummy-module', 'dummy-function', 'test-limitation'],
383
                        ],
384
                        31
385
                    ),
386
                    32 => $this->createRole(
387
                        [
388
                            ['dummy-module', 'dummy-function', 'notfound'],
389
                        ],
390
                        32
391
                    ),
392
                ],
393
                [
394
                    new RoleAssignment(
395
                        [
396
                            'roleId' => 31,
397
                        ]
398
                    ),
399
                    new RoleAssignment(
400
                        [
401
                            'roleId' => 32,
402
                        ]
403
                    ),
404
                ],
405
            ],
406
        ];
407
    }
408
409
    /**
410
     * Test for the hasAccess() method.
411
     *
412
     * @dataProvider providerForTestHasAccessReturnsLimitationNotFoundException
413
     * @expectedException \eZ\Publish\Core\Base\Exceptions\NotFound\LimitationNotFoundException
414
     */
415
    public function testHasAccessReturnsLimitationNotFoundException(array $roles, array $roleAssignments)
416
    {
417
        /** @var $userHandlerMock \PHPUnit\Framework\MockObject\MockObject */
418
        $userHandlerMock = $this->getPersistenceMock()->userHandler();
419
        $roleDomainMapper = $this->getRoleDomainMapperMock();
420
        $permissionResolverMock = $this->getPermissionResolverMock(['getCurrentUserReference']);
421
422
        $permissionResolverMock
423
            ->expects($this->once())
424
            ->method('getCurrentUserReference')
425
            ->will($this->returnValue(new UserReference(14)));
426
427
        $userHandlerMock
428
            ->expects($this->once())
429
            ->method('loadRoleAssignmentsByGroupId')
430
            ->with($this->isType('integer'), $this->equalTo(true))
431
            ->will($this->returnValue($roleAssignments));
432
433
        foreach ($roleAssignments as $at => $roleAssignment) {
434
            $userHandlerMock
435
                ->expects($this->at($at + 1))
436
                ->method('loadRole')
437
                ->with($roleAssignment->roleId)
438
                ->will($this->returnValue($roles[$roleAssignment->roleId]));
439
        }
440
441
        $count = 0;
442
        /* @var $roleAssignments \eZ\Publish\SPI\Persistence\User\RoleAssignment[] */
443
        foreach ($roleAssignments as $i => $roleAssignment) {
444
            $permissionSet = ['limitation' => null];
445
            foreach ($roles[$roleAssignment->roleId]->policies as $k => $policy) {
446
                $policyName = 'policy-' . $i . '-' . $k;
447
                if ($policy->limitations === 'notfound') {
448
                    $return = $this->throwException(new LimitationNotFoundException('notfound'));
449
                } else {
450
                    $return = $this->returnValue($policyName);
451
                    $permissionSet['policies'][] = $policyName;
452
                }
453
454
                $roleDomainMapper
455
                    ->expects($this->at($count++))
456
                    ->method('buildDomainPolicyObject')
457
                    ->with($policy)
458
                    ->will($return);
459
460
                if ($policy->limitations === 'notfound') {
461
                    break 2; // no more execution after exception
462
                }
463
            }
464
        }
465
466
        $permissionResolverMock->hasAccess('dummy-module', 'dummy-function');
467
    }
468
469
    /**
470
     * @return array
471
     */
472 View Code Duplication
    public function providerForTestHasAccessReturnsInvalidArgumentValueException()
473
    {
474
        return [
475
            [
476
                [
477
                    31 => $this->createRole(
478
                        [
479
                            ['test-module', 'test-function', '*'],
480
                        ],
481
                        31
482
                    ),
483
                ],
484
                [
485
                    new RoleAssignment(
486
                        [
487
                            'roleId' => 31,
488
                        ]
489
                    ),
490
                ],
491
            ],
492
            [
493
                [
494
                    31 => $this->createRole(
495
                        [
496
                            ['other-module', 'test-function', '*'],
497
                        ],
498
                        31
499
                    ),
500
                    32 => $this->createRole(
501
                        [
502
                            ['test-module', 'other-function', '*'],
503
                        ],
504
                        32
505
                    ),
506
                ],
507
                [
508
                    new RoleAssignment(
509
                        [
510
                            'roleId' => 31,
511
                        ]
512
                    ),
513
                    new RoleAssignment(
514
                        [
515
                            'roleId' => 32,
516
                        ]
517
                    ),
518
                ],
519
            ],
520
        ];
521
    }
522
523
    /**
524
     * Test for the hasAccess() method.
525
     *
526
     * @dataProvider providerForTestHasAccessReturnsInvalidArgumentValueException
527
     * @expectedException \eZ\Publish\Core\Base\Exceptions\InvalidArgumentValue
528
     */
529
    public function testHasAccessReturnsInvalidArgumentValueException(array $roles, array $roleAssignments)
0 ignored issues
show
Unused Code introduced by
The parameter $roleAssignments is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
530
    {
531
        $permissionResolverMock = $this->getPermissionResolverMock(['getCurrentUserReference']);
532
533
        /** @var $role \eZ\Publish\SPI\Persistence\User\Role */
534
        foreach ($roles as $role) {
535
            /** @var $policy \eZ\Publish\SPI\Persistence\User\Policy */
536
            foreach ($role->policies as $policy) {
537
                $permissionResolverMock->hasAccess($policy->module, $policy->function);
538
            }
539
        }
540
    }
541
542
    public function providerForTestHasAccessReturnsPermissionSetsWithRoleLimitation()
543
    {
544
        return [
545
            [
546
                [
547
                    32 => $this->createRole(
548
                        [
549
                            [
550
                                'dummy-module', 'dummy-function', [
551
                                'Subtree' => [
552
                                    '/1/2/',
553
                                ],
554
                            ],
555
                            ],
556
                        ],
557
                        32
558
                    ),
559
                ],
560
                [
561
                    new RoleAssignment(
562
                        [
563
                            'roleId' => 32,
564
                            'limitationIdentifier' => 'Subtree',
565
                            'values' => ['/1/2/'],
566
                        ]
567
                    ),
568
                ],
569
            ],
570
            [
571
                [
572
                    33 => $this->createRole([['*', '*', '*']], 33),
573
                ],
574
                [
575
                    new RoleAssignment(
576
                        [
577
                            'roleId' => 33,
578
                            'limitationIdentifier' => 'Subtree',
579
                            'values' => ['/1/2/'],
580
                        ]
581
                    ),
582
                ],
583
            ],
584
        ];
585
    }
586
587
    /**
588
     * Test for the hasAccess() method.
589
     *
590
     * @dataProvider providerForTestHasAccessReturnsPermissionSetsWithRoleLimitation
591
     */
592
    public function testHasAccessReturnsPermissionSetsWithRoleLimitation(array $roles, array $roleAssignments)
593
    {
594
        /** @var $userHandlerMock \PHPUnit\Framework\MockObject\MockObject */
595
        $userHandlerMock = $this->getPersistenceMock()->userHandler();
596
        $limitationTypeMock = $this->createMock(Type::class);
597
        $limitationService = $this->getLimitationServiceMock();
598
        $roleDomainMapper = $this->getRoleDomainMapperMock();
599
        $permissionResolverMock = $this->getPermissionResolverMock(['getCurrentUserReference']);
600
601
        $permissionResolverMock
602
            ->expects($this->once())
603
            ->method('getCurrentUserReference')
604
            ->will($this->returnValue(new UserReference(14)));
605
606
        $userHandlerMock
607
            ->expects($this->once())
608
            ->method('loadRoleAssignmentsByGroupId')
609
            ->with($this->isType('integer'), $this->equalTo(true))
610
            ->will($this->returnValue($roleAssignments));
611
612
        foreach ($roleAssignments as $at => $roleAssignment) {
613
            $userHandlerMock
614
                ->expects($this->at($at + 1))
615
                ->method('loadRole')
616
                ->with($roleAssignment->roleId)
617
                ->will($this->returnValue($roles[$roleAssignment->roleId]));
618
        }
619
620
        $permissionSets = [];
621
        /** @var $roleAssignments \eZ\Publish\SPI\Persistence\User\RoleAssignment[] */
622
        foreach ($roleAssignments as $i => $roleAssignment) {
623
            $permissionSet = [];
624
            foreach ($roles[$roleAssignment->roleId]->policies as $k => $policy) {
625
                $policyName = "policy-{$i}-{$k}";
626
                $permissionSet['policies'][] = $policyName;
627
                $roleDomainMapper
628
                    ->expects($this->at($k))
629
                    ->method('buildDomainPolicyObject')
630
                    ->with($policy)
631
                    ->will($this->returnValue($policyName));
632
            }
633
634
            $permissionSet['limitation'] = "limitation-{$i}";
635
            $limitationTypeMock
636
                ->expects($this->at($i))
637
                ->method('buildValue')
638
                ->with($roleAssignment->values)
639
                ->will($this->returnValue($permissionSet['limitation']));
640
            $limitationService
641
                ->expects($this->any())
642
                ->method('getLimitationType')
643
                ->with($roleAssignment->limitationIdentifier)
644
                ->will($this->returnValue($limitationTypeMock));
645
646
            $permissionSets[] = $permissionSet;
647
        }
648
649
        self::assertEquals(
650
            $permissionSets,
651
            $permissionResolverMock->hasAccess('dummy-module', 'dummy-function')
652
        );
653
    }
654
655
    /**
656
     * Returns Role stub.
657
     *
658
     * @param array $policiesData
659
     * @param mixed $roleId
660
     *
661
     * @return \eZ\Publish\SPI\Persistence\User\Role
662
     */
663
    private function createRole(array $policiesData, $roleId = null)
664
    {
665
        $policies = [];
666
        foreach ($policiesData as $policyData) {
667
            $policies[] = new Policy(
668
                [
669
                    'module' => $policyData[0],
670
                    'function' => $policyData[1],
671
                    'limitations' => $policyData[2],
672
                ]
673
            );
674
        }
675
676
        return new Role(
677
            [
678
                'id' => $roleId,
679
                'policies' => $policies,
680
            ]
681
        );
682
    }
683
684 View Code Duplication
    public function providerForTestCanUserSimple()
685
    {
686
        return [
687
            [true, true],
688
            [false, false],
689
            [[], false],
690
        ];
691
    }
692
693
    /**
694
     * Test for the canUser() method.
695
     *
696
     * Tests execution paths with permission sets equaling to boolean value or empty array.
697
     *
698
     * @dataProvider providerForTestCanUserSimple
699
     */
700 View Code Duplication
    public function testCanUserSimple($permissionSets, $result)
701
    {
702
        $permissionResolverMock = $this->getPermissionResolverMock(['hasAccess']);
703
704
        $permissionResolverMock
705
            ->expects($this->once())
706
            ->method('hasAccess')
707
            ->with($this->equalTo('test-module'), $this->equalTo('test-function'))
708
            ->will($this->returnValue($permissionSets));
709
710
        /** @var $valueObject \eZ\Publish\API\Repository\Values\ValueObject */
711
        $valueObject = $this->getMockForAbstractClass(ValueObject::class);
712
713
        self::assertEquals(
714
            $result,
715
            $permissionResolverMock->canUser('test-module', 'test-function', $valueObject, [$valueObject])
716
        );
717
    }
718
719
    /**
720
     * Test for the canUser() method.
721
     *
722
     * Tests execution path with permission set defining no limitations.
723
     */
724
    public function testCanUserWithoutLimitations()
725
    {
726
        $permissionResolverMock = $this->getPermissionResolverMock(
727
            [
728
                'hasAccess',
729
                'getCurrentUserReference',
730
            ]
731
        );
732
733
        $policyMock = $this->getMockBuilder(Policy::class)
734
            ->setMethods(['getLimitations'])
735
            ->setConstructorArgs([])
736
            ->disableOriginalConstructor()
737
            ->getMock();
738
739
        $policyMock
740
            ->expects($this->once())
741
            ->method('getLimitations')
742
            ->will($this->returnValue('*'));
743
        $permissionSets = [
744
            [
745
                'limitation' => null,
746
                'policies' => [$policyMock],
747
            ],
748
        ];
749
        $permissionResolverMock
750
            ->expects($this->once())
751
            ->method('hasAccess')
752
            ->with($this->equalTo('test-module'), $this->equalTo('test-function'))
753
            ->will($this->returnValue($permissionSets));
754
755
        $permissionResolverMock
756
            ->expects($this->once())
757
            ->method('getCurrentUserReference')
758
            ->will($this->returnValue(new UserReference(14)));
759
760
        /** @var $valueObject \eZ\Publish\API\Repository\Values\ValueObject */
761
        $valueObject = $this->getMockForAbstractClass(ValueObject::class);
762
763
        self::assertTrue(
764
            $permissionResolverMock->canUser(
765
                'test-module',
766
                'test-function',
767
                $valueObject,
768
                [$valueObject]
769
            )
770
        );
771
    }
772
773
    /**
774
     * @return array
775
     */
776
    private function getPermissionSetsMock()
777
    {
778
        $roleLimitationMock = $this->createMock(Limitation::class);
779
        $roleLimitationMock
780
            ->expects($this->any())
781
            ->method('getIdentifier')
782
            ->will($this->returnValue('test-role-limitation-identifier'));
783
784
        $policyLimitationMock = $this->createMock(Limitation::class);
785
        $policyLimitationMock
786
            ->expects($this->any())
787
            ->method('getIdentifier')
788
            ->will($this->returnValue('test-policy-limitation-identifier'));
789
790
        $policyMock = $this->getMockBuilder(Policy::class)
791
            ->setMethods(['getLimitations'])
792
            ->setConstructorArgs([])
793
            ->getMock();
794
795
        $policyMock
796
            ->expects($this->any())
797
            ->method('getLimitations')
798
            ->will($this->returnValue([$policyLimitationMock, $policyLimitationMock]));
799
800
        $permissionSet = [
801
            'limitation' => clone $roleLimitationMock,
802
            'policies' => [$policyMock, $policyMock],
803
        ];
804
        $permissionSets = [$permissionSet, $permissionSet];
805
806
        return $permissionSets;
807
    }
808
809
    /**
810
     * Provides evaluation results for two permission sets, each with a role limitation and two policies,
811
     * with two limitations per policy.
812
     *
813
     * @return array
814
     */
815
    public function providerForTestCanUserComplex()
816
    {
817
        return [
818
            [
819
                [true, true],
820
                [
821
                    [
822
                        [true, true],
823
                        [true, true],
824
                    ],
825
                    [
826
                        [true, true],
827
                        [true, true],
828
                    ],
829
                ],
830
                true,
831
            ],
832
            [
833
                [false, false],
834
                [
835
                    [
836
                        [true, true],
837
                        [true, true],
838
                    ],
839
                    [
840
                        [true, true],
841
                        [true, true],
842
                    ],
843
                ],
844
                false,
845
            ],
846
            [
847
                [false, true],
848
                [
849
                    [
850
                        [true, true],
851
                        [true, true],
852
                    ],
853
                    [
854
                        [true, true],
855
                        [true, true],
856
                    ],
857
                ],
858
                true,
859
            ],
860
            [
861
                [false, true],
862
                [
863
                    [
864
                        [true, true],
865
                        [true, true],
866
                    ],
867
                    [
868
                        [true, false],
869
                        [true, true],
870
                    ],
871
                ],
872
                true,
873
            ],
874
            [
875
                [true, false],
876
                [
877
                    [
878
                        [true, false],
879
                        [false, true],
880
                    ],
881
                    [
882
                        [true, true],
883
                        [true, true],
884
                    ],
885
                ],
886
                false,
887
            ],
888
        ];
889
    }
890
891
    /**
892
     * Test for the canUser() method.
893
     *
894
     * Tests execution paths with permission sets containing limitations.
895
     *
896
     * @dataProvider providerForTestCanUserComplex
897
     */
898
    public function testCanUserComplex(array $roleLimitationEvaluations, array $policyLimitationEvaluations, $userCan)
899
    {
900
        /** @var $valueObject \eZ\Publish\API\Repository\Values\ValueObject */
901
        $valueObject = $this->createMock(ValueObject::class);
902
        $limitationServiceMock = $this->getLimitationServiceMock();
903
        $permissionResolverMock = $this->getPermissionResolverMock(
904
            [
905
                'hasAccess',
906
                'getCurrentUserReference',
907
            ]
908
        );
909
910
        $permissionSets = $this->getPermissionSetsMock();
911
        $permissionResolverMock
912
            ->expects($this->once())
913
            ->method('hasAccess')
914
            ->with($this->equalTo('test-module'), $this->equalTo('test-function'))
915
            ->will($this->returnValue($permissionSets));
916
917
        $userRef = new UserReference(14);
918
        $permissionResolverMock
919
            ->expects($this->once())
920
            ->method('getCurrentUserReference')
921
            ->will($this->returnValue(new UserReference(14)));
922
923
        $invocation = 0;
924
        for ($i = 0; $i < count($permissionSets); ++$i) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
925
            $limitation = $this->createMock(Type::class);
926
            $limitation
927
                ->expects($this->once())
928
                ->method('evaluate')
929
                ->with($permissionSets[$i]['limitation'], $userRef, $valueObject, [$valueObject])
930
                ->will($this->returnValue($roleLimitationEvaluations[$i]));
931
            $limitationServiceMock
932
                ->expects($this->at($invocation++))
933
                ->method('getLimitationType')
934
                ->with('test-role-limitation-identifier')
935
                ->will($this->returnValue($limitation));
936
937
            if (!$roleLimitationEvaluations[$i]) {
938
                continue;
939
            }
940
941
            for ($j = 0; $j < count($permissionSets[$i]['policies']); ++$j) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
942
                /** @var $policy \eZ\Publish\API\Repository\Values\User\Policy */
943
                $policy = $permissionSets[$i]['policies'][$j];
944
                $limitations = $policy->getLimitations();
945
                for ($k = 0; $k < count($limitations); ++$k) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
946
                    $limitationsPass = true;
947
                    $limitation = $this->createMock(Type::class);
948
                    $limitation
949
                        ->expects($this->once())
950
                        ->method('evaluate')
951
                        ->with($limitations[$k], $userRef, $valueObject, [$valueObject])
952
                        ->will($this->returnValue($policyLimitationEvaluations[$i][$j][$k]));
953
                    $limitationServiceMock
954
                        ->expects($this->at($invocation++))
955
                        ->method('getLimitationType')
956
                        ->with('test-policy-limitation-identifier')
957
                        ->will($this->returnValue($limitation));
958
959
                    if (!$policyLimitationEvaluations[$i][$j][$k]) {
960
                        $limitationsPass = false;
961
                        break;
962
                    }
963
                }
964
965
                /** @var $limitationsPass */
966
                if ($limitationsPass) {
0 ignored issues
show
Bug introduced by
The variable $limitationsPass does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
967
                    break 2;
968
                }
969
            }
970
        }
971
972
        self::assertEquals(
973
            $userCan,
974
            $permissionResolverMock->canUser(
975
                'test-module',
976
                'test-function',
977
                $valueObject,
978
                [$valueObject]
979
            )
980
        );
981
    }
982
983
    /**
984
     * Test for the setCurrentUserReference() and getCurrentUserReference() methods.
985
     */
986
    public function testSetAndGetCurrentUserReference()
987
    {
988
        $permissionResolverMock = $this->getPermissionResolverMock(null);
989
        $userReferenceMock = $this->getUserReferenceMock();
990
991
        $userReferenceMock
992
            ->expects($this->once())
993
            ->method('getUserId')
994
            ->will($this->returnValue(42));
995
996
        $permissionResolverMock->setCurrentUserReference($userReferenceMock);
997
998
        self::assertSame(
999
            $userReferenceMock,
1000
            $permissionResolverMock->getCurrentUserReference()
1001
        );
1002
    }
1003
1004
    /**
1005
     * Test for the getCurrentUserReference() method.
1006
     */
1007
    public function testGetCurrentUserReferenceReturnsAnonymousUser()
1008
    {
1009
        $permissionResolverMock = $this->getPermissionResolverMock(null);
1010
        $userReferenceMock = $this->getUserReferenceMock();
1011
1012
        self::assertSame(
1013
            $userReferenceMock,
1014
            $permissionResolverMock->getCurrentUserReference()
1015
        );
1016
    }
1017
1018
    protected $permissionResolverMock;
1019
1020
    /**
1021
     * @return \eZ\Publish\API\Repository\PermissionResolver|\PHPUnit\Framework\MockObject\MockObject
1022
     */
1023
    protected function getPermissionResolverMock($methods = [])
1024
    {
1025
        if ($this->permissionResolverMock === null) {
1026
            $this->permissionResolverMock = $this
1027
                ->getMockBuilder(PermissionResolver::class)
1028
                ->setMethods($methods)
1029
                ->setConstructorArgs(
1030
                    [
1031
                        $this->getRoleDomainMapperMock(),
1032
                        $this->getLimitationServiceMock(),
1033
                        $this->getPersistenceMock()->userHandler(),
1034
                        $this->getUserReferenceMock(),
1035
                        [
1036
                            'dummy-module' => [
1037
                                'dummy-function' => [
1038
                                    'dummy-limitation' => true,
1039
                                ],
1040
                                'dummy-function2' => [
1041
                                    'dummy-limitation' => true,
1042
                                ],
1043
                            ],
1044
                            'dummy-module2' => [
1045
                                'dummy-function' => [
1046
                                    'dummy-limitation' => true,
1047
                                ],
1048
                                'dummy-function2' => [
1049
                                    'dummy-limitation' => true,
1050
                                ],
1051
                            ],
1052
                        ],
1053
                    ]
1054
                )
1055
                ->getMock();
1056
        }
1057
1058
        return $this->permissionResolverMock;
1059
    }
1060
1061
    protected $userReferenceMock;
1062
1063
    protected function getUserReferenceMock()
1064
    {
1065
        if ($this->userReferenceMock === null) {
1066
            $this->userReferenceMock = $this->createMock(UserReference::class);
1067
        }
1068
1069
        return $this->userReferenceMock;
1070
    }
1071
1072
    protected $repositoryMock;
1073
1074
    /**
1075
     * @return \eZ\Publish\API\Repository\Repository|\PHPUnit\Framework\MockObject\MockObject
1076
     */
1077
    protected function getRepositoryMock($methods = [])
0 ignored issues
show
Unused Code introduced by
The parameter $methods is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1078
    {
1079
        if ($this->repositoryMock === null) {
1080
            $this->repositoryMock = $this
1081
                ->getMockBuilder(CoreRepository::class)
1082
                ->setMethods(['getPermissionResolver'])
1083
                ->disableOriginalConstructor()
1084
                ->getMock();
1085
        }
1086
1087
        return $this->repositoryMock;
1088
    }
1089
1090
    protected $roleDomainMapperMock;
1091
1092
    /**
1093
     * @return \eZ\Publish\Core\Repository\Helper\RoleDomainMapper|\PHPUnit\Framework\MockObject\MockObject
1094
     */
1095 View Code Duplication
    protected function getRoleDomainMapperMock($methods = [])
1096
    {
1097
        if ($this->roleDomainMapperMock === null) {
1098
            $this->roleDomainMapperMock = $this
1099
                ->getMockBuilder(RoleDomainMapper::class)
1100
                ->setMethods($methods)
1101
                ->disableOriginalConstructor()
1102
                ->getMock();
1103
        }
1104
1105
        return $this->roleDomainMapperMock;
1106
    }
1107
1108
    protected $limitationServiceMock;
1109
1110
    /**
1111
     * @return \eZ\Publish\Core\Repository\Helper\LimitationService|\PHPUnit\Framework\MockObject\MockObject
1112
     */
1113 View Code Duplication
    protected function getLimitationServiceMock($methods = [])
1114
    {
1115
        if ($this->limitationServiceMock === null) {
1116
            $this->limitationServiceMock = $this
1117
                ->getMockBuilder(LimitationService::class)
1118
                ->setMethods($methods)
1119
                ->disableOriginalConstructor()
1120
                ->getMock();
1121
        }
1122
1123
        return $this->limitationServiceMock;
1124
    }
1125
}
1126