laravel-state-machine
laravel-state-machine copied to clipboard
Filter Transitions deending on user role or permission
Hello Is there any way to filter the allowed transitions depending on the auth user role(s) or permission(s) ? Thanks for your support
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?
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.
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!
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']
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?
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 .
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 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;
}