src/Acl/Doctrine/ORM/QueryExtension/EntityExtension.php
public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null)
    {
        if (!$this->entityCollection->contains($resourceClass)) {
            return;
        }

        $token = $this->tokenStorage->getToken();

        if (!$token) {
            throw new LogicException('Token is not defined.');
        }

        $user = $token->getUser();
        $permissions = $this->accessService->getPermissions($user);
        $rootAlias = $queryBuilder->getRootAliases()[0];
        $conditions = [];
        $parameters = [];
        $i = 0;

        foreach ($permissions as $permission) {
            if (Permission::ENTITY !== $permission->getType()) {
                // Skip permissions that are not of type "entity".
                continue;
            }

            if (!fnmatch($permission->getValue(), $resourceClass, FNM_NOESCAPE)) {
                // Skip permissions that are not related to the entity.
                // The fnmatch function is used to match asterisk patterns.
                continue;
            }

            if (!in_array(Permission::BROWSE, $permission->getAttributes(), true)) {
                // Skip permissions that do not have the required attribute.
                continue;
            }

            switch ($permission->getScope()) {
                case 'generic':
                    // This permission grants access to all entities of the class, no conditions need to be applied.
                    return;

                case 'object':
                    if (!in_array(Uuidentifiable::class, class_implements($resourceClass), true)) {
                        // Skip permissions with scope "object" if the entity is not uuidentifiable.
                        continue;
                    }

                    $conditions[] = $queryBuilder->expr()->eq($rootAlias.'.uuid', ':ds_security_uuid_'.$i);
                    $parameters['ds_security_uuid_'.$i] = $permission->getEntityUuid();
                    $i++;

                    break;

                case 'identity':
                    if (!in_array(Identitiable::class, class_implements($resourceClass), true)) {
                        // Skip permissions with scope "identity" if the entity is not identitiable.
                        continue;
                    }

                    if (in_array($resourceClass, [
                        'App\\Entity\\Anonymous',
                        'App\\Entity\\Individual',
                        'App\\Entity\\Organization',
                        'App\\Entity\\Staff'
                    ])) {
                        $conditions[] = $queryBuilder->expr()->eq($rootAlias.'.uuid', ':ds_security_identity_'.$i);
                        $parameters['ds_security_identity_'.$i] = $permission->getEntity();
                    } else if (in_array($resourceClass, [
                        'App\\Entity\\AnonymousPersona',
                        'App\\Entity\\IndividualPersona',
                        'App\\Entity\\OrganizationPersona',
                        'App\\Entity\\StaffPersona'
                    ])) {
                        $identity = substr($resourceClass, 0, -7);
                        $alias = strtolower(substr($resourceClass, 17, -7));
                        $subQueryBuilder = new QueryBuilder($queryBuilder->getEntityManager());
                        $conditions[] = $queryBuilder->expr()->in(
                            $rootAlias.'.'.$alias,
                            $subQueryBuilder
                                ->select($alias)
                                ->from($identity, $alias)
                                ->where($alias.'.uuid = :ds_security_identity_uuid_'.$i)
                                ->getDQL()
                        );
                        $parameters['ds_security_identity_uuid_'.$i] = $permission->getEntityUuid();
                    } else {
                        $conditions[] = $queryBuilder->expr()->andX(
                            $queryBuilder->expr()->eq($rootAlias.'.identity', ':ds_security_identity_'.$i),
                            $queryBuilder->expr()->eq($rootAlias.'.identityUuid', ':ds_security_identity_uuid_'.$i)
                        );
                        $parameters['ds_security_identity_'.$i] = $permission->getEntity();
                        $parameters['ds_security_identity_uuid_'.$i] = $permission->getEntityUuid();
                    }

                    $i++;

                    break;

                case 'owner':
                    if (!in_array(Ownable::class, class_implements($resourceClass), true)) {
                        // Skip permissions with scope "owner" if the entity is not ownable.
                        continue;
                    }

                    if (null === $permission->getEntityUuid()) {
                        $conditions[] = $queryBuilder->expr()->eq($rootAlias.'.owner', ':ds_security_owner_'.$i);
                        $parameters['ds_security_owner_'.$i] = $permission->getEntity();
                    } else {
                        $conditions[] = $queryBuilder->expr()->andX(
                            $queryBuilder->expr()->eq($rootAlias.'.owner', ':ds_security_owner_'.$i),
                            $queryBuilder->expr()->eq($rootAlias.'.ownerUuid', ':ds_security_owner_uuid_'.$i)
                        );
                        $parameters['ds_security_owner_'.$i] = $permission->getEntity();
                        $parameters['ds_security_owner_uuid_'.$i] = $permission->getEntityUuid();
                    }

                    $i++;

                    break;

                case 'session':
                    if (!in_array(Identitiable::class, class_implements($resourceClass), true)) {
                        // Skip permissions with scope "session" if the entity is not identitiable.
                        continue;
                    }

                    // @todo Refactor this exception handling at the entity level with metadata, the core should not know about these details.
                    if (in_array($resourceClass, [
                        'App\\Entity\\Anonymous',
                        'App\\Entity\\Individual',
                        'App\\Entity\\Organization',
                        'App\\Entity\\Staff'
                    ])) {
                        $conditions[] = $queryBuilder->expr()->eq($rootAlias.'.uuid', ':ds_security_identity_uuid_'.$i);
                        $parameters['ds_security_identity_uuid_'.$i] = $user->getIdentity()->getUuid();
                    } else if (in_array($resourceClass, [
                        'App\\Entity\\AnonymousPersona',
                        'App\\Entity\\IndividualPersona',
                        'App\\Entity\\OrganizationPersona',
                        'App\\Entity\\StaffPersona'
                    ])) {
                        $identity = substr($resourceClass, 0, -7);
                        $alias = strtolower(substr($resourceClass, 17, -7));
                        $subQueryBuilder = new QueryBuilder($queryBuilder->getEntityManager());
                        $conditions[] = $queryBuilder->expr()->in(
                            $rootAlias.'.'.$alias,
                            $subQueryBuilder
                                ->select($alias)
                                ->from($identity, $alias)
                                ->where($alias.'.uuid = :ds_security_identity_uuid_'.$i)
                                ->getDQL()
                        );
                        $parameters['ds_security_identity_uuid_'.$i] = $user->getIdentity()->getUuid();
                    } else {
                        $conditions[] = $queryBuilder->expr()->andX(
                            $queryBuilder->expr()->eq($rootAlias.'.identity', ':ds_security_identity_'.$i),
                            $queryBuilder->expr()->eq($rootAlias.'.identityUuid', ':ds_security_identity_uuid_'.$i)
                        );
                        $parameters['ds_security_identity_'.$i] = $user->getIdentity()->getType();
                        $parameters['ds_security_identity_uuid_'.$i] = $user->getIdentity()->getUuid();
                    }

                    $i++;

                    break;

                default:
                    // Skip permissions with unknown scopes. In theory, this case should never
                    // be selected unless there are data integrity issues.
                    // @todo Add notice logs
                    continue;
            }
        }

        if (!$conditions) {
            throw new NoPermissionsException;
        }

        $queryBuilder->andWhere(call_user_func_array([$queryBuilder->expr(), 'orX'], $conditions));

        foreach ($parameters as $key => $value) {
            $queryBuilder->setParameter($key, $value);
        }
    }
public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null)
    {
        if (!$this->entityCollection->contains($resourceClass)) {
            return;
        }

        $token = $this->tokenStorage->getToken();

        if (!$token) {
            throw new LogicException('Token is not defined.');
        }

        $user = $token->getUser();
        $permissions = $this->accessService->getPermissions($user);
        $rootAlias = $queryBuilder->getRootAliases()[0];
        $conditions = [];
        $parameters = [];
        $i = 0;

        foreach ($permissions as $permission) {
            if (Permission::ENTITY !== $permission->getType()) {
                // Skip permissions that are not of type "entity".
                continue;
            }

            if (!fnmatch($permission->getValue(), $resourceClass, FNM_NOESCAPE)) {
                // Skip permissions that are not related to the entity.
                // The fnmatch function is used to match asterisk patterns.
                continue;
            }

            if (!in_array(Permission::BROWSE, $permission->getAttributes(), true)) {
                // Skip permissions that do not have the required attribute.
                continue;
            }

            switch ($permission->getScope()) {
                case 'generic':
                    // This permission grants access to all entities of the class, no conditions need to be applied.
                    return;

                case 'object':
                    if (!in_array(Uuidentifiable::class, class_implements($resourceClass), true)) {
                        // Skip permissions with scope "object" if the entity is not uuidentifiable.
                        continue;
                    }

                    $conditions[] = $queryBuilder->expr()->eq($rootAlias.'.uuid', ':ds_security_uuid_'.$i);
                    $parameters['ds_security_uuid_'.$i] = $permission->getEntityUuid();
                    $i++;

                    break;

                case 'identity':
                    if (!in_array(Identitiable::class, class_implements($resourceClass), true)) {
                        // Skip permissions with scope "identity" if the entity is not identitiable.
                        continue;
                    }

                    if (in_array($resourceClass, [
                        'App\\Entity\\Anonymous',
                        'App\\Entity\\Individual',
                        'App\\Entity\\Organization',
                        'App\\Entity\\Staff'
                    ])) {
                        $conditions[] = $queryBuilder->expr()->eq($rootAlias.'.uuid', ':ds_security_identity_'.$i);
                        $parameters['ds_security_identity_'.$i] = $permission->getEntity();
                    } else if (in_array($resourceClass, [
                        'App\\Entity\\AnonymousPersona',
                        'App\\Entity\\IndividualPersona',
                        'App\\Entity\\OrganizationPersona',
                        'App\\Entity\\StaffPersona'
                    ])) {
                        $identity = substr($resourceClass, 0, -7);
                        $alias = strtolower(substr($resourceClass, 17, -7));
                        $subQueryBuilder = new QueryBuilder($queryBuilder->getEntityManager());
                        $conditions[] = $queryBuilder->expr()->in(
                            $rootAlias.'.'.$alias,
                            $subQueryBuilder
                                ->select($alias)
                                ->from($identity, $alias)
                                ->where($alias.'.uuid = :ds_security_identity_uuid_'.$i)
                                ->getDQL()
                        );
                        $parameters['ds_security_identity_uuid_'.$i] = $permission->getEntityUuid();
                    } else {
                        $conditions[] = $queryBuilder->expr()->andX(
                            $queryBuilder->expr()->eq($rootAlias.'.identity', ':ds_security_identity_'.$i),
                            $queryBuilder->expr()->eq($rootAlias.'.identityUuid', ':ds_security_identity_uuid_'.$i)
                        );
                        $parameters['ds_security_identity_'.$i] = $permission->getEntity();
                        $parameters['ds_security_identity_uuid_'.$i] = $permission->getEntityUuid();
                    }

                    $i++;

                    break;

                case 'owner':
                    if (!in_array(Ownable::class, class_implements($resourceClass), true)) {
                        // Skip permissions with scope "owner" if the entity is not ownable.
                        continue;
                    }

                    if (null === $permission->getEntityUuid()) {
                        $conditions[] = $queryBuilder->expr()->eq($rootAlias.'.owner', ':ds_security_owner_'.$i);
                        $parameters['ds_security_owner_'.$i] = $permission->getEntity();
                    } else {
                        $conditions[] = $queryBuilder->expr()->andX(
                            $queryBuilder->expr()->eq($rootAlias.'.owner', ':ds_security_owner_'.$i),
                            $queryBuilder->expr()->eq($rootAlias.'.ownerUuid', ':ds_security_owner_uuid_'.$i)
                        );
                        $parameters['ds_security_owner_'.$i] = $permission->getEntity();
                        $parameters['ds_security_owner_uuid_'.$i] = $permission->getEntityUuid();
                    }

                    $i++;

                    break;

                case 'session':
                    if (!in_array(Identitiable::class, class_implements($resourceClass), true)) {
                        // Skip permissions with scope "session" if the entity is not identitiable.
                        continue;
                    }

                    // @todo Refactor this exception handling at the entity level with metadata, the core should not know about these details.
                    if (in_array($resourceClass, [
                        'App\\Entity\\Anonymous',
                        'App\\Entity\\Individual',
                        'App\\Entity\\Organization',
                        'App\\Entity\\Staff'
                    ])) {
                        $conditions[] = $queryBuilder->expr()->eq($rootAlias.'.uuid', ':ds_security_identity_uuid_'.$i);
                        $parameters['ds_security_identity_uuid_'.$i] = $user->getIdentity()->getUuid();
                    } else if (in_array($resourceClass, [
                        'App\\Entity\\AnonymousPersona',
                        'App\\Entity\\IndividualPersona',
                        'App\\Entity\\OrganizationPersona',
                        'App\\Entity\\StaffPersona'
                    ])) {
                        $identity = substr($resourceClass, 0, -7);
                        $alias = strtolower(substr($resourceClass, 17, -7));
                        $subQueryBuilder = new QueryBuilder($queryBuilder->getEntityManager());
                        $conditions[] = $queryBuilder->expr()->in(
                            $rootAlias.'.'.$alias,
                            $subQueryBuilder
                                ->select($alias)
                                ->from($identity, $alias)
                                ->where($alias.'.uuid = :ds_security_identity_uuid_'.$i)
                                ->getDQL()
                        );
                        $parameters['ds_security_identity_uuid_'.$i] = $user->getIdentity()->getUuid();
                    } else {
                        $conditions[] = $queryBuilder->expr()->andX(
                            $queryBuilder->expr()->eq($rootAlias.'.identity', ':ds_security_identity_'.$i),
                            $queryBuilder->expr()->eq($rootAlias.'.identityUuid', ':ds_security_identity_uuid_'.$i)
                        );
                        $parameters['ds_security_identity_'.$i] = $user->getIdentity()->getType();
                        $parameters['ds_security_identity_uuid_'.$i] = $user->getIdentity()->getUuid();
                    }

                    $i++;

                    break;

                default:
                    // Skip permissions with unknown scopes. In theory, this case should never
                    // be selected unless there are data integrity issues.
                    // @todo Add notice logs
                    continue;
            }
        }

        if (!$conditions) {
            throw new NoPermissionsException;
        }

        $queryBuilder->andWhere(call_user_func_array([$queryBuilder->expr(), 'orX'], $conditions));

        foreach ($parameters as $key => $value) {
            $queryBuilder->setParameter($key, $value);
        }
    }
public function applyToCollection ( QueryBuilder $ queryBuilder , QueryNameGeneratorInterface $ queryNameGenerator , string $ resourceClass , string $ operationName = null ) { if ( ! $ this -> entityCollection -> contains ( $ resourceClass ) ) { return ; } $ token = $ this -> tokenStorage -> getToken ( ) ; if ( ! $ token ) { throw new LogicException ( 'Token is not defined.' ) ; } $ user = $ token -> getUser ( ) ; $ permissions = $ this -> accessService -> getPermissions ( $ user ) ; $ rootAlias = $ queryBuilder -> getRootAliases ( ) [ 0 ] ; $ conditions = [ ] ; $ parameters = [ ] ; $ i = 0 ; foreach ( $ permissions as $ permission ) { if ( Permission :: ENTITY !== $ permission -> getType ( ) ) { // Skip permissions that are not of type "entity". continue ; } if ( ! fnmatch ( $ permission -> getValue ( ) , $ resourceClass , FNM_NOESCAPE ) ) { // Skip permissions that are not related to the entity. // The fnmatch function is used to match asterisk patterns. continue ; } if ( ! in_array ( Permission :: BROWSE , $ permission -> getAttributes ( ) , true ) ) { // Skip permissions that do not have the required attribute. continue ; } switch ( $ permission -> getScope ( ) ) { case 'generic' : // This permission grants access to all entities of the class, no conditions need to be applied. return ; case 'object' : if ( ! in_array ( Uuidentifiable :: class , class_implements ( $ resourceClass ) , true ) ) { // Skip permissions with scope "object" if the entity is not uuidentifiable. continue ; } $ conditions [ ] = $ queryBuilder -> expr ( ) -> eq ( $ rootAlias . '.uuid' , ':ds_security_uuid_' . $ i ) ; $ parameters [ 'ds_security_uuid_' . $ i ] = $ permission -> getEntityUuid ( ) ; $ i ++ ; break ; case 'identity' : if ( ! in_array ( Identitiable :: class , class_implements ( $ resourceClass ) , true ) ) { // Skip permissions with scope "identity" if the entity is not identitiable. continue ; } if ( in_array ( $ resourceClass , [ 'App\\Entity\\Anonymous' , 'App\\Entity\\Individual' , 'App\\Entity\\Organization' , 'App\\Entity\\Staff' ] ) ) { $ conditions [ ] = $ queryBuilder -> expr ( ) -> eq ( $ rootAlias . '.uuid' , ':ds_security_identity_' . $ i ) ; $ parameters [ 'ds_security_identity_' . $ i ] = $ permission -> getEntity ( ) ; } else if ( in_array ( $ resourceClass , [ 'App\\Entity\\AnonymousPersona' , 'App\\Entity\\IndividualPersona' , 'App\\Entity\\OrganizationPersona' , 'App\\Entity\\StaffPersona' ] ) ) { $ identity = substr ( $ resourceClass , 0 , - 7 ) ; $ alias = strtolower ( substr ( $ resourceClass , 17 , - 7 ) ) ; $ subQueryBuilder = new QueryBuilder ( $ queryBuilder -> getEntityManager ( ) ) ; $ conditions [ ] = $ queryBuilder -> expr ( ) -> in ( $ rootAlias . '.' . $ alias , $ subQueryBuilder -> select ( $ alias ) -> from ( $ identity , $ alias ) -> where ( $ alias . '.uuid = :ds_security_identity_uuid_' . $ i ) -> getDQL ( ) ) ; $ parameters [ 'ds_security_identity_uuid_' . $ i ] = $ permission -> getEntityUuid ( ) ; } else { $ conditions [ ] = $ queryBuilder -> expr ( ) -> andX ( $ queryBuilder -> expr ( ) -> eq ( $ rootAlias . '.identity' , ':ds_security_identity_' . $ i ) , $ queryBuilder -> expr ( ) -> eq ( $ rootAlias . '.identityUuid' , ':ds_security_identity_uuid_' . $ i ) ) ; $ parameters [ 'ds_security_identity_' . $ i ] = $ permission -> getEntity ( ) ; $ parameters [ 'ds_security_identity_uuid_' . $ i ] = $ permission -> getEntityUuid ( ) ; } $ i ++ ; break ; case 'owner' : if ( ! in_array ( Ownable :: class , class_implements ( $ resourceClass ) , true ) ) { // Skip permissions with scope "owner" if the entity is not ownable. continue ; } if ( null === $ permission -> getEntityUuid ( ) ) { $ conditions [ ] = $ queryBuilder -> expr ( ) -> eq ( $ rootAlias . '.owner' , ':ds_security_owner_' . $ i ) ; $ parameters [ 'ds_security_owner_' . $ i ] = $ permission -> getEntity ( ) ; } else { $ conditions [ ] = $ queryBuilder -> expr ( ) -> andX ( $ queryBuilder -> expr ( ) -> eq ( $ rootAlias . '.owner' , ':ds_security_owner_' . $ i ) , $ queryBuilder -> expr ( ) -> eq ( $ rootAlias . '.ownerUuid' , ':ds_security_owner_uuid_' . $ i ) ) ; $ parameters [ 'ds_security_owner_' . $ i ] = $ permission -> getEntity ( ) ; $ parameters [ 'ds_security_owner_uuid_' . $ i ] = $ permission -> getEntityUuid ( ) ; } $ i ++ ; break ; case 'session' : if ( ! in_array ( Identitiable :: class , class_implements ( $ resourceClass ) , true ) ) { // Skip permissions with scope "session" if the entity is not identitiable. continue ; } // @todo Refactor this exception handling at the entity level with metadata, the core should not know about these details. if ( in_array ( $ resourceClass , [ 'App\\Entity\\Anonymous' , 'App\\Entity\\Individual' , 'App\\Entity\\Organization' , 'App\\Entity\\Staff' ] ) ) { $ conditions [ ] = $ queryBuilder -> expr ( ) -> eq ( $ rootAlias . '.uuid' , ':ds_security_identity_uuid_' . $ i ) ; $ parameters [ 'ds_security_identity_uuid_' . $ i ] = $ user -> getIdentity ( ) -> getUuid ( ) ; } else if ( in_array ( $ resourceClass , [ 'App\\Entity\\AnonymousPersona' , 'App\\Entity\\IndividualPersona' , 'App\\Entity\\OrganizationPersona' , 'App\\Entity\\StaffPersona' ] ) ) { $ identity = substr ( $ resourceClass , 0 , - 7 ) ; $ alias = strtolower ( substr ( $ resourceClass , 17 , - 7 ) ) ; $ subQueryBuilder = new QueryBuilder ( $ queryBuilder -> getEntityManager ( ) ) ; $ conditions [ ] = $ queryBuilder -> expr ( ) -> in ( $ rootAlias . '.' . $ alias , $ subQueryBuilder -> select ( $ alias ) -> from ( $ identity , $ alias ) -> where ( $ alias . '.uuid = :ds_security_identity_uuid_' . $ i ) -> getDQL ( ) ) ; $ parameters [ 'ds_security_identity_uuid_' . $ i ] = $ user -> getIdentity ( ) -> getUuid ( ) ; } else { $ conditions [ ] = $ queryBuilder -> expr ( ) -> andX ( $ queryBuilder -> expr ( ) -> eq ( $ rootAlias . '.identity' , ':ds_security_identity_' . $ i ) , $ queryBuilder -> expr ( ) -> eq ( $ rootAlias . '.identityUuid' , ':ds_security_identity_uuid_' . $ i ) ) ; $ parameters [ 'ds_security_identity_' . $ i ] = $ user -> getIdentity ( ) -> getType ( ) ; $ parameters [ 'ds_security_identity_uuid_' . $ i ] = $ user -> getIdentity ( ) -> getUuid ( ) ; } $ i ++ ; break ; default : // Skip permissions with unknown scopes. In theory, this case should never // be selected unless there are data integrity issues. // @todo Add notice logs continue ; } } if ( ! $ conditions ) { throw new NoPermissionsException ; } $ queryBuilder -> andWhere ( call_user_func_array ( [ $ queryBuilder -> expr ( ) , 'orX' ] , $ conditions ) ) ; foreach ( $ parameters as $ key => $ value ) { $ queryBuilder -> setParameter ( $ key , $ value ) ; } }
{@inheritdoc}
{