EntityAclExtensionTest   F
last analyzed

Complexity

Total Complexity 55

Size/Duplication

Total Lines 1263
Duplicated Lines 11.96 %

Coupling/Cohesion

Components 1
Dependencies 23
Metric Value
wmc 55
lcom 1
cbo 23
dl 151
loc 1263
rs 0.6197

45 Methods

Rating   Name   Duplication   Size   Complexity  
A testValidateMaskForBusinessUnit() 0 4 1
A testValidateMaskForOrganization() 0 4 1
B buildTestTree() 0 79 1
A testValidateMaskForOrganizationInvalid() 0 4 1
A testValidateMaskForBusinessUnitInvalid() 0 4 1
A testValidateMaskForUser() 0 4 1
A testValidateMaskForUserInvalid() 0 4 1
A testValidateMaskForOrganizationOwned() 0 8 1
A testValidateMaskForOrganizationOwnedInvalid() 0 8 1
A testValidateMaskForUserOwned() 0 8 1
A testValidateMaskForUserOwnedInvalid() 0 8 1
A testValidateMaskForRoot() 0 4 1
A testValidateMaskForRootInvalid() 0 4 1
A testGetPermissions() 0 7 1
B testGetAllowedPermissions() 0 59 4
B testDecideIsGranting() 0 38 6
A testGetMaskBuilder() 0 7 1
A getMaskBuilderProvider() 0 11 1
A testGetAllMaskBuilders() 0 10 1
A testAdaptRootMask() 0 21 2
A testGetAccessLevel() 0 4 1
A getAccessLevelProvider() 0 48 1
A testGetAccessLevelNamesForRoot() 0 14 1
A testGetAccessLevelNamesForNonRoot() 0 11 1
B accessLevelProvider() 0 32 1
A getAllowedPermissionsProvider() 0 66 1
A decideIsGrantingProvider() 0 64 1
A adaptRootMaskProvider() 0 65 1
A validateMaskForOrganizationProvider() 10 10 1
A validateMaskForOrganizationInvalidProvider() 11 11 1
B validateMaskForBusinessUnitProvider() 31 31 1
A validateMaskForBusinessUnitInvalidProvider() 9 9 1
B validateMaskForUserProvider() 31 31 1
A validateMaskForUserInvalidProvider() 9 9 1
B validateMaskForUserOwnedProvider() 0 38 1
A validateMaskForUserOwnedInvalidProvider() 9 9 1
A validateMaskForOrganizationOwnedProvider() 0 18 1
A validateMaskForOrganizationOwnedInvalidProvider() 10 10 1
B testSupports() 0 33 2
B supportsDataProvider() 0 33 1
A testGetObjectIdentity() 0 4 1
A getObjectIdentityDataProvider() 0 49 1
B setUp() 0 89 1
A getPermissionManagerMock() 18 18 1
A getPermission() 13 13 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like EntityAclExtensionTest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use EntityAclExtensionTest, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Oro\Bundle\SecurityBundle\Tests\Unit\Acl\Extension;
4
5
use Symfony\Component\DependencyInjection\ContainerInterface;
6
use Symfony\Component\Security\Core\Util\ClassUtils;
7
use Symfony\Component\Security\Acl\Domain\ObjectIdentity;
8
9
use Oro\Bundle\EntityBundle\ORM\EntityClassResolver;
10
11
use Oro\Bundle\SecurityBundle\Acl\AccessLevel;
12
use Oro\Bundle\SecurityBundle\Acl\Domain\ObjectIdAccessor;
13
use Oro\Bundle\SecurityBundle\Acl\Domain\ObjectIdentityFactory;
14
use Oro\Bundle\SecurityBundle\Acl\Extension\EntityAclExtension;
15
use Oro\Bundle\SecurityBundle\Acl\Extension\EntityMaskBuilder;
16
use Oro\Bundle\SecurityBundle\Acl\Group\AclGroupProviderInterface;
17
use Oro\Bundle\SecurityBundle\Acl\Permission\PermissionManager;
18
use Oro\Bundle\SecurityBundle\Annotation\Acl as AclAnnotation;
19
use Oro\Bundle\SecurityBundle\Authentication\Token\UsernamePasswordOrganizationToken;
20
use Oro\Bundle\SecurityBundle\Entity\Permission;
21
use Oro\Bundle\SecurityBundle\Metadata\EntitySecurityMetadata;
22
use Oro\Bundle\SecurityBundle\Metadata\EntitySecurityMetadataProvider;
23
use Oro\Bundle\SecurityBundle\Owner\EntityOwnerAccessor;
24
use Oro\Bundle\SecurityBundle\Owner\EntityOwnershipDecisionMaker;
25
use Oro\Bundle\SecurityBundle\Owner\Metadata\OwnershipMetadata;
26
use Oro\Bundle\SecurityBundle\Owner\OwnerTreeProvider;
27
use Oro\Bundle\SecurityBundle\Tests\Unit\Acl\Domain\Fixtures\Entity\BusinessUnit;
28
use Oro\Bundle\SecurityBundle\Tests\Unit\Acl\Domain\Fixtures\Entity\Organization;
29
use Oro\Bundle\SecurityBundle\Tests\Unit\Acl\Domain\Fixtures\Entity\TestEntity;
30
use Oro\Bundle\SecurityBundle\Tests\Unit\Acl\Domain\Fixtures\Entity\User;
31
use Oro\Bundle\SecurityBundle\Tests\Unit\TestHelper;
32
use Oro\Bundle\SecurityBundle\Tests\Unit\Stub\OwnershipMetadataProviderStub;
33
use Oro\Bundle\SecurityBundle\Owner\OwnerTree;
34
35
/**
36
 * @SuppressWarnings(PHPMD.ExcessiveClassLength)
37
 * @SuppressWarnings(PHPMD.TooManyMethods)
38
 * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
39
 */
40
class EntityAclExtensionTest extends \PHPUnit_Framework_TestCase
41
{
42
    /** @var EntityAclExtension */
43
    private $extension;
44
45
    /** @var EntitySecurityMetadataProvider|\PHPUnit_Framework_MockObject_MockObject */
46
    private $securityMetadataProvider;
47
48
    /** @var OwnershipMetadataProviderStub */
49
    private $metadataProvider;
50
51
    /** @var OwnerTree */
52
    private $tree;
53
54
    /** @var EntityOwnershipDecisionMaker */
55
    private $decisionMaker;
56
57
    /** @var \PHPUnit_Framework_MockObject_MockObject|PermissionManager */
58
    private $permissionManager;
59
60
    /** @var \PHPUnit_Framework_MockObject_MockObject|AclGroupProviderInterface */
61
    private $groupProvider;
62
63
    protected function setUp()
64
    {
65
        $this->tree = new OwnerTree();
66
67
        $this->securityMetadataProvider = $this
68
            ->getMockBuilder('Oro\Bundle\SecurityBundle\Metadata\EntitySecurityMetadataProvider')
69
            ->disableOriginalConstructor()
70
            ->getMock();
71
72
        $this->metadataProvider = new OwnershipMetadataProviderStub($this);
73
        $this->metadataProvider->setMetadata(
74
            $this->metadataProvider->getGlobalLevelClass(),
75
            new OwnershipMetadata()
76
        );
77
        $this->metadataProvider->setMetadata(
78
            $this->metadataProvider->getLocalLevelClass(),
79
            new OwnershipMetadata('BUSINESS_UNIT', 'owner', 'owner_id')
80
        );
81
        $this->metadataProvider->setMetadata(
82
            $this->metadataProvider->getBasicLevelClass(),
83
            new OwnershipMetadata('BUSINESS_UNIT', 'owner', 'owner_id')
84
        );
85
86
        /** @var \PHPUnit_Framework_MockObject_MockObject|OwnerTreeProvider $treeProviderMock */
87
        $treeProviderMock = $this->getMockBuilder('Oro\Bundle\SecurityBundle\Owner\OwnerTreeProvider')
88
            ->disableOriginalConstructor()
89
            ->getMock();
90
91
        $treeProviderMock->expects($this->any())
92
            ->method('getTree')
93
            ->will($this->returnValue($this->tree));
94
95
        /** @var \PHPUnit_Framework_MockObject_MockObject|ContainerInterface $container */
96
        $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
97
        $container->expects($this->any())
98
            ->method('get')
99
            ->will(
100
                $this->returnValueMap(
101
                    [
102
                        [
103
                            'oro_security.ownership_tree_provider.chain',
104
                            ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE,
105
                            $treeProviderMock,
106
                        ],
107
                        [
108
                            'oro_security.owner.metadata_provider.chain',
109
                            ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE,
110
                            $this->metadataProvider,
111
                        ],
112
                        [
113
                            'oro_security.acl.object_id_accessor',
114
                            ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE,
115
                            new ObjectIdAccessor(),
116
                        ],
117
                        [
118
                            'oro_security.owner.entity_owner_accessor',
119
                            ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE,
120
                            new EntityOwnerAccessor($this->metadataProvider),
121
                        ],
122
                    ]
123
                )
124
            );
125
        $entityOwnerAccessor = new EntityOwnerAccessor($this->metadataProvider);
126
        $this->decisionMaker = new EntityOwnershipDecisionMaker(
127
            $treeProviderMock,
128
            new ObjectIdAccessor(),
129
            $entityOwnerAccessor,
130
            $this->metadataProvider
131
        );
132
        $this->decisionMaker->setContainer($container);
133
134
        $this->permissionManager = $this->getPermissionManagerMock();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->getPermissionManagerMock() can also be of type object<Oro\Bundle\Securi...sion\PermissionManager>. However, the property $permissionManager is declared as type object<PHPUnit_Framework_MockObject_MockObject>. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
135
136
        $this->groupProvider = $this->getMock('Oro\Bundle\SecurityBundle\Acl\Group\AclGroupProviderInterface');
137
        $this->groupProvider->expects($this->any())
138
            ->method('getGroup')
139
            ->willReturn(AclGroupProviderInterface::DEFAULT_SECURITY_GROUP);
140
141
        $this->extension = TestHelper::get($this)->createEntityAclExtension(
142
            $this->metadataProvider,
143
            $this->tree,
144
            new ObjectIdAccessor(),
145
            $this->decisionMaker,
146
            $this->permissionManager,
147
            $this->groupProvider
148
        );
149
150
        $this->extension->setEntityOwnerAccessor($entityOwnerAccessor);
151
    }
152
153
    private function buildTestTree()
154
    {
155
        /**
156
         * org1  org2     org3         org4
157
         *                |            |
158
         *  bu1   bu2     +-bu3        +-bu4
159
         *        |       | |            |
160
         *        |       | +-bu31       |
161
         *        |       | | |          |
162
         *        |       | | +-user31   |
163
         *        |       | |            |
164
         *  user1 +-user2 | +-user3      +-user4
165
         *                |                |
166
         *                +-bu3a           +-bu3
167
         *                  |              +-bu4
168
         *                  +-bu3a1          |
169
         *                                   +-bu41
170
         *                                     |
171
         *                                     +-bu411
172
         *                                       |
173
         *                                       +-user411
174
         *
175
         * user1 user2 user3 user31 user4 user411
176
         *
177
         * org1  org2  org3  org3   org4  org4
178
         * org2        org2
179
         *
180
         * bu1   bu2   bu3   bu31   bu4   bu411
181
         * bu2         bu2
182
         *
183
         */
184
        $this->tree->addLocalEntity('bu1', null);
185
        $this->tree->addLocalEntity('bu2', null);
186
        $this->tree->addLocalEntity('bu3', 'org3');
187
        $this->tree->addLocalEntity('bu31', 'org3');
188
        $this->tree->addLocalEntity('bu3a', 'org3');
189
        $this->tree->addLocalEntity('bu3a1', 'org3');
190
        $this->tree->addLocalEntity('bu4', 'org4');
191
        $this->tree->addLocalEntity('bu41', 'org4');
192
        $this->tree->addLocalEntity('bu411', 'org4');
193
194
        $this->tree->addDeepEntity('bu1', null);
195
        $this->tree->addDeepEntity('bu2', null);
196
        $this->tree->addDeepEntity('bu3', null);
197
        $this->tree->addDeepEntity('bu31', 'bu3');
198
        $this->tree->addDeepEntity('bu3a', null);
199
        $this->tree->addDeepEntity('bu3a1', 'bu3a');
200
        $this->tree->addDeepEntity('bu4', null);
201
        $this->tree->addDeepEntity('bu41', 'bu4');
202
        $this->tree->addDeepEntity('bu411', 'bu41');
203
204
        $this->tree->addBasicEntity('user1', null);
205
        $this->tree->addBasicEntity('user2', 'bu2');
206
        $this->tree->addBasicEntity('user3', 'bu3');
207
        $this->tree->addBasicEntity('user31', 'bu31');
208
        $this->tree->addBasicEntity('user4', 'bu4');
209
        $this->tree->addBasicEntity('user41', 'bu41');
210
        $this->tree->addBasicEntity('user411', 'bu411');
211
212
        $this->tree->addGlobalEntity('user1', 'org1');
213
        $this->tree->addGlobalEntity('user1', 'org2');
214
        $this->tree->addGlobalEntity('user2', 'org2');
215
        $this->tree->addGlobalEntity('user3', 'org2');
216
        $this->tree->addGlobalEntity('user3', 'org3');
217
        $this->tree->addGlobalEntity('user31', 'org3');
218
        $this->tree->addGlobalEntity('user4', 'org4');
219
        $this->tree->addGlobalEntity('user411', 'org4');
220
221
        $this->tree->addLocalEntityToBasic('user1', 'bu1', 'org1');
222
        $this->tree->addLocalEntityToBasic('user1', 'bu2', 'org2');
223
        $this->tree->addLocalEntityToBasic('user2', 'bu2', 'org2');
224
        $this->tree->addLocalEntityToBasic('user3', 'bu3', 'org3');
225
        $this->tree->addLocalEntityToBasic('user3', 'bu2', 'org2');
226
        $this->tree->addLocalEntityToBasic('user31', 'bu31', 'org3');
227
        $this->tree->addLocalEntityToBasic('user4', 'bu4', 'org4');
228
        $this->tree->addLocalEntityToBasic('user411', 'bu411', 'org4');
229
230
        $this->tree->buildTree();
231
    }
232
233
    /**
234
     * @dataProvider validateMaskForOrganizationProvider
235
     *
236
     * @param int $mask
237
     */
238
    public function testValidateMaskForOrganization($mask)
239
    {
240
        $this->extension->validateMask($mask, new Organization());
241
    }
242
243
    /**
244
     * @dataProvider validateMaskForOrganizationInvalidProvider
245
     * @expectedException \Oro\Bundle\SecurityBundle\Acl\Exception\InvalidAclMaskException
246
     *
247
     * @param int $mask
248
     */
249
    public function testValidateMaskForOrganizationInvalid($mask)
250
    {
251
        $this->extension->validateMask($mask, new Organization());
252
    }
253
254
    /**
255
     * @dataProvider validateMaskForBusinessUnitProvider
256
     *
257
     * @param int $mask
258
     */
259
    public function testValidateMaskForBusinessUnit($mask)
260
    {
261
        $this->extension->validateMask($mask, new BusinessUnit());
262
    }
263
264
    /**
265
     * @dataProvider validateMaskForBusinessUnitInvalidProvider
266
     * @expectedException \Oro\Bundle\SecurityBundle\Acl\Exception\InvalidAclMaskException
267
     *
268
     * @param int $mask
269
     */
270
    public function testValidateMaskForBusinessUnitInvalid($mask)
271
    {
272
        $this->extension->validateMask($mask, new BusinessUnit());
273
    }
274
275
    /**
276
     * @dataProvider validateMaskForUserProvider
277
     *
278
     * @param int $mask
279
     */
280
    public function testValidateMaskForUser($mask)
281
    {
282
        $this->extension->validateMask($mask, new User());
283
    }
284
285
    /**
286
     * @dataProvider validateMaskForUserInvalidProvider
287
     * @expectedException \Oro\Bundle\SecurityBundle\Acl\Exception\InvalidAclMaskException
288
     *
289
     * @param int $mask
290
     */
291
    public function testValidateMaskForUserInvalid($mask)
292
    {
293
        $this->extension->validateMask($mask, new User());
294
    }
295
296
    /**
297
     * @dataProvider validateMaskForOrganizationOwnedProvider
298
     *
299
     * @param int $mask
300
     */
301
    public function testValidateMaskForOrganizationOwned($mask)
302
    {
303
        $this->metadataProvider->setMetadata(
304
            'Oro\Bundle\SecurityBundle\Tests\Unit\Acl\Domain\Fixtures\Entity\TestEntity',
305
            new OwnershipMetadata('ORGANIZATION', 'owner', 'owner_id')
306
        );
307
        $this->extension->validateMask($mask, new TestEntity());
308
    }
309
310
    /**
311
     * @dataProvider validateMaskForOrganizationOwnedInvalidProvider
312
     * @expectedException \Oro\Bundle\SecurityBundle\Acl\Exception\InvalidAclMaskException
313
     *
314
     * @param int $mask
315
     */
316
    public function testValidateMaskForOrganizationOwnedInvalid($mask)
317
    {
318
        $this->metadataProvider->setMetadata(
319
            'Oro\Bundle\SecurityBundle\Tests\Unit\Acl\Domain\Fixtures\Entity\TestEntity',
320
            new OwnershipMetadata('ORGANIZATION', 'owner', 'owner_id')
321
        );
322
        $this->extension->validateMask($mask, new TestEntity());
323
    }
324
325
    /**
326
     * @dataProvider validateMaskForUserOwnedProvider
327
     *
328
     * @param int $mask
329
     */
330
    public function testValidateMaskForUserOwned($mask)
331
    {
332
        $this->metadataProvider->setMetadata(
333
            'Oro\Bundle\SecurityBundle\Tests\Unit\Acl\Domain\Fixtures\Entity\TestEntity',
334
            new OwnershipMetadata('USER', 'owner', 'owner_id')
335
        );
336
        $this->extension->validateMask($mask, new TestEntity());
337
    }
338
339
    /**
340
     * @dataProvider validateMaskForUserOwnedInvalidProvider
341
     * @expectedException \Oro\Bundle\SecurityBundle\Acl\Exception\InvalidAclMaskException
342
     *
343
     * @param int $mask
344
     */
345
    public function testValidateMaskForUserOwnedInvalid($mask)
346
    {
347
        $this->metadataProvider->setMetadata(
348
            'Oro\Bundle\SecurityBundle\Tests\Unit\Acl\Domain\Fixtures\Entity\TestEntity',
349
            new OwnershipMetadata('USER', 'owner', 'owner_id')
350
        );
351
        $this->extension->validateMask($mask, new TestEntity());
352
    }
353
354
    /**
355
     * @dataProvider validateMaskForUserOwnedProvider
356
     *
357
     * @param int $mask
358
     */
359
    public function testValidateMaskForRoot($mask)
360
    {
361
        $this->extension->validateMask($mask, new ObjectIdentity('entity', ObjectIdentityFactory::ROOT_IDENTITY_TYPE));
362
    }
363
364
    /**
365
     * @dataProvider validateMaskForUserOwnedInvalidProvider
366
     * @expectedException \Oro\Bundle\SecurityBundle\Acl\Exception\InvalidAclMaskException
367
     *
368
     * @param int $mask
369
     */
370
    public function testValidateMaskForRootInvalid($mask)
371
    {
372
        $this->extension->validateMask($mask, new ObjectIdentity('entity', ObjectIdentityFactory::ROOT_IDENTITY_TYPE));
373
    }
374
375
    public function testGetPermissions()
376
    {
377
        $this->assertEquals(
378
            ['VIEW', 'CREATE', 'EDIT', 'DELETE', 'ASSIGN', 'SHARE'],
379
            $this->extension->getPermissions()
380
        );
381
    }
382
383
    /**
384
     * @param array $inputData
385
     * @param array $expectedData
386
     *
387
     * @dataProvider getAllowedPermissionsProvider
388
     */
389
    public function testGetAllowedPermissions(array $inputData, array $expectedData)
390
    {
391
        $this->securityMetadataProvider->expects($this->any())
392
            ->method('getMetadata')
393
            ->with($inputData['type'])
394
            ->willReturn(new EntitySecurityMetadata('', '', '', '', $inputData['entityConfig']));
395
396
        if ($inputData['owner']) {
397
            $this->metadataProvider->setMetadata(
398
                'TestEntity1',
399
                new OwnershipMetadata('BUSINESS_UNIT', 'owner', 'owner_id')
400
            );
401
        }
402
403
        $isRootType = $inputData['type'] === ObjectIdentityFactory::ROOT_IDENTITY_TYPE;
404
405
        $this->permissionManager = $this->getMockBuilder('Oro\Bundle\SecurityBundle\Acl\Permission\PermissionManager')
406
            ->disableOriginalConstructor()
407
            ->getMock();
408
        $this->permissionManager->expects($isRootType ? $this->never() : $this->once())
409
            ->method('getPermissionsForEntity')
410
            ->with($inputData['type'], AclGroupProviderInterface::DEFAULT_SECURITY_GROUP)
411
            ->willReturn($inputData['permissions']);
412
        $this->permissionManager->expects($isRootType ? $this->once() : $this->never())
413
            ->method('getPermissionsForGroup')
414
            ->with(AclGroupProviderInterface::DEFAULT_SECURITY_GROUP)
415
            ->willReturn($inputData['permissions']);
416
        $this->permissionManager->expects($this->any())
417
            ->method('getPermissionsMap')
418
            ->willReturn([
419
                'VIEW'   => 1,
420
                'CREATE' => 2,
421
                'EDIT'   => 3,
422
                'DELETE' => 4,
423
                'ASSIGN' => 5,
424
                'SHARE'  => 6,
425
                'PERMISSION' => 7,
426
                'UNKNOWN' => 8,
427
            ]);
428
429
        /* @var $entityClassResolver EntityClassResolver|\PHPUnit_Framework_MockObject_MockObject  */
430
        $entityClassResolver = $this->getMockBuilder('Oro\Bundle\EntityBundle\ORM\EntityClassResolver')
431
            ->disableOriginalConstructor()
432
            ->getMock();
433
434
        $extension = new EntityAclExtension(
435
            new ObjectIdAccessor(),
436
            $entityClassResolver,
437
            $this->securityMetadataProvider,
438
            $this->metadataProvider,
439
            $this->decisionMaker,
440
            $this->permissionManager,
441
            $this->groupProvider
442
        );
443
444
        $this->assertEquals($expectedData, $extension->getAllowedPermissions(
445
            new ObjectIdentity('entity', $inputData['type'])
446
        ));
447
    }
448
449
    /**
450
     * @dataProvider decideIsGrantingProvider
451
     *
452
     * @param int $triggeredMask
453
     * @param User $user
454
     * @param Organization $organization
455
     * @param object $object
456
     * @param bool $expectedResult
457
     */
458
    public function testDecideIsGranting($triggeredMask, $user, $organization, $object, $expectedResult)
459
    {
460
        $this->buildTestTree();
461
462
        if ($object instanceof TestEntity && $object->getOwner() !== null) {
463
            $owner = $object->getOwner();
464
            if (is_a($owner, $this->metadataProvider->getGlobalLevelClass())) {
465
                $this->metadataProvider->setMetadata(
466
                    get_class($object),
467
                    new OwnershipMetadata('ORGANIZATION', 'owner', 'owner_id', 'organization')
468
                );
469
            } elseif (is_a($owner, $this->metadataProvider->getLocalLevelClass())) {
470
                $this->metadataProvider->setMetadata(
471
                    get_class($object),
472
                    new OwnershipMetadata('BUSINESS_UNIT', 'owner', 'owner_id', 'organization')
473
                );
474
            } elseif (is_a($owner, $this->metadataProvider->getBasicLevelClass())) {
475
                $this->metadataProvider->setMetadata(
476
                    get_class($object),
477
                    new OwnershipMetadata('USER', 'owner', 'owner_id', 'organization')
478
                );
479
            }
480
        }
481
482
        /** @var \PHPUnit_Framework_MockObject_MockObject|UsernamePasswordOrganizationToken $token */
483
        $token =
484
            $this->getMockBuilder('Oro\Bundle\SecurityBundle\Authentication\Token\UsernamePasswordOrganizationToken')
485
                ->disableOriginalConstructor()
486
                ->getMock();
487
        $token->expects($this->any())
488
            ->method('getOrganizationContext')
489
            ->will($this->returnValue($organization));
490
        $token->expects($this->any())
491
            ->method('getUser')
492
            ->will($this->returnValue($user));
493
494
        $this->assertEquals($expectedResult, $this->extension->decideIsGranting($triggeredMask, $object, $token));
495
    }
496
497
    /**
498
     * @dataProvider getMaskBuilderProvider
499
     *
500
     * @param string $permission
501
     * @param int $identity
502
     * @param array $permissions
503
     */
504
    public function testGetMaskBuilder($permission, $identity, array $permissions)
505
    {
506
        $this->assertEquals(
507
            new EntityMaskBuilder($identity, $permissions),
508
            $this->extension->getMaskBuilder($permission)
509
        );
510
    }
511
512
    /**
513
     * @return array
514
     */
515
    public function getMaskBuilderProvider()
516
    {
517
        return [
518
            ['permission' => 'VIEW', 'identity' => 0, 'permissions' => ['VIEW', 'CREATE', 'EDIT']],
519
            ['permission' => 'CREATE', 'identity' => 0, 'permissions' => ['VIEW', 'CREATE', 'EDIT']],
520
            ['permission' => 'EDIT', 'identity' => 0, 'permissions' => ['VIEW', 'CREATE', 'EDIT']],
521
            ['permission' => 'DELETE', 'identity' => 32768, 'permissions' => ['DELETE', 'ASSIGN', 'SHARE']],
522
            ['permission' => 'ASSIGN', 'identity' => 32768, 'permissions' => ['DELETE', 'ASSIGN', 'SHARE']],
523
            ['permission' => 'SHARE', 'identity' => 32768, 'permissions' => ['DELETE', 'ASSIGN', 'SHARE']],
524
        ];
525
    }
526
527
    public function testGetAllMaskBuilders()
528
    {
529
        $this->assertEquals(
530
            [
531
                new EntityMaskBuilder(0, ['VIEW', 'CREATE', 'EDIT']),
532
                new EntityMaskBuilder(32768, ['DELETE', 'ASSIGN', 'SHARE'])
533
            ],
534
            $this->extension->getAllMaskBuilders()
535
        );
536
    }
537
538
    /**
539
     * @dataProvider adaptRootMaskProvider
540
     *
541
     * @param object $object
542
     * @param string $ownerType
543
     * @param int $aceMask
544
     * @param int $expectedMask
545
     */
546
    public function testAdaptRootMask($object, $ownerType, $aceMask, $expectedMask)
547
    {
548
        if ($ownerType !== null) {
549
            $this->metadataProvider->setMetadata(
550
                'Oro\Bundle\SecurityBundle\Tests\Unit\Acl\Domain\Fixtures\Entity\TestEntity',
551
                new OwnershipMetadata($ownerType, 'owner', 'owner_id')
552
            );
553
        }
554
555
        $resultMask = $this->extension->adaptRootMask($aceMask, $object);
556
        $this->assertEquals(
557
            $expectedMask,
558
            $resultMask,
559
            sprintf(
560
                'Expected "%s" -> "%s"; Actual: "%s"',
561
                $this->extension->getMaskPattern($aceMask),
562
                $this->extension->getMaskPattern($expectedMask),
563
                $this->extension->getMaskPattern($resultMask)
564
            )
565
        );
566
    }
567
568
    /**
569
     * @dataProvider getAccessLevelProvider
570
     *
571
     * @param int $mask
572
     * @param int $expectedLevel
573
     * @param string $permission
574
     */
575
    public function testGetAccessLevel($mask, $expectedLevel, $permission = null)
576
    {
577
        $this->assertEquals($expectedLevel, $this->extension->getAccessLevel($mask, $permission));
578
    }
579
580
    public function getAccessLevelProvider()
581
    {
582
        return [
583
            [
584
                'mask' => 0 /* GROUP_NONE */,
585
                'expectedLevel' => AccessLevel::NONE_LEVEL
586
            ],
587
            [
588
                'mask' => 32768 /* GROUP_NONE */,
589
                'expectedLevel' => AccessLevel::NONE_LEVEL
590
            ],
591
            [
592
                'mask' => 1 << 4 /* MASK_VIEW_SYSTEM */,
593
                'expectedLevel' => AccessLevel::SYSTEM_LEVEL
594
            ],
595
            [
596
                'mask' => 1 << 3 /* GLOBAL_LEVEL */,
597
                'expectedLevel' => AccessLevel::GLOBAL_LEVEL
598
            ],
599
            [
600
                'mask' => 1 << 2 /* DEEP_LEVEL */,
601
                'expectedLevel' => AccessLevel::DEEP_LEVEL
602
            ],
603
            [
604
                'mask' => 1 << 1 /* LOCAL_LEVEL */,
605
                'expectedLevel' => AccessLevel::LOCAL_LEVEL
606
            ],
607
            [
608
                'mask' => 1 << 0 /* BASIC_LEVEL */,
609
                'expectedLevel' => AccessLevel::BASIC_LEVEL
610
            ],
611
            [
612
                'mask' => (1 << 4) /* MASK_VIEW_SYSTEM */ | (1 << 10) /* MASK_EDIT_BASIC */,
613
                'expectedLevel' => AccessLevel::SYSTEM_LEVEL,
614
                'permission' => 'VIEW'
615
            ],
616
            [
617
                'mask' => (1 << 4) /* MASK_VIEW_SYSTEM */ | (1 << 10) /* MASK_EDIT_BASIC */,
618
                'expectedLevel' => AccessLevel::BASIC_LEVEL,
619
                'permission' => 'EDIT'
620
            ],
621
            [
622
                'mask' => (1 << 4) /* MASK_VIEW_SYSTEM */ | (1 << 10) /* MASK_EDIT_BASIC */,
623
                'expectedLevel' => AccessLevel::NONE_LEVEL,
624
                'permission' => 'CREATE'
625
            ]
626
        ];
627
    }
628
629
    public function testGetAccessLevelNamesForRoot()
630
    {
631
        $object = new ObjectIdentity('entity', ObjectIdentityFactory::ROOT_IDENTITY_TYPE);
632
        $this->assertEquals(
633
            [
634
                0 => 'NONE',
635
                1 => 'BASIC',
636
                2 => 'LOCAL',
637
                3 => 'DEEP',
638
                5 => 'SYSTEM'
639
            ],
640
            $this->extension->getAccessLevelNames($object)
641
        );
642
    }
643
644
    /**
645
     * @param OwnershipMetadata $metadata
646
     * @param array $expected
647
     *
648
     * @dataProvider accessLevelProvider
649
     */
650
    public function testGetAccessLevelNamesForNonRoot(OwnershipMetadata $metadata, array $expected)
651
    {
652
        $object = new ObjectIdentity('entity', '\stdClass');
653
654
        $this->metadataProvider->setMetadata('\stdClass', $metadata);
655
656
        $this->assertEquals(
657
            $expected,
658
            $this->extension->getAccessLevelNames($object)
659
        );
660
    }
661
662
    /**
663
     * @return array
664
     */
665
    public function accessLevelProvider()
666
    {
667
        return [
668
            'without owner' => [new OwnershipMetadata(), [0 => 'NONE', 5 => 'SYSTEM']],
669
            'basic level owned' => [
670
                new OwnershipMetadata('USER', 'user', 'user_id'),
671
                [
672
                    0 => 'NONE',
673
                    1 => 'BASIC',
674
                    2 => 'LOCAL',
675
                    3 => 'DEEP',
676
                    4 => 'GLOBAL',
677
                ],
678
            ],
679
            'local level owned' => [
680
                new OwnershipMetadata('BUSINESS_UNIT', 'bu', 'bu_id'),
681
                [
682
                    0 => 'NONE',
683
                    2 => 'LOCAL',
684
                    3 => 'DEEP',
685
                    4 => 'GLOBAL',
686
                ],
687
            ],
688
            'global level owned' => [
689
                new OwnershipMetadata('ORGANIZATION', 'org', 'org_id'),
690
                [
691
                    0 => 'NONE',
692
                    4 => 'GLOBAL',
693
                ],
694
            ],
695
        ];
696
    }
697
698
    /**
699
     * @return array
700
     */
701
    public function getAllowedPermissionsProvider()
702
    {
703
        return [
704
            '(root)' => [
705
                'input' => [
706
                    'type' => ObjectIdentityFactory::ROOT_IDENTITY_TYPE,
707
                    'owner' => false,
708
                    'entityConfig' => [],
709
                    'permissions' => [
710
                        $this->getPermission(1, 'VIEW'),
711
                        $this->getPermission(2, 'CREATE'),
712
                        $this->getPermission(3, 'EDIT'),
713
                        $this->getPermission(4, 'DELETE'),
714
                        $this->getPermission(5, 'ASSIGN'),
715
                        $this->getPermission(6, 'SHARE'),
716
                        $this->getPermission(7, 'PERMISSION')
717
                    ],
718
                ],
719
                'expected' => ['VIEW', 'CREATE', 'EDIT', 'DELETE', 'ASSIGN', 'SHARE', 'PERMISSION'],
720
            ],
721
            'TestEntity1 + config' => [
722
                'input' => [
723
                    'type' => 'TestEntity1',
724
                    'owner' => false,
725
                    'entityConfig' => ['VIEW', 'CREATE', 'ASSIGN', 'SHARE', 'PERMISSION'],
726
                    'permissions' => [
727
                        $this->getPermission(1, 'VIEW'),
728
                        $this->getPermission(2, 'CREATE'),
729
                        $this->getPermission(3, 'ASSIGN'),
730
                        $this->getPermission(4, 'SHARE'),
731
                        $this->getPermission(5, 'PERMISSION')
732
                    ],
733
                ],
734
                'expected' => ['VIEW', 'CREATE', 'PERMISSION'],
735
            ],
736
            'TestEntity1 + config + owner' => [
737
                'input' => [
738
                    'type' => 'TestEntity1',
739
                    'owner' => true,
740
                    'entityConfig' => ['VIEW', 'CREATE', 'ASSIGN', 'SHARE', 'PERMISSION'],
741
                    'permissions' => [
742
                        $this->getPermission(1, 'VIEW'),
743
                        $this->getPermission(2, 'CREATE'),
744
                        $this->getPermission(3, 'ASSIGN'),
745
                        $this->getPermission(4, 'SHARE'),
746
                        $this->getPermission(5, 'PERMISSION')
747
                    ],
748
                ],
749
                'expected' => ['VIEW', 'CREATE', 'ASSIGN', 'SHARE', 'PERMISSION'],
750
            ],
751
            'TestEntity1 + empty owner' => [
752
                'input' => [
753
                    'type' => 'TestEntity1',
754
                    'owner' => false,
755
                    'entityConfig' => [],
756
                    'permissions' => [
757
                        $this->getPermission(1, 'VIEW'),
758
                        $this->getPermission(2, 'ASSIGN'),
759
                        $this->getPermission(3, 'SHARE'),
760
                        $this->getPermission(4, 'PERMISSION'),
761
                    ],
762
                ],
763
                'expected' => ['VIEW', 'PERMISSION'],
764
            ],
765
        ];
766
    }
767
768
    /**
769
     * @return array
770
     */
771
    public function decideIsGrantingProvider()
772
    {
773
        $org3 = new Organization('org3');
774
        $org4 = new Organization('org4');
775
776
        $bu3 = new BusinessUnit('bu3');
777
        $bu4 = new BusinessUnit('bu4');
778
        $bu41 = new BusinessUnit('bu41', $bu4);
779
        $bu411 = new BusinessUnit('bu411', $bu41);
780
781
        $user3 = new User('user3', $bu3);
782
        $user4 = new User('user4', $bu4);
783
        $user411 = new User('user411', $bu411);
784
785
        return [
786
            [1 << 4 /* MASK_VIEW_SYSTEM */, null, $org4, null, true],
787
            [1 << 3 /* MASK_VIEW_GLOBAL */, null, $org4, null, true],
788
            [1 << 2 /* MASK_VIEW_DEEP */, null, $org4, null, true],
789
            [1 << 1 /* MASK_VIEW_LOCAL */, null, $org4, null, true],
790
            [1 << 0 /* MASK_VIEW_BASIC */, null, $org4, null, true],
791
            [1 << 4 /* MASK_VIEW_SYSTEM */, null, $org4, 'foo', true],
792
            [1 << 3 /* MASK_VIEW_GLOBAL */, null, $org4, 'foo', true],
793
            [1 << 2 /* MASK_VIEW_DEEP */, null, $org4, 'foo', true],
794
            [1 << 1 /* MASK_VIEW_LOCAL */, null, $org4, 'foo', true],
795
            [1 << 0 /* MASK_VIEW_BASIC */, null, $org4, 'foo', true],
796
            [1 << 4 /* MASK_VIEW_SYSTEM */, null, $org4, new ObjectIdentity('test', 'foo'), true],
797
            [1 << 3 /* MASK_VIEW_GLOBAL */, null, $org4, new ObjectIdentity('test', 'foo'), true],
798
            [1 << 2 /* MASK_VIEW_DEEP */, null, $org4, new ObjectIdentity('test', 'foo'), true],
799
            [1 << 1 /* MASK_VIEW_LOCAL */, null, $org4, new ObjectIdentity('test', 'foo'), true],
800
            [1 << 0 /* MASK_VIEW_BASIC */, null, $org4, new ObjectIdentity('test', 'foo'), true],
801
            [1 << 4 /* MASK_VIEW_SYSTEM */, null, $org4, new TestEntity(1), true],
802
            [1 << 3 /* MASK_VIEW_GLOBAL */, null, $org4, new TestEntity(1), true],
803
            [1 << 2 /* MASK_VIEW_DEEP */, null, $org4, new TestEntity(1), true],
804
            [1 << 1 /* MASK_VIEW_LOCAL */, null, $org4, new TestEntity(1), true],
805
            [1 << 0 /* MASK_VIEW_BASIC */, null, $org4, new TestEntity(1), true],
806
            [1 << 3 /* MASK_VIEW_GLOBAL */, $user3, $org4, new TestEntity(1, $org3), false],
807
            [1 << 3 /* MASK_VIEW_GLOBAL */, $user4, $org4, new TestEntity(1, $org4), true],
808
            [1 << 3 /* MASK_VIEW_GLOBAL */, $user3, $org4, new TestEntity(1, $bu3, $org3), false],
809
            [1 << 3 /* MASK_VIEW_GLOBAL */, $user4, $org4, new TestEntity(1, $bu4, $org4), true],
810
            [1 << 3 /* MASK_VIEW_GLOBAL */, $user4, $org4, new TestEntity(1, $bu411, $org4), true],
811
            [1 << 2 /* MASK_VIEW_DEEP */, $user3, $org4, new TestEntity(1, $bu3, $org3), false],
812
            [1 << 2 /* MASK_VIEW_DEEP */, $user4, $org4, new TestEntity(1, $bu4, $org4), true],
813
            [1 << 2 /* MASK_VIEW_DEEP */, $user4, $org4, new TestEntity(1, $bu411, $org4), true],
814
            [1 << 1 /* MASK_VIEW_LOCAL */, $user3, $org4, new TestEntity(1, $bu3, $org3), false],
815
            [1 << 1 /* MASK_VIEW_LOCAL */, $user4, $org4, new TestEntity(1, $bu4, $org4), true],
816
            [1 << 1 /* MASK_VIEW_LOCAL */, $user4, $org4, new TestEntity(1, $bu411, $org4), false],
817
            [1 << 3 /* MASK_VIEW_GLOBAL */, $user3, $org4, new TestEntity(1, $user3, $org3), false],
818
            [1 << 3 /* MASK_VIEW_GLOBAL */, $user4, $org4, new TestEntity(1, $user4, $org4), true],
819
            [1 << 3 /* MASK_VIEW_GLOBAL */, $user4, $org4, new TestEntity(1, $user411, $org4), true],
820
            [1 << 3 /* MASK_VIEW_GLOBAL */, $user4, $org4, new TestEntity(1, $user3, $org3), false],
821
            [1 << 2 /* MASK_VIEW_DEEP */, $user3, $org4, new TestEntity(1, $user3, $org3), false],
822
            [1 << 2 /* MASK_VIEW_DEEP */, $user4, $org4, new TestEntity(1, $user4, $org4), true],
823
            [1 << 2 /* MASK_VIEW_DEEP */, $user4, $org4, new TestEntity(1, $user411, $org4), true],
824
            [1 << 2 /* MASK_VIEW_DEEP */, $user4, $org4, new TestEntity(1, $user3, $org4), false],
825
            [1 << 1 /* MASK_VIEW_LOCAL */, $user3, $org4, new TestEntity(1, $user3, $org3), false],
826
            [1 << 1 /* MASK_VIEW_LOCAL */, $user4, $org4, new TestEntity(1, $user4, $org4), true],
827
            [1 << 1 /* MASK_VIEW_LOCAL */, $user4, $org4, new TestEntity(1, $user411, $org4), false],
828
            [1 << 1 /* MASK_VIEW_LOCAL */, $user4, $org4, new TestEntity(1, $user3, $org3), false],
829
            [1 << 0 /* MASK_VIEW_BASIC */, $user3, $org4, new TestEntity(1, $user3, $org3), false],
830
            [1 << 0 /* MASK_VIEW_BASIC */, $user4, $org4, new TestEntity(1, $user4, $org4), true],
831
            [1 << 0 /* MASK_VIEW_BASIC */, $user4, $org4, new TestEntity(1, $user411, $org4), false],
832
            [1 << 0 /* MASK_VIEW_BASIC */, $user4, $org4, new TestEntity(1, $user3, $org3), false]
833
        ];
834
    }
835
836
    /**
837
     * @return array
838
     */
839
    public static function adaptRootMaskProvider()
840
    {
841
        return [
842
            [
843
                new TestEntity(),
844
                null,
845
                (1 << 4) /* MASK_VIEW_SYSTEM */ | (1 << 9) /* MASK_CREATE_SYSTEM */,
846
                (1 << 4) /* MASK_VIEW_SYSTEM */ | (1 << 9) /* MASK_CREATE_SYSTEM */
847
            ],
848
            [
849
                new TestEntity(),
850
                null,
851
                (1 << 0) /* MASK_VIEW_BASIC */ | (1 << 6) /* MASK_CREATE_LOCAL */,
852
                (1 << 4) /* MASK_VIEW_SYSTEM */ | (1 << 9) /* MASK_CREATE_SYSTEM */
853
            ],
854
            [
855
                new TestEntity(),
856
                null,
857
                ((1 << 9) | 32768) /* MASK_ASSIGN_SYSTEM */ | ((1 << 10) | 32768) /* MASK_SHARE_BASIC */,
858
                32768 /* GROUP_NONE */
859
            ],
860
            [
861
                new Organization(),
862
                null,
863
                (1 << 0) /* MASK_VIEW_BASIC */ | (1 << 6) /* MASK_CREATE_LOCAL */,
864
                (1 << 4) /* MASK_VIEW_SYSTEM */ | (1 << 9) /* MASK_CREATE_SYSTEM */
865
            ],
866
            [
867
                new BusinessUnit(),
868
                null,
869
                (1 << 0) /* MASK_VIEW_BASIC */ | (1 << 6) /* MASK_CREATE_LOCAL */,
870
                (1 << 1) /* MASK_VIEW_LOCAL */ | (1 << 6) /* MASK_CREATE_LOCAL */
871
            ],
872
            [
873
                new BusinessUnit(),
874
                null,
875
                (1 << 2) /* MASK_VIEW_DEEP */ | (1 << 6) /* MASK_CREATE_LOCAL */,
876
                (1 << 2) /* MASK_VIEW_DEEP */ | (1 << 6) /* MASK_CREATE_LOCAL */
877
            ],
878
            [
879
                new User(),
880
                null,
881
                (1 << 0) /* MASK_VIEW_BASIC */ | (1 << 6) /* MASK_CREATE_LOCAL */,
882
                (1 << 1) /* MASK_VIEW_LOCAL */ | (1 << 6) /* MASK_CREATE_LOCAL */
883
            ],
884
            [
885
                new TestEntity(),
886
                'ORGANIZATION',
887
                (1 << 4) /* MASK_VIEW_SYSTEM */ | (1 << 7) /* MASK_CREATE_DEEP */,
888
                (1 << 4) /* MASK_VIEW_SYSTEM */ | (1 << 8) /* MASK_CREATE_GLOBAL */
889
            ],
890
            [
891
                new TestEntity(),
892
                'BUSINESS_UNIT',
893
                (1 << 2) /* MASK_VIEW_DEEP */ | (1 << 5) /* MASK_CREATE_BASIC */,
894
                (1 << 2) /* MASK_VIEW_DEEP */ | (1 << 6) /* MASK_CREATE_LOCAL */
895
            ],
896
            [
897
                new TestEntity(),
898
                'USER',
899
                (1 << 3) /* MASK_VIEW_GLOBAL */ | (1 << 5) /* MASK_CREATE_BASIC */,
900
                (1 << 3) /* MASK_VIEW_GLOBAL */ | (1 << 5) /* MASK_CREATE_BASIC */
901
            ]
902
        ];
903
    }
904
905
    /**
906
     * @return array
907
     */
908 View Code Duplication
    public static function validateMaskForOrganizationProvider()
909
    {
910
        return [
911
            [1 << 4 /* MASK_VIEW_SYSTEM */],
912
            [1 << 9 /* MASK_CREATE_SYSTEM */],
913
            [1 << 14 /* MASK_EDIT_SYSTEM */],
914
            [(1 << 4) + 32768 /* MASK_DELETE_SYSTEM */],
915
            [(1 << 4) /* MASK_VIEW_SYSTEM */ | ((1 << 4) + 32768) /* MASK_DELETE_SYSTEM */],
916
        ];
917
    }
918
919
    /**
920
     * @return array
921
     */
922 View Code Duplication
    public static function validateMaskForOrganizationInvalidProvider()
923
    {
924
        return [
925
            [(1 << 9) + 32768 /*MASK_ASSIGN_SYSTEM*/],
926
            [(1 << 14) + 32768 /*MASK_SHARE_SYSTEM*/],
927
            [1 << 3 /*MASK_VIEW_GLOBAL*/],
928
            [1 << 2 /*MASK_VIEW_DEEP*/],
929
            [1 << 1 /*MASK_VIEW_LOCAL*/],
930
            [1 << 0 /*MASK_VIEW_BASIC*/]
931
        ];
932
    }
933
934
    /**
935
     * @return array
936
     */
937 View Code Duplication
    public static function validateMaskForBusinessUnitProvider()
938
    {
939
        return [
940
            [1 << 4 /* MASK_VIEW_SYSTEM */],
941
            [1 << 9 /* MASK_CREATE_SYSTEM */],
942
            [1 << 14 /* MASK_EDIT_SYSTEM */],
943
            [(1 << 4) + 32768 /* MASK_DELETE_SYSTEM */],
944
            [(1 << 9) + 32768 /* MASK_ASSIGN_SYSTEM */],
945
            [(1 << 14) + 32768 /* MASK_SHARE_SYSTEM */],
946
            [1 << 3 /* MASK_VIEW_GLOBAL */],
947
            [1 << 8 /* MASK_CREATE_GLOBAL */],
948
            [1 << 13 /* MASK_EDIT_GLOBAL */],
949
            [(1 << 3) + 32768 /* MASK_DELETE_GLOBAL */],
950
            [(1 << 8) + 32768 /* MASK_ASSIGN_GLOBAL */],
951
            [(1 << 13) + 32768 /* MASK_SHARE_GLOBAL */],
952
            [1 << 2 /* MASK_VIEW_DEEP */],
953
            [1 << 7 /* MASK_CREATE_DEEP */],
954
            [1 << 12 /* MASK_EDIT_DEEP */],
955
            [(1 << 2) + 32768 /* MASK_DELETE_DEEP */],
956
            [(1 << 7) + 32768 /* MASK_ASSIGN_DEEP */],
957
            [(1 << 12) + 32768 /* MASK_SHARE_DEEP */],
958
            [1 << 1 /* MASK_VIEW_LOCAL */],
959
            [1 << 6 /* MASK_CREATE_LOCAL */],
960
            [1 << 11 /* MASK_EDIT_LOCAL */],
961
            [(1 << 1) + 32768 /* MASK_DELETE_LOCAL */],
962
            [(1 << 6) + 32768 /* MASK_ASSIGN_LOCAL */],
963
            [(1 << 11) + 32768 /* MASK_SHARE_LOCAL */],
964
            [(1 << 4) /* MASK_VIEW_SYSTEM */ | (1 << 8) /* MASK_CREATE_GLOBAL */ | (1 << 12) /* MASK_EDIT_DEEP */],
965
            [(1 << 3) /* MASK_VIEW_GLOBAL */ | (1 << 7) /* MASK_CREATE_DEEP */ | (1 << 11) /* MASK_EDIT_LOCAL */]
966
        ];
967
    }
968
969
    /**
970
     * @return array
971
     */
972 View Code Duplication
    public static function validateMaskForBusinessUnitInvalidProvider()
973
    {
974
        return [
975
            [1 << 0 /* MASK_VIEW_BASIC */],
976
            [(1 << 4) /* MASK_VIEW_SYSTEM */ | (1 << 3) /* MASK_VIEW_GLOBAL */],
977
            [(1 << 3) /* MASK_VIEW_GLOBAL */ | (1 << 2) /* MASK_VIEW_DEEP */],
978
            [(1 << 2) /* MASK_VIEW_DEEP */ | (1 << 1) /* MASK_VIEW_LOCAL */]
979
        ];
980
    }
981
982
    /**
983
     * @return array
984
     */
985 View Code Duplication
    public static function validateMaskForUserProvider()
986
    {
987
        return [
988
            [1 << 4 /* MASK_VIEW_SYSTEM */],
989
            [1 << 9 /* MASK_CREATE_SYSTEM */],
990
            [1 << 14 /* MASK_EDIT_SYSTEM */],
991
            [(1 << 4) + 32768 /* MASK_DELETE_SYSTEM */],
992
            [(1 << 9) + 32768 /* MASK_ASSIGN_SYSTEM */],
993
            [(1 << 14) + 32768 /* MASK_SHARE_SYSTEM */],
994
            [1 << 3 /* MASK_VIEW_GLOBAL */],
995
            [1 << 8 /* MASK_CREATE_GLOBAL */],
996
            [1 << 13 /* MASK_EDIT_GLOBAL */],
997
            [(1 << 4) + 32768 /* MASK_DELETE_GLOBAL */],
998
            [(1 << 9) + 32768 /* MASK_ASSIGN_GLOBAL */],
999
            [(1 << 14) + 32768 /* MASK_SHARE_GLOBAL */],
1000
            [1 << 2 /* MASK_VIEW_DEEP */],
1001
            [1 << 7 /* MASK_CREATE_DEEP */],
1002
            [1 << 12 /* MASK_EDIT_DEEP */],
1003
            [(1 << 4) + 32768 /* MASK_DELETE_DEEP */],
1004
            [(1 << 9) + 32768 /* MASK_ASSIGN_DEEP */],
1005
            [(1 << 14) + 32768 /* MASK_SHARE_DEEP */],
1006
            [1 << 1 /* MASK_VIEW_LOCAL */],
1007
            [1 << 6 /* MASK_CREATE_LOCAL */],
1008
            [1 << 11 /* MASK_EDIT_LOCAL */],
1009
            [(1 << 4) + 32768 /* MASK_DELETE_LOCAL */],
1010
            [(1 << 9) + 32768 /* MASK_ASSIGN_LOCAL */],
1011
            [(1 << 14) + 32768 /* MASK_SHARE_LOCAL */],
1012
            [(1 << 4) /* MASK_VIEW_SYSTEM */ | (1 << 8) /* MASK_CREATE_GLOBAL */ | (1 << 12) /* MASK_EDIT_DEEP */],
1013
            [(1 << 3) /* MASK_VIEW_GLOBAL */ | (1 << 7) /* MASK_CREATE_DEEP */ | (1 << 11) /* MASK_EDIT_LOCAL */]
1014
        ];
1015
    }
1016
1017
    /**
1018
     * @return array
1019
     */
1020 View Code Duplication
    public static function validateMaskForUserInvalidProvider()
1021
    {
1022
        return [
1023
            [1 << 0 /* MASK_VIEW_BASIC */],
1024
            [(1 << 4) /* MASK_VIEW_SYSTEM */ | (1 << 3) /* MASK_VIEW_GLOBAL */],
1025
            [(1 << 3) /* MASK_VIEW_GLOBAL */ | (1 << 2) /* MASK_VIEW_DEEP */],
1026
            [(1 << 2) /* MASK_VIEW_DEEP */ | (1 << 1) /* MASK_VIEW_LOCAL */]
1027
        ];
1028
    }
1029
1030
    /**
1031
     * @return array
1032
     */
1033
    public static function validateMaskForUserOwnedProvider()
1034
    {
1035
        return [
1036
            [1 << 4 /* MASK_VIEW_SYSTEM */],
1037
            [1 << 9 /* MASK_CREATE_SYSTEM */],
1038
            [1 << 14 /* MASK_EDIT_SYSTEM */],
1039
            [(1 << 4) + 32768 /* MASK_DELETE_SYSTEM */],
1040
            [(1 << 9) + 32768 /* MASK_ASSIGN_SYSTEM */],
1041
            [(1 << 14) + 32768 /* MASK_SHARE_SYSTEM */],
1042
            [1 << 3 /* MASK_VIEW_GLOBAL */],
1043
            [1 << 8 /* MASK_CREATE_GLOBAL */],
1044
            [1 << 13 /* MASK_EDIT_GLOBAL */],
1045
            [(1 << 4) + 32768 /* MASK_DELETE_GLOBAL */],
1046
            [(1 << 9) + 32768 /* MASK_ASSIGN_GLOBAL */],
1047
            [(1 << 14) + 32768 /* MASK_SHARE_GLOBAL */],
1048
            [1 << 2 /* MASK_VIEW_DEEP */],
1049
            [1 << 7 /* MASK_CREATE_DEEP */],
1050
            [1 << 12 /* MASK_EDIT_DEEP */],
1051
            [(1 << 4) + 32768 /* MASK_DELETE_DEEP */],
1052
            [(1 << 9) + 32768 /* MASK_ASSIGN_DEEP */],
1053
            [(1 << 14) + 32768 /* MASK_SHARE_DEEP */],
1054
            [1 << 1 /* MASK_VIEW_LOCAL */],
1055
            [1 << 6 /* MASK_CREATE_LOCAL */],
1056
            [1 << 11 /* MASK_EDIT_LOCAL */],
1057
            [(1 << 4) + 32768 /* MASK_DELETE_LOCAL */],
1058
            [(1 << 9) + 32768 /* MASK_ASSIGN_LOCAL */],
1059
            [(1 << 14) + 32768 /* MASK_SHARE_LOCAL */],
1060
            [1 << 0 /* MASK_VIEW_BASIC */],
1061
            [1 << 5 /* MASK_CREATE_BASIC */],
1062
            [1 << 10 /* MASK_EDIT_BASIC */],
1063
            [(1 << 0) + 32768 /* MASK_DELETE_BASIC */],
1064
            [(1 << 5) + 32768 /* MASK_ASSIGN_BASIC */],
1065
            [(1 << 10) + 32768 /* MASK_SHARE_BASIC */],
1066
            [(1 << 4) /* MASK_VIEW_SYSTEM */ | (1 << 8) /* MASK_CREATE_GLOBAL */ | (1 << 12) /* MASK_EDIT_DEEP */],
1067
            [(1 << 3) /* MASK_VIEW_GLOBAL */ | (1 << 7) /* MASK_CREATE_DEEP */ | (1 << 11) /* MASK_EDIT_LOCAL */],
1068
            [(1 << 2) /* MASK_VIEW_DEEP */ | (1 << 6) /* MASK_CREATE_LOCAL */ | (1 << 10) /* MASK_EDIT_BASIC */]
1069
        ];
1070
    }
1071
1072
    /**
1073
     * @return array
1074
     */
1075 View Code Duplication
    public static function validateMaskForUserOwnedInvalidProvider()
1076
    {
1077
        return [
1078
            [(1 << 4) /* MASK_VIEW_SYSTEM */ | (1 << 3) /* MASK_VIEW_GLOBAL */],
1079
            [(1 << 3) /* MASK_VIEW_GLOBAL */ | (1 << 2) /* MASK_VIEW_DEEP */],
1080
            [(1 << 2) /* MASK_VIEW_DEEP */ | (1 << 1) /* MASK_VIEW_LOCAL */],
1081
            [(1 << 1) /* MASK_VIEW_LOCAL */ | (1 << 0) /* MASK_VIEW_BASIC */]
1082
        ];
1083
    }
1084
1085
    /**
1086
     * @return array
1087
     */
1088
    public static function validateMaskForOrganizationOwnedProvider()
1089
    {
1090
        return [
1091
            [1 << 4 /* MASK_VIEW_SYSTEM */],
1092
            [1 << 9 /* MASK_CREATE_SYSTEM */],
1093
            [1 << 14 /* MASK_EDIT_SYSTEM */],
1094
            [(1 << 4) + 32768 /* MASK_DELETE_SYSTEM */],
1095
            [(1 << 9) + 32768 /* MASK_ASSIGN_SYSTEM */],
1096
            [(1 << 14) + 32768 /* MASK_SHARE_SYSTEM */],
1097
            [1 << 3 /* MASK_VIEW_GLOBAL */],
1098
            [1 << 8 /* MASK_CREATE_GLOBAL */],
1099
            [1 << 13 /* MASK_EDIT_GLOBAL */],
1100
            [(1 << 4) + 32768 /* MASK_DELETE_GLOBAL */],
1101
            [(1 << 9) + 32768 /* MASK_ASSIGN_GLOBAL */],
1102
            [(1 << 14) + 32768 /* MASK_SHARE_GLOBAL */],
1103
            [(1 << 4) /* MASK_VIEW_SYSTEM */ | (1 << 8) /* MASK_CREATE_GLOBAL */]
1104
        ];
1105
    }
1106
1107 View Code Duplication
    public static function validateMaskForOrganizationOwnedInvalidProvider()
1108
    {
1109
        return [
1110
            [1 << 2 /* MASK_VIEW_DEEP */],
1111
            [1 << 1 /* MASK_VIEW_LOCAL */],
1112
            [1 << 0 /* MASK_VIEW_BASIC */],
1113
            [(1 << 4) /* MASK_VIEW_SYSTEM */ | (1 << 3) /* MASK_VIEW_GLOBAL */],
1114
            [(1 << 3) /* MASK_VIEW_GLOBAL */ | (1 << 2) /* MASK_VIEW_DEEP */]
1115
        ];
1116
    }
1117
1118
    /**
1119
     * @dataProvider supportsDataProvider
1120
     *
1121
     * @param mixed $id
1122
     * @param string $type
1123
     * @param string $class
1124
     * @param bool $isEntity
1125
     * @param bool $expected
1126
     */
1127
    public function testSupports($id, $type, $class, $isEntity, $expected)
1128
    {
1129
        /** @var \PHPUnit_Framework_MockObject_MockObject|EntityClassResolver $entityClassResolverMock */
1130
        $entityClassResolverMock = $this->getMockBuilder('Oro\Bundle\EntityBundle\ORM\EntityClassResolver')
1131
            ->disableOriginalConstructor()
1132
            ->getMock();
1133
        $entityClassResolverMock->expects($isEntity ? $this->once() : $this->never())
1134
            ->method('getEntityClass')
1135
            ->with($class)
1136
            ->willReturn($class);
1137
        $entityClassResolverMock->expects($this->once())
1138
            ->method('isEntity')
1139
            ->with($class)
1140
            ->willReturn($expected);
1141
1142
        /** @var \PHPUnit_Framework_MockObject_MockObject|EntitySecurityMetadataProvider $entityMetadataProvider */
1143
        $entityMetadataProvider = $this
1144
            ->getMockBuilder('Oro\Bundle\SecurityBundle\Metadata\EntitySecurityMetadataProvider')
1145
            ->disableOriginalConstructor()
1146
            ->getMock();
1147
1148
        $extension = new EntityAclExtension(
1149
            new ObjectIdAccessor(),
1150
            $entityClassResolverMock,
1151
            $entityMetadataProvider,
1152
            $this->metadataProvider,
1153
            $this->decisionMaker,
1154
            $this->permissionManager,
1155
            $this->groupProvider
1156
        );
1157
1158
        $this->assertEquals($expected, $extension->supports($type, $id));
1159
    }
1160
1161
    /**
1162
     * @return array
1163
     */
1164
    public function supportsDataProvider()
1165
    {
1166
        return [
1167
            [
1168
                'id' => 'action',
1169
                'type' => '\stdClass',
1170
                'class' => '\stdClass',
1171
                'isEntity' => false,
1172
                'expected' => false
1173
            ],
1174
            [
1175
                'id' => 'entity',
1176
                'type' => '\stdClass',
1177
                'class' => '\stdClass',
1178
                'isEntity' => true,
1179
                'expected' => true
1180
            ],
1181
            [
1182
                'id' => 'entity',
1183
                'type' => '@\stdClass',
1184
                'class' => '\stdClass',
1185
                'isEntity' => true,
1186
                'expected' => true
1187
            ],
1188
            [
1189
                'id' => 'entity',
1190
                'type' => 'group@\stdClass',
1191
                'class' => '\stdClass',
1192
                'isEntity' => true,
1193
                'expected' => true
1194
            ]
1195
        ];
1196
    }
1197
1198
    /**
1199
     * @dataProvider getObjectIdentityDataProvider
1200
     *
1201
     * @param mixed $val
1202
     * @param ObjectIdentity $expected
1203
     */
1204
    public function testGetObjectIdentity($val, $expected)
1205
    {
1206
        $this->assertEquals($expected, $this->extension->getObjectIdentity($val));
1207
    }
1208
1209
    /**
1210
     * @return array
1211
     */
1212
    public function getObjectIdentityDataProvider()
1213
    {
1214
        $annotation = new AclAnnotation([
1215
            'id' => 'test_id',
1216
            'type' => 'entity',
1217
            'permission' => 'VIEW',
1218
            'class' => '\stdClass'
1219
        ]);
1220
1221
        $annotation2 = new AclAnnotation([
1222
            'id' => 'test_id',
1223
            'type' => 'entity',
1224
            'permission' => 'VIEW',
1225
            'class' => '\stdClass',
1226
            'group_name' => 'group'
1227
        ]);
1228
1229
        $domainObject = new Stub\DomainObjectStub();
1230
1231
        return [
1232
            [
1233
                'val' => 'entity:\stdClass',
1234
                'expected' => new ObjectIdentity('entity', '\stdClass')
1235
            ],
1236
            [
1237
                'val' => 'entity:group@\stdClass',
1238
                'expected' => new ObjectIdentity('entity', 'group@\stdClass')
1239
            ],
1240
            [
1241
                'val' => 'entity:@\stdClass',
1242
                'expected' => new ObjectIdentity('entity', '\stdClass')
1243
            ],
1244
            [
1245
                'val' => $annotation,
1246
                'expected' => new ObjectIdentity('entity', '\stdClass')
1247
            ],
1248
            [
1249
                'val' => $annotation2,
1250
                'expected' => new ObjectIdentity('entity', 'group@\stdClass')
1251
            ],
1252
            [
1253
                'val' => $domainObject,
1254
                'expected' => new ObjectIdentity(
1255
                    Stub\DomainObjectStub::IDENTIFIER,
1256
                    ClassUtils::getRealClass($domainObject)
1257
                ),
1258
            ]
1259
        ];
1260
    }
1261
1262
    /**
1263
     * @param string $id
1264
     * @param string $name
1265
     * @return Permission
1266
     */
1267 View Code Duplication
    protected function getPermission($id, $name)
1268
    {
1269
        $permission = new Permission();
1270
1271
        $reflection = new \ReflectionClass('Oro\Bundle\SecurityBundle\Entity\Permission');
1272
        $reflectionProperty = $reflection->getProperty('id');
1273
        $reflectionProperty->setAccessible(true);
1274
        $reflectionProperty->setValue($permission, $id);
1275
1276
        $permission->setName($name);
1277
1278
        return $permission;
1279
    }
1280
1281
    /**
1282
     * @return \PHPUnit_Framework_MockObject_MockObject|PermissionManager
1283
     */
1284 View Code Duplication
    protected function getPermissionManagerMock()
1285
    {
1286
        $mock = $this->getMockBuilder('Oro\Bundle\SecurityBundle\Acl\Permission\PermissionManager')
1287
            ->disableOriginalConstructor()
1288
            ->getMock();
1289
        $mock->expects($this->any())
1290
            ->method('getPermissionsMap')
1291
            ->willReturn([
1292
                'VIEW'   => 1,
1293
                'CREATE' => 2,
1294
                'EDIT'   => 3,
1295
                'DELETE' => 4,
1296
                'ASSIGN' => 5,
1297
                'SHARE'  => 6
1298
            ]);
1299
1300
        return $mock;
1301
    }
1302
}
1303