/** * Apply the ACL constraints to the specified query builder, using the permission definition * * @param QueryBuilder $queryBuilder The query builder * @param PermissionDefinition $permissionDef The permission definition * * @return QueryBuilder */ public function apply(QueryBuilder $queryBuilder, PermissionDefinition $permissionDef) { $aclConnection = $this->em->getConnection(); $databasePrefix = is_file($aclConnection->getDatabase()) ? '' : $aclConnection->getDatabase() . '.'; $rootEntity = $permissionDef->getEntity(); $linkAlias = $permissionDef->getAlias(); // Only tables with a single ID PK are currently supported $linkField = $this->em->getClassMetadata($rootEntity)->getSingleIdentifierColumnName(); $rootEntity = '"' . str_replace('\\', '\\\\', $rootEntity) . '"'; $query = $queryBuilder; $builder = new MaskBuilder(); foreach ($permissionDef->getPermissions() as $permission) { $mask = constant(get_class($builder) . '::MASK_' . strtoupper($permission)); $builder->add($mask); } $mask = $builder->get(); /* @var $token TokenInterface */ $token = $this->tokenStorage->getToken(); $userRoles = array(); if (!is_null($token)) { $user = $token->getUser(); $userRoles = $this->roleHierarchy->getReachableRoles($token->getRoles()); } // Security context does not provide anonymous role automatically. $uR = array('"IS_AUTHENTICATED_ANONYMOUSLY"'); /* @var $role RoleInterface */ foreach ($userRoles as $role) { // The reason we ignore this is because by default FOSUserBundle adds ROLE_USER for every user if ($role->getRole() !== 'ROLE_USER') { $uR[] = '"' . $role->getRole() . '"'; } } $uR = array_unique($uR); $inString = implode(' OR s.identifier = ', (array) $uR); if (is_object($user)) { $inString .= ' OR s.identifier = "' . str_replace('\\', '\\\\', get_class($user)) . '-' . $user->getUserName() . '"'; } $joinTableQuery = <<<SELECTQUERY SELECT DISTINCT o.object_identifier as id FROM {$databasePrefix}acl_object_identities as o INNER JOIN {$databasePrefix}acl_classes c ON c.id = o.class_id LEFT JOIN {$databasePrefix}acl_entries e ON ( e.class_id = o.class_id AND (e.object_identity_id = o.id OR {$aclConnection->getDatabasePlatform()->getIsNullExpression('e.object_identity_id')}) ) LEFT JOIN {$databasePrefix}acl_security_identities s ON ( s.id = e.security_identity_id ) WHERE c.class_type = {$rootEntity} AND (s.identifier = {$inString}) AND e.mask & {$mask} > 0 SELECTQUERY; $query->join($linkAlias, '(' . $joinTableQuery . ')', 'perms_', 'perms_.id = ' . $linkAlias . '.' . $linkField); return $query; }
/** * Apply the ACL constraints to the specified query builder, using the permission definition * * @param QueryBuilder $queryBuilder The query builder * @param PermissionDefinition $permissionDef The permission definition * * @return Query */ public function apply(QueryBuilder $queryBuilder, PermissionDefinition $permissionDef) { $whereQueryParts = $queryBuilder->getDQLPart('where'); if (empty($whereQueryParts)) { $queryBuilder->where('1 = 1'); // this will help in cases where no where query is specified } $query = $this->cloneQuery($queryBuilder->getQuery()); $builder = new MaskBuilder(); foreach ($permissionDef->getPermissions() as $permission) { $mask = constant(get_class($builder) . '::MASK_' . strtoupper($permission)); $builder->add($mask); } $query->setHint('acl.mask', $builder->get()); $query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Kunstmaan\\AdminBundle\\Helper\\Security\\Acl\\AclWalker'); $rootEntity = $permissionDef->getEntity(); $rootAlias = $permissionDef->getAlias(); // If either alias or entity was not specified - use default from QueryBuilder if (empty($rootEntity) || empty($rootAlias)) { $rootEntities = $queryBuilder->getRootEntities(); $rootAliases = $queryBuilder->getRootAliases(); $rootEntity = $rootEntities[0]; $rootAlias = $rootAliases[0]; } $query->setHint('acl.root.entity', $rootEntity); $query->setHint('acl.extra.query', $this->getPermittedAclIdsSQLForUser($query)); $classMeta = $this->em->getClassMetadata($rootEntity); $entityRootTableName = $this->quoteStrategy->getTableName($classMeta, $this->em->getConnection()->getDatabasePlatform()); $query->setHint('acl.entityRootTableName', $entityRootTableName); $query->setHint('acl.entityRootTableDqlAlias', $rootAlias); return $query; }
/** * @covers Kunstmaan\AdminBundle\Helper\Security\Acl\Permission\PermissionDefinition::setAlias * @covers Kunstmaan\AdminBundle\Helper\Security\Acl\Permission\PermissionDefinition::getAlias */ public function testSetGetAlias() { $this->object->setAlias('alias'); $this->assertEquals('alias', $this->object->getAlias()); }