laravel-state-machine icon indicating copy to clipboard operation
laravel-state-machine copied to clipboard

Filter Transitions deending on user role or permission

Open himan72 opened this issue 5 years ago • 8 comments

Hello Is there any way to filter the allowed transitions depending on the auth user role(s) or permission(s) ? Thanks for your support

himan72 avatar Apr 23 '19 16:04 himan72

Hello,

you could achieve this in several ways, but it depends on how your roles/permissions are structured. If you are using gates/policies as guards for the transitions, $sm->getPossibleTransitions() will only return the transitions allowed for the authenticated user based on the policies.

Could give me an example of what would you like to achieve? Are you interested in the transitions allowed for the authenticated user? Or do you want to check another $user perharps?

sebdesign avatar Apr 23 '19 21:04 sebdesign

Hello First of all a BIG THANKS to Sébastien for taking the time to respond to my question. :) I am using spatie/laravel-permission package to handle the permissions. What i want to achieve is to filter the transitions based on the authenticated user role. I guess the gates/policies is a good way to do it.

himan72 avatar Apr 24 '19 17:04 himan72

You're welcome!

You can definitely use this package, and it will work the same as if you had your own gates/policies. I will take a look at spatie/laravel-permission and will give you an example tomorrow.

Cheers!

sebdesign avatar Apr 24 '19 17:04 sebdesign

Hello @himan72 ,

Here is an example of some permissions set up with spatie/laravel permissions:

$writer = Role::findByName('writer');
$writer->givePermissionTo('submit articles');

$admin = Role::findByName('admin');
$admin->givePermissionTo('submit articles');
$admin->givePermissionTo('publish articles');
$admin->givePermissionTo('unpublish articles');

$user->assignRole('writer');
$superUser->assignRole('admin');

And a state machine configuration: The name of the permission in the can keys must match the permissions given above.

    'articles' => [
        'class' => App\Article::class,
        'graph' => 'default',
        'property_path' => 'state',
        'states' => [
            'pending',
            'unpublished',
            'published',
        ],
        'transitions' => [
            'submit' => [
                'from' => ['pending'],
                'to' => 'unpublished',
            ],
            'publish' => [
                'from' =>  ['unpublished'],
                'to' => 'published',
            ],
            'unpublish' => [
                'from' => ['published'],
                'to' => 'unpublished',
            ],
        ],
        'callbacks' => [
            'guard' => [
                'guard_on_submitting' => [
                    'on' => 'submit',
                    'can' => 'submit articles',
                ],
                'guard_on_publishing' => [
                    'on' => 'publish',
                    'can' => 'publish articles',
                ],
                'guard_on_unpublishing' => [
                    'on' => 'unpublish',
                    'can' => 'unpublish articles',
                ],
            ],
        ],
    ],

So when the $user is authenticated, the possible transitions will be submit:

$sm = StateMachine::get($article);
$sm->getPossibleTransitions(); // ['submit']

But when the $superUser is authenticated, the possible transitions will be submit, publish, and unpublish:

$sm = StateMachine::get($article);
$sm->getPossibleTransitions(); // ['submit', 'publish', 'unpublish']

sebdesign avatar Apr 25 '19 18:04 sebdesign

And a state machine configuration: The name of the permission in the can keys must match the permissions given above.

Wouldn't it check the gates on the policies for App\Article rather than the user permissions?

divan-mt avatar May 05 '19 08:05 divan-mt

Yep I plan to use a policy to handle the permissions.

Le dim. 5 mai 2019 08:21, divan-mt [email protected] a écrit :

And a state machine configuration: The name of the permission in the can keys must match the permissions given above.

Wouldn't it check the gates on App\Article rather than the user permissions?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/sebdesign/laravel-state-machine/issues/20#issuecomment-489402666, or mute the thread https://github.com/notifications/unsubscribe-auth/ABTSI2K7DHSSOTIFDU7EWYDPT2KGZANCNFSM4HHZVNUA .

himan72 avatar May 05 '19 11:05 himan72

Hey @divan-mt @himan72 ,

I believe with this configuration that it would NOT check the policies. The reason is because in the configuration there is no 'args' => ['object'], for the can callback. So instead of doing Gate::check('publish articles', $article), it will simply execute Gate::check('publish articles').

Using the args key allows you to define which arguments you want to call the gate with (after the name of the permission). If you want to use policies, then ['object'] will pass the model/object inside the state machine, which will cause the Gate to check the policy if it exists.

sebdesign avatar May 06 '19 18:05 sebdesign

@sebdesign Actually, in the project I'm working on right now, I have created policies for the Object and it works without explicitly having 'args' => ['object'].

//state-machine.php
'guard_on_ask_for_employee_changes' => [
                    'on' => 'ask_for_employee_changes',
                    'can' => 'ask-for-employee-changes',
                ],
//TrainingRequestPolicy.php
public function askForEmployeeChanges(User $user, TrainingRequest $trainingRequest)
    {
        if (null === $user) {
            return false;
        }

        if ($user->can('ask for department employee changes') && RequestState::PendingDepartmentHeadReview === $trainingRequest->last_state) {
            return true;
        }

        if ($user->can('ask for any employee changes') && RequestState::PendingHRTeamReview === $trainingRequest->last_state) {
            return true;
        }

        return false;
    }

divanoli avatar May 07 '19 03:05 divanoli