/** * Applies ACL conditions to the search query * * @param Query $query * @param string $permission * * @return Query */ public function apply(Query $query, $permission = 'VIEW') { $querySearchAliases = $this->getSearchAliases($query); $allowedAliases = []; $ownerExpressions = []; $expr = $query->getCriteria()->expr(); if (count($querySearchAliases) !== 0) { foreach ($querySearchAliases as $entityAlias) { $className = $this->mappingProvider->getEntityClass($entityAlias); if ($className) { $ownerField = sprintf('%s_owner', $entityAlias); $condition = $this->ownershipDataBuilder->getAclConditionData($className, $permission); if (count($condition) === 0 || !($condition[0] === null && $condition[3] === null)) { $allowedAliases[] = $entityAlias; // in case if we should not limit data for entity if (count($condition) === 0 || $condition[1] === null) { $ownerExpressions[] = $expr->gte('integer.' . $ownerField, SearchListener::EMPTY_OWNER_ID); continue; } $owners = !empty($condition[1]) ? $condition[1] : SearchListener::EMPTY_OWNER_ID; $ownerExpressions[] = !is_array($owners) || count($owners) === 1 ? $expr->eq('integer.' . $ownerField, $owners) : $expr->in('integer.' . $ownerField, $owners); } } } } if (count($ownerExpressions) !== 0) { $query->getCriteria()->andWhere(new CompositeExpression(CompositeExpression::TYPE_OR, $ownerExpressions)); } $query->from($allowedAliases); $this->addOrganizationLimits($query, $expr); return $query; }
/** * @dataProvider buildFilterConstraintProvider */ public function testGetAclConditionData($userId, $organizationId, $isGranted, $accessLevel, $ownerType, $targetEntityClassName, $expectedConstraint, $expectedGroup = '') { $this->buildTestTree(); if ($ownerType !== null) { $this->metadataProvider->setMetadata(self::TEST_ENTITY, new OwnershipMetadata($ownerType, 'owner', 'owner_id', 'organization', 'organization_id')); } /** @var OneShotIsGrantedObserver $aclObserver */ $aclObserver = null; $this->aclVoter->expects($this->any())->method('addOneShotIsGrantedObserver')->will($this->returnCallback(function ($observer) use(&$aclObserver, &$accessLevel) { $aclObserver = $observer; /** @var OneShotIsGrantedObserver $aclObserver */ $aclObserver->setAccessLevel($accessLevel); })); $user = new User($userId); $organization = new Organization($organizationId); $user->addOrganization($organization); $token = $this->getMockBuilder('Oro\\Bundle\\SecurityBundle\\Authentication\\Token\\UsernamePasswordOrganizationToken')->disableOriginalConstructor()->getMock(); $token->expects($this->any())->method('getUser')->will($this->returnValue($user)); $token->expects($this->any())->method('getOrganizationContext')->will($this->returnValue($organization)); /** @var \PHPUnit_Framework_MockObject_MockObject|AclGroupProviderInterface $aclGroupProvider */ $aclGroupProvider = $this->getMock('Oro\\Bundle\\SecurityBundle\\Acl\\Group\\AclGroupProviderInterface'); $aclGroupProvider->expects($this->any())->method('getGroup')->willReturn($expectedGroup); $this->builder->setAclGroupProvider($aclGroupProvider); $this->securityContext->expects($this->any())->method('isGranted')->with($this->equalTo('VIEW'), $this->callback(function (ObjectIdentity $identity) use($targetEntityClassName, $expectedGroup) { $this->assertEquals('entity', $identity->getIdentifier()); $this->assertStringEndsWith($targetEntityClassName, $identity->getType()); if ($expectedGroup) { $this->assertStringStartsWith($expectedGroup, $identity->getType()); } return true; }))->will($this->returnValue($isGranted)); $this->securityContext->expects($this->any())->method('getToken')->will($this->returnValue($userId ? $token : null)); $result = $this->builder->getAclConditionData($targetEntityClassName); $this->assertEquals($expectedConstraint, $result); }
/** * Process where statement * * @param RangeVariableDeclaration $rangeVariableDeclaration * @param $permission * @param bool $isJoin * @return null|AclCondition|JoinAclCondition */ protected function processRangeVariableDeclaration(RangeVariableDeclaration $rangeVariableDeclaration, $permission, $isJoin = false) { $this->addEntityAlias($rangeVariableDeclaration); $entityName = $rangeVariableDeclaration->abstractSchemaName; $entityAlias = $rangeVariableDeclaration->aliasIdentificationVariable; $resultData = $this->builder->getAclConditionData($entityName, $permission); if ($resultData === null || !empty($resultData)) { $entityField = $value = null; if (!empty($resultData)) { list($entityField, $value) = $resultData; } if ($isJoin) { return new JoinAclCondition($entityAlias, $entityField, $value); } else { return new AclCondition($entityAlias, $entityField, $value); } } return null; }
/** * @dataProvider buildFilterConstraintProvider */ public function testGetAclConditionData($userId, $isGranted, $accessLevel, $ownerType, $targetEntityClassName, $targetTableAlias, $expectedConstraint) { $this->buildTestTree(); if ($ownerType !== null) { $this->metadataProvider->setMetadata(self::TEST_ENTITY, new OwnershipMetadata($ownerType, 'owner', 'owner_id')); } /** @var OneShotIsGrantedObserver $aclObserver */ $aclObserver = null; $this->aclVoter->expects($this->any())->method('addOneShotIsGrantedObserver')->will($this->returnCallback(function ($observer) use(&$aclObserver, &$accessLevel) { $aclObserver = $observer; /** @var OneShotIsGrantedObserver $aclObserver */ $aclObserver->setAccessLevel($accessLevel); })); $user = new User($userId); $token = $this->getMock('Symfony\\Component\\Security\\Core\\Authentication\\Token\\TokenInterface'); $token->expects($this->any())->method('getUser')->will($this->returnValue($user)); $this->securityContext->expects($this->any())->method('isGranted')->with($this->equalTo('VIEW'), $this->equalTo('entity:' . $targetEntityClassName))->will($this->returnValue($isGranted)); $this->securityContext->expects($this->any())->method('getToken')->will($this->returnValue($userId ? $token : null)); $result = $this->builder->getAclConditionData($targetEntityClassName); $this->assertEquals($expectedConstraint, $result); }
/** * Process where statement * * @param RangeVariableDeclaration $rangeVariableDeclaration * @param string $permission * @param bool $isJoin * @param bool $isSubRequest * * @return null|AclCondition|JoinAclCondition */ protected function processRangeVariableDeclaration(RangeVariableDeclaration $rangeVariableDeclaration, $permission, $isJoin = false, $isSubRequest = false) { $this->addEntityAlias($rangeVariableDeclaration); $entityName = $rangeVariableDeclaration->abstractSchemaName; $entityAlias = $rangeVariableDeclaration->aliasIdentificationVariable; $isUserTable = in_array($rangeVariableDeclaration->abstractSchemaName, [self::ORO_USER_CLASS]); $resultData = false; if (!$isUserTable || $rangeVariableDeclaration->isRoot) { $resultData = $this->builder->getAclConditionData($entityName, $permission); } if ($resultData !== false && ($resultData === null || !empty($resultData))) { $entityField = $value = $pathExpressionType = $organizationField = $organizationValue = $ignoreOwner = null; if (!empty($resultData)) { list($entityField, $value, $pathExpressionType, $organizationField, $organizationValue, $ignoreOwner) = $resultData; } if ($isJoin) { return new JoinAclCondition($entityAlias, $entityField, $value, $pathExpressionType, $organizationField, $organizationValue, $ignoreOwner); } else { return new AclCondition($entityAlias, $entityField, $value, $pathExpressionType, $organizationField, $organizationValue, $ignoreOwner); } } return null; }