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

@haspermission directive - Non Default guard #2515

Merged
merged 4 commits into from
Oct 24, 2023

Conversation

axlwild
Copy link
Contributor

@axlwild axlwild commented Oct 12, 2023

Has permission directive to use instead can directive when using non-default guard

Creating this PR to be able to use another blade directive when you use another guard distinct from the default one.

This issue is mentioned here.

With this change, you can use the following directive

@haspermission('admin.users.view', 'admin')
   ...
@endhaspermission

instead of

@can('admin.users.view')
   ...
@can

@parallels999
Copy link
Contributor

parallels999 commented Oct 13, 2023

@drbyte hi, couldn't this be solved by adding the guard on the gate directive?

$gate->before(function (Authorizable $user, string $ability) {
if (method_exists($user, 'checkPermissionTo')) {
return $user->checkPermissionTo($ability) ?: null;
}
});

$gate->before(function (Authorizable $user, string $ability, array &$args = []) {
     if(is_string($args[0] ?? null) && !class_exists($args[0])) {
        $guard = array_shift($args);
     }
     if (method_exists($user, 'checkPermissionTo')) { 
         return $user->checkPermissionTo($ability, $guard ?? null) ?: null; 
     } 
 });

Now we could do

@can('admin.users.view', 'admin')
   ...
@endcan
auth()->user()->can('admin.users.view', 'admin')
auth()->user()->can('admin.users.view', ['admin', $post])

@drbyte
Copy link
Collaborator

drbyte commented Oct 13, 2023

adding the guard on the gate directive

That would be preferable. Until now we've avoided adding blade helpers for permissions because they basically duplicate what Laravel already provides in the can/canany/canall series.

A few versions ago I explored your suggestion when tinkering with making guards simpler but all kinds of things broke .... but I think the part you mention might have been fine. I rolled back the whole thing, but probably could have kept that part.
It's worth writing some tests for it and giving it a try!

@drbyte
Copy link
Collaborator

drbyte commented Oct 16, 2023

Current status: undecided between merging this (after tests are added for this new directive), or simply adding it to the can logic...

@parallels999
Copy link
Contributor

I did test it with the if(is_string($args[0] ?? null) && !class_exists($args[0])) { $guard = array_shift($args); } and it works, but i don't know if protected $policies could be used with custom strings, on that case that it will fail

@drbyte
Copy link
Collaborator

drbyte commented Oct 16, 2023

Ya, we don't want to break the normal Policy stuff.

@drbyte
Copy link
Collaborator

drbyte commented Oct 16, 2023

@parallels999 Maybe I've been at the keyboard too long today, but I can't get a Blade test to pass when passing a guard.

eg: Added this to BladeTest.php:

    /** @test */
    public function the_can_directive_can_accept_a_guard_name()
    {
        $this->testAdminRole->givePermissionTo($this->testAdminPermission);
        $this->testAdmin->assignRole($this->testAdminRole);
    
        // log in as the Admin with the permission-via-role
        auth('admin')->setUser($this->testAdmin);

        $permission = 'admin-permission'; // from $this->testAdminPermission
        $guard = 'admin'; // from $this->testAdminPermission
        $this->assertEquals('has permission', $this->renderView('can', compact('permission', 'guard')));
    }

and revised the can.blade.php template to add the $guard param:

@can($permission, $guard ?? null)
has permission
@else
does not have permission
@endcan

@drbyte
Copy link
Collaborator

drbyte commented Oct 17, 2023

Turns out it was the auth('admin')->setUser vs auth()->setUser (not specifying the guard in the forced-login for the test)

@drbyte
Copy link
Collaborator

drbyte commented Oct 23, 2023

Just thinking "aloud" ... Regarding policies ... since this package is only checking for the permission names provided by this package, does it really need to also check against a policy? Policies should be checking the ability (permission name) against the model, inside the policy, so I don't think we need to worry about cascading the arguments list down to policy names like core Laravel does.

@drbyte
Copy link
Collaborator

drbyte commented Oct 23, 2023

@axlwild ... still considering this. But I'd like to add tests. Can you update the PR to "allow edits by maintainers"? (tick the checkbox)

EDIT: I decided to add the tests separately. But in future, it's always better to "allow edits by maintainers" when submitting PR's!

@drbyte drbyte merged commit 4e6e86d into spatie:main Oct 24, 2023
22 checks passed
drbyte added a commit that referenced this pull request Oct 24, 2023
drbyte added a commit that referenced this pull request Oct 24, 2023
As discussed in comments on 2515: #2515 (comment)

Co-authored-by: parallels999 <parallels999@users.noreply.github.com>
drbyte added a commit that referenced this pull request Oct 25, 2023
* Add guard parameter to can()

As discussed in comments on 2515: #2515 (comment)

Co-authored-by: parallels999 <parallels999@users.noreply.github.com>
@drbyte drbyte changed the title Has permission directive - Non Default guard @haspermission directive - Non Default guard Oct 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants