oro-security

Installation
SKILL.md

OroCommerce v6.1 Security & ACL Configuration

Entity ACL Configuration

Place in Resources/config/oro/acls.yml:

acls:
    acme_demo_document_view:
        type: entity
        class: Acme\Bundle\DemoBundle\Entity\Document
        permission: VIEW
        description: View documents

    acme_demo_document_edit:
        type: entity
        class: Acme\Bundle\DemoBundle\Entity\Document
        permission: EDIT

Key structure: type: entity, class (FQCN), permission (VIEW, CREATE, EDIT, DELETE, ASSIGN, EXECUTE).

PHP 8 Acl Attribute

Declare ACL requirements directly on controller methods:

use Oro\Bundle\SecurityBundle\Attribute\Acl;

class DocumentController
{
    #[Acl(
        id: 'acme_demo_document_view',
        type: 'entity',
        class: 'Acme\Bundle\DemoBundle\Entity\Document',
        permission: 'VIEW'
    )]
    public function viewAction(Document $document)
    {
        // ACL is checked before this method executes
    }
}

Attributes are preferred over YAML bindings — they're colocated with the code they protect and type-safe.

Ownership and Organization

Ownership determines who can access an entity. Four scopes: USER, BUSINESS_UNIT, ORGANIZATION, GLOBAL.

CRITICAL: If ownership is USER or BUSINESS_UNIT, the entity MUST have an organization field. Missing it causes permission checks to fail silently.

Define in Resources/config/oro/entity.yml:

entities:
    Acme\Bundle\DemoBundle\Entity\Document:
        ownership:
            owner_type: USER
            owner_field_name: owner
            organization_field_name: organization

AclHelper: Query Filtering

ACL checks do NOT happen automatically on queries. You must explicitly apply filtering:

class DocumentRepository
{
    public function findApprovedDocuments(User $user)
    {
        $qb = $this->createQueryBuilder('d')
            ->where('d.status = :status')
            ->setParameter('status', 'approved');

        $this->aclHelper->apply($qb);

        return $qb->getQuery()->getResult();
    }
}

Without $aclHelper->apply($qb), the query returns all entities regardless of permissions.

For custom access rules (AccessRuleInterface), see security-patterns.md.

Key Pitfalls

  1. Query filtering is not automatic: Must call $aclHelper->apply($qb) explicitly. Common mistake: fetching all entities and filtering in PHP rather than at DB level.

  2. AclAncestor skips object-level checks: Use AclAncestor only for class-level permission verification (list pages). For specific objects, use full Acl attributes or isGranted().

  3. Organization field is mandatory for USER/BUSINESS_UNIT ownership: Omitting it causes permission checks to return false unexpectedly.

For AclAncestor details, custom permissions, field-level ACL, common patterns, debugging, and additional pitfalls, see security-patterns.md.

Version Notes

See permission-matrix.md for the full permission/ownership matrix, v6.1 notes, and v7.0 notes.

Weekly Installs
2
First Seen
2 days ago