Gate a middleware
Pri zapnutom register_gate_check (predvolene) sa oprávnenia vyhodnocujú cez Gate v Laraveli, takže natívny middleware can: funguje hneď:
Route::get('/users', UsersController::class)->middleware('can:auth.users.view');
$user->can('auth.users.view'); // true when granted directly or via a role
Gate::forUser($user)->allows('auth.users.view');Ako hook rozhoduje
Balík zaregistruje jediný hook Gate::before. Odpovedá iba vtedy, keď platí všetko nasledujúce — inak vráti null a vaše vlastné gates a policies prebehnú bez zásahu:
- Kontrola nemá argumenty — žiadny model ani ďalšie parametre — alebo pri zapnutých priradeniach práve jeden PermissionScope (pozrite Kontroly v rozsahu nižšie).
- Model používateľa má metódu hasPermissionTo(), teda používa HasRoles.
- Ability je názov zaregistrovaného oprávnenia.
Ak používateľ oprávnenie drží — priamo alebo cez rolu — hook vráti true. Nikdy nevráti false: používateľ bez oprávnenia prejde na vaše gates, a ak žiadne nie sú, Laravel prístup zamietne, takže middleware can: odpovie kódom 403.
Posledné slovo majú policies
Kontrola oprávnení nikdy neprebije policy modelu. Hneď ako kontrola nesie model alebo akýkoľvek argument — $user->can('update', $post) či middleware can:update,post — hook prenechá rozhodnutie vašej gate alebo policy. Oprávnenie s názvom update autorizuje $user->can('update'), no o $user->can('update', $post) stále rozhoduje PostPolicy::update():
Permissions::permission('update');
Permissions::for($user)->givePermissionTo('update');
$user->can('update'); // true — argument-less, answered by the permission
$user->can('update', $post); // PostPolicy::update() decides — ownership, tenancy, …final class PostPolicy
{
public function update(User $user, Post $post): bool
{
return $post->owner_id === $user->getKey();
}
}Hrubozrnné oprávnenia a policies viazané na model tak fungujú vedľa seba a ani jedno potichu nepohltí druhé.
Kontroly v rozsahu
Pri zapnutých priradeniach odovzdajte Permissions::scope() ako jediný argument pre Gate a kontrola prebehne v rámci projektu, tímu či tenanta — viac rozsahov znamená ktorýkoľvek z nich. Funguje s can(), Gate::authorize() aj @can; nové Blade direktívy nepribudli:
use RoundlyConsulting\Permissions\Facades\Permissions;
$user->can('posts.edit', Permissions::scope($project));
Gate::authorize('posts.edit', Permissions::scope([$team, $parentTeam])); // any of them@can('posts.edit', Permissions::scope($project))
<button>Edit post</button>
@endcanHook stále odpovedá len true alebo null, takže vaše gates môžu prístup ešte povoliť. Na PermissionScope sa nemôže naviazať žiadna policy, takže kontrola v rozsahu s ňou nikdy nekoliduje; akýkoľvek iný tvar argumentov ide nedotknutý k vašim gates a policies.
Implicitný rozsah
Kontroly bez rozsahu — middleware can:, @can('posts.edit'), $user->can('posts.edit') — zostávajú bez rozsahu, takže ich priradenie v rozsahu nikdy nesplní. Zaregistrujte resolver, ktorý im dodá implicitný rozsah, napríklad aktuálny tím či projekt:
// app/Providers/AppServiceProvider.php → boot()
use Illuminate\Contracts\Auth\Access\Authorizable;
use Illuminate\Database\Eloquent\Model;
use RoundlyConsulting\Permissions\Facades\Permissions;
Permissions::resolveScopeUsing(
fn (Authorizable $user, string $ability): Model|iterable|null => $user->currentProject,
);
// can:posts.edit, @can('posts.edit') and $user->can('posts.edit') now check inside it
Permissions::resolveScopeUsing(null); // remove it againAk resolver vráti null alebo prázdny zoznam, kontrola zostane bez rozsahu. Resolver platí len pre Gate, nikdy pre hasPermissionTo() či hasRole(), a žije v singletone v kontajneri, takže ho Permissions::fake() zachová. teams-for-laravel si pri zapnutom moste k permissions zaregistruje jeden pre aktuálny tím.
Middleware pre routy s rozsahom
EnsurePermission overí oprávnenie v rozsahu, na ktorý je naviazaný parameter routy. Alias sa neregistruje — odkazujte na triedu:
use RoundlyConsulting\Permissions\Http\Middleware\EnsurePermission;
Route::put('/projects/{project}/posts/{post}', UpdatePost::class)
->middleware(EnsurePermission::using('posts.edit', scope: 'project'));
// the same, as a string
Route::put('/projects/{project}/posts/{post}', UpdatePost::class)
->middleware(EnsurePermission::class.':posts.edit,project');
// unscoped
Route::get('/admin', AdminController::class)
->middleware(EnsurePermission::using('admin.access'));Parameter rozsahu musí byť implicitne naviazaný model; chýbajúci alebo nenaviazaný vyhodí PermissionException — je to chyba routy, nikdy tiché povolenie či zamietnutie. Neprihlásený používateľ, používateľ bez HasRoles alebo chýbajúce oprávnenie skončí výnimkou AuthorizationException (403). Middleware sa pýta priamo registra, nie Gate, takže funguje aj pri vypnutom register_gate_check a ignoruje resolveScopeUsing() — na to použite middleware can:.
Vypnutie hooku
Nastavte register_gate_check na false, ak chcete hook úplne vynechať — vrátane kontrol v rozsahu — a oprávnenia vyhodnocovať sami:
// config/permissions.php
'register_gate_check' => false,
// then check explicitly where you need it
abort_unless($request->user()->hasPermissionTo('auth.users.view'), 403);Prejavte lásku k open source
Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.
Ďalšie spôsoby podpory vrátane kryptomienOdoslaním daru súhlasíte s našimi podmienkami prijímania darov.
Chcete to zabudovať do svojho produktu?
Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.