Skip to content

Use security voter with a #[MapRequestPayload] controller argument #53510

@tsantos84

Description

@tsantos84

Symfony version(s) affected

6.3.11

Description

I don't know if it is really a bug but the behavior of what I'm describing here is weird to me.

I'm trying to create a custom security voter that receives the controller argument annotated with #[MapRequestPayload] attribute as subject. I'm expecting that the mixed $subject argument of Voter::supports to be the value already resolved but an instance of MapRequestPayload is being passed to the voter instead.

How to reproduce

The controller class:

#[Route('/some-resource', methods=['POST'])]
#[IsGranted('create', 'someResource')]
class MyController {
    public function __invoke(#[MapRequestPayload] MyResource $someResource): Response
    {
        return /* generate response here */;
    }
}

The voter class:

class CreateMyResource extends Voter {
    protected function supports(string $attribute, mixed $subject): bool
    {
        // an instance of MapRequestPayload is being passed to supports method

        return $attribute === 'create' && $subject instanceof MyResource;
    }

    protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
    {
        return /* my custom logic here */;
    }
}

Possible Solution

I suppose that the order of event listeners - security listerner are being executed before value resolver listener - is contributing to this behavior.

Additional Context

I've tried to resolve the value inside my Voter class but I realized that doing this does not make sense given the necessary effort to make it work.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions