A token acts as the person who made it, within the permissions it was given and those they still hold, checked on every request. Permission checks now go through one gate rule, since spatie's answered first and never asked the token. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
99 lines
3.5 KiB
PHP
99 lines
3.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Providers;
|
|
|
|
use App\Models\Application;
|
|
use App\Models\Call;
|
|
use App\Models\Category;
|
|
use App\Models\Client;
|
|
use App\Models\Media;
|
|
use App\Models\Member;
|
|
use App\Models\MissingUrl;
|
|
use App\Models\Page;
|
|
use App\Models\Project;
|
|
use App\Models\Redirect;
|
|
use App\Models\Repository;
|
|
use App\Models\Service;
|
|
use App\Models\Talk;
|
|
use App\Models\Technology;
|
|
use App\Models\Testimonial;
|
|
use App\Models\User;
|
|
use App\Policies\ApplicationPolicy;
|
|
use App\Policies\CallPolicy;
|
|
use App\Policies\CategoryPolicy;
|
|
use App\Policies\ClientPolicy;
|
|
use App\Policies\MediaPolicy;
|
|
use App\Policies\MemberPolicy;
|
|
use App\Policies\MissingUrlPolicy;
|
|
use App\Policies\PagePolicy;
|
|
use App\Policies\ProjectPolicy;
|
|
use App\Policies\RedirectPolicy;
|
|
use App\Policies\RepositoryPolicy;
|
|
use App\Policies\RolePolicy;
|
|
use App\Policies\ServicePolicy;
|
|
use App\Policies\TalkPolicy;
|
|
use App\Policies\TechnologyPolicy;
|
|
use App\Policies\TestimonialPolicy;
|
|
use App\Policies\UserPolicy;
|
|
use App\Support\Permissions;
|
|
use Illuminate\Support\Facades\Gate;
|
|
use Illuminate\Support\ServiceProvider;
|
|
use Spatie\Permission\Models\Role;
|
|
|
|
class AuthServiceProvider extends ServiceProvider
|
|
{
|
|
public function boot(): void
|
|
{
|
|
Gate::policy(Page::class, PagePolicy::class);
|
|
Gate::policy(Category::class, CategoryPolicy::class);
|
|
Gate::policy(Project::class, ProjectPolicy::class);
|
|
Gate::policy(Member::class, MemberPolicy::class);
|
|
Gate::policy(Technology::class, TechnologyPolicy::class);
|
|
Gate::policy(Call::class, CallPolicy::class);
|
|
Gate::policy(Application::class, ApplicationPolicy::class);
|
|
Gate::policy(Service::class, ServicePolicy::class);
|
|
Gate::policy(Client::class, ClientPolicy::class);
|
|
Gate::policy(Testimonial::class, TestimonialPolicy::class);
|
|
Gate::policy(Talk::class, TalkPolicy::class);
|
|
Gate::policy(Media::class, MediaPolicy::class);
|
|
Gate::policy(Redirect::class, RedirectPolicy::class);
|
|
Gate::policy(MissingUrl::class, MissingUrlPolicy::class);
|
|
Gate::policy(Repository::class, RepositoryPolicy::class);
|
|
Gate::policy(User::class, UserPolicy::class);
|
|
Gate::policy(Role::class, RolePolicy::class);
|
|
|
|
// The one place a permission is granted — spatie's own gate check is
|
|
// switched off (config/permission.php) so nothing answers before this.
|
|
//
|
|
// Super admins bypass every check. Granting the role this way rather
|
|
// than by attaching every permission means the role can never fall
|
|
// behind as the catalogue grows. Returning null (not false) when
|
|
// nothing applies lets the normal policy chain run.
|
|
//
|
|
// A machine token narrows all of that: a permission must be one the
|
|
// token was given *and* one its owner holds. A policy is not a
|
|
// permission, so it runs as usual and asks for permissions, which come
|
|
// back here.
|
|
Gate::before(function (User $user, string $ability): ?bool {
|
|
$token = $user->currentAccessToken();
|
|
|
|
if ($token !== null) {
|
|
if (! in_array($ability, Permissions::all(), true)) {
|
|
return null;
|
|
}
|
|
|
|
return $token->allows($ability)
|
|
&& ($user->hasRole('super_admin') || $user->checkPermissionTo($ability));
|
|
}
|
|
|
|
if ($user->hasRole('super_admin')) {
|
|
return true;
|
|
}
|
|
|
|
return $user->checkPermissionTo($ability) ?: null;
|
|
});
|
|
}
|
|
}
|