Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filter Transitions deending on user role or permission #20

Open
himan72 opened this issue Apr 23, 2019 · 8 comments
Open

Filter Transitions deending on user role or permission #20

himan72 opened this issue Apr 23, 2019 · 8 comments
Labels

Comments

@himan72
Copy link

himan72 commented Apr 23, 2019

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

@sebdesign
Copy link
Owner

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?

@himan72
Copy link
Author

himan72 commented Apr 24, 2019

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.

@sebdesign
Copy link
Owner

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
Copy link
Owner

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']

@divan-mt
Copy link

divan-mt commented May 5, 2019

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?

@himan72
Copy link
Author

himan72 commented May 5, 2019 via email

@sebdesign
Copy link
Owner

sebdesign commented May 6, 2019

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.

@divanoli
Copy link
Contributor

divanoli commented May 7, 2019

@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;
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants