include::../description.adoc[]

== Noncompliant Code Example

In a Symfony web application:

* the ``vote`` method of a https://symfony.com/doc/current/security/voters.html[VoterInterface] type is not compliant when it returns only an affirmative decision (``ACCESS_GRANTED``):

----
class NoncompliantVoterInterface implements VoterInterface
{
    public function vote(TokenInterface $token, $subject, array $attributes)
    {
        return self::ACCESS_GRANTED; // Noncompliant
    }
}
----

* the ``voteOnAttribute`` method of a https://symfony.com/doc/current/security/voters.html[Voter] type is not compliant when it returns only an affirmative decision (``true``):

----
class NoncompliantVoter extends Voter
{
    protected function supports(string $attribute, $subject)
    {
        return true;
    }

    protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token)
    {
        return true; // Noncompliant
    }
}
----

In a Laravel web application:

* the ``define``, ``before``, and ``after`` methods of a https://laravel.com/docs/8.x/authorization[Gate] are not compliant when they return only an affirmative decision (``true`` or ``Response::allow()``):

----
class NoncompliantGuard
{
    public function boot()
    {
        Gate::define('xxx', function ($user) {
            return true; // Noncompliant
        });

        Gate::define('xxx', function ($user) {
            return Response::allow(); // Noncompliant
        });
    }
}
----

== Compliant Solution

In a Symfony web application:

* the ``vote`` method of a https://symfony.com/doc/current/security/voters.html[VoterInterface] type should return a negative decision (``ACCESS_DENIED``) or abstain from making a decision (``ACCESS_ABSTAIN``):

----
class CompliantVoterInterface implements VoterInterface
{
    public function vote(TokenInterface $token, $subject, array $attributes)
    {
        if (foo()) {
            return self::ACCESS_GRANTED; // Compliant
        } else if (bar()) {
            return self::ACCESS_ABSTAIN;
        }
        return self::ACCESS_DENIED;
    }
}
----

* the ``voteOnAttribute`` method of a https://symfony.com/doc/current/security/voters.html[Voter] type should return a negative decision (``false``):

----
class CompliantVoter extends Voter
{
    protected function supports(string $attribute, $subject)
    {
        return true;
    }

    protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token)
    {
        if (foo()) {
            return true; // Compliant
        }
        return false;
    }
}
----

In a Laravel web application:

* the ``define``, ``before``, and ``after`` methods of a https://laravel.com/docs/8.x/authorization[Gate] should return a negative decision (``false`` or ``Response::deny()``) or abstain from making a decision (``null``):

----
class NoncompliantGuard
{
    public function boot()
    {
        Gate::define('xxx', function ($user) {
            if (foo()) {
                return true; // Compliant
            }
            return false;
        });

        Gate::define('xxx', function ($user) {
            if (foo()) {
                return Response::allow(); // Compliant
            }
            return Response::deny();
        });
    }
}
----

include::../see.adoc[]
