NovinkaZverejnili sme 50+ Laravel balíkov ako open source
Custom AI apps, agents and automation — Roundly ConsultingRoundly
Všetky balíky
Teams for Laravel

Most k permissions

Členstvo nesie jednu rolu. Ak potrebujete viac — niekoľko rolí pre člena v tíme, rolu platnú do piatku, priame oprávnenie pre jedného člena, roly, ktoré si tím definuje sám —, nainštalujte permissions-for-laravel a zapnite most. Teams tento balík len odporúča, nikdy ho nevyžaduje, a kým most nezapnete, nič sa nemení. team_members.role zostáva rolou členstva; ďalšie, jemnejšie a časovo obmedzené priradenia pochádzajú z permissions-for-laravel a platia v rozsahu tímu.

Zapnutie

composer require roundly-consulting/permissions-for-laravel
php artisan vendor:publish --tag="permissions-migrations"
php artisan migrate
PERMISSIONS_SCOPE_KEY_TYPE=ulid   # only when teams key differently from users — before migrating
PERMISSIONS_ASSIGNMENTS=true
TEAMS_PERMISSIONS_BRIDGE=true

Most potrebuje permissions-for-laravel 2.1 alebo novší — so staršími verziami teams deklaruje konflikt — so zapnutými priradeniami v rozsahu. Ak majú vaše tímy iný typ kľúča ako používatelia, najprv nastavte typ kľúča rozsahov. Potom pridajte modelu používateľa trait HasRoles z permissions popri HasTeams:

use Illuminate\Foundation\Auth\User as Authenticatable;
use RoundlyConsulting\Permissions\Concerns\HasRoles;
use RoundlyConsulting\Teams\Traits\HasTeams;

class User extends Authenticatable
{
    use HasRoles;   // permissions-for-laravel
    use HasTeams;
}

Ak je prepínač zapnutý, no balík chýba alebo je permissions.assignments.enabled vypnuté, aplikácia pri štarte zlyhá s InvalidConfigurationException, ktorá pomenuje, čo chýba — zapnutý prepínač, ktorý potichu nerobí nič, by bol horší. php artisan about zobrazí Permissions bridge ON alebo OFF.

Priradenia v rámci tímu

members()->grant($member) je skratka pre Permissions::for($member)->in($team) s dvoma pravidlami tímu:

use RoundlyConsulting\Teams\Facades\Teams;

Teams::for($team)->members()->grant($user)->assignRole('reviewer');
Teams::for($team)->members()->grant($user)->until($friday)->givePermissionTo('reports.export');
Teams::for($team)->members()->grant($user)->syncRoles(['reviewer', 'editor']);   // the complete set in this team
Teams::for($team)->members()->grant($user)->removeRole('editor');
Teams::for($team)->members()->grant($user)->forgetAllAuthorization();            // everything in this team

Teams::for($team)->members()->grant($user)->hasPermissionTo('reports.export');   // bool
Teams::for($team)->members()->grant($user)->assignments();                       // the member's rows in this team
  • Len členovia — pridanie (assignRole, givePermissionTo, syncRoles, syncPermissions) potrebuje aktuálne alebo naplánované členstvo v tomto tíme; nečlen, člen iného tímu či člen s vypršaným členstvom vyhodí MemberNotFoundException. Odoberanie funguje pre kohokoľvek, takže vyčistiť priradenia toho, kto odchádza, je vždy bezpečné.
  • Predvoleným koncom je expirácia členstva — bez until() sa pridanie skončí spolu s členstvom. until($date) nastaví iný koniec, until(null) žiadny; from() a between() nastavia začiatok.
  • syncRoles() a syncPermissions() nastavia úplnú množinu v tomto tíme; odobratie vyčistí všetky okná.
  • Prijme názvy, backed enumy, modely Role a Permission aj zoznamy — čokoľvek, čo prijme permissions-for-laravel. Zápis priamo cez Permissions::for($user)->in($team) funguje tiež: most číta, čo tam je, a grant() pridáva len pravidlá členstva a záznam pre Teams::fake().

Kým je most vypnutý, grant() vyhodí TeamsException. Cez injektovaný manager alebo priamo akciou vyzerá ten istý zápis takto:

use RoundlyConsulting\Teams\Bridges\Permissions\Actions\GrantMemberAuthorizationAction;
use RoundlyConsulting\Teams\Bridges\Permissions\DataTransferObjects\GrantMemberAuthorizationData;
use RoundlyConsulting\Teams\Bridges\Permissions\Enums\MemberGrant;

// Injected manager — the same API as the facade
$this->teams->for($team)->members()->grant($user)->assignRole('reviewer');

// The raw action
app(GrantMemberAuthorizationAction::class)->execute($team, new GrantMemberAuthorizationData(
    member: $user,
    verb: MemberGrant::AssignRole,
    items: ['reviewer'],
));

Čo vidia kontroly

Pri zapnutom moste odpovedia memberHasPermission() a memberHasRole() true, ak to udeľuje rola členstva — ako doteraz —, alebo ak to v tíme udeľuje permissions-for-laravel. Zjednotenie zdedí všetko, čo na nich stavia: hasTeamPermission() a hasTeamRole(), ability teams.<oprávnenie> v Gate, @teamPermission a @teamRole aj AbstractTeamPolicy:

$team->memberHasPermission($user, 'reports.export');   // the membership role OR a grant in the team
$user->can('teams.reports.export', $team);              // the same, through the Gate

Route::middleware(['auth', 'teams.context', 'can:posts.edit'])
    ->put('/teams/{team}/posts/{post}', UpdatePost::class);   // resolved in the current team
  • Overuje sa v čase kontroly — expirované, ešte nezačaté či odobraté členstvo okamžite znefunkční priradenia svojho tímu, ešte pred akýmkoľvek upratovaním.
  • Názvy sa zhodujú — teams.posts.edit sa pýta na oprávnenie posts.edit a memberHasRole($u, 'reviewer') na rolu reviewer. Katalógy oboch balíkov sú oddelené; názvy registrujte tam, kde ich udeľujete.
  • Globálne priradenia — priradenie z permissions-for-laravel bez rozsahu platí v každom tíme, kde je používateľ aktívnym členom, kým je permissions.assignments.global_applies_in_scope zapnuté (predvolene áno). Prísne multi-tenant aplikácie ho vypnú.
  • Vnorené tímy — pri inherit_roles_down platí priradenie v nadradenom tíme aj v tímoch pod ním, a to pre člena toho nadradeného tímu. Smerom nahor sa priradenie nikdy nešíri.
  • Priradenie v tíme nikdy nesplní kontrolu bez rozsahu, ako je $user->can('posts.edit') bez tímu — okrem implicitného rozsahu nižšie. Používatelia bez HasRoles dostanú len odpoveď podľa roly členstva a teamsWithRole() aj teamRole() naďalej čítajú len rolu členstva.

Aktuálny tím ako implicitný rozsah

Most zaregistruje Permissions::resolveScopeUsing(), takže kontroly cez Gate bez rozsahu — middleware can:, @can('posts.edit'), $user->can('posts.edit') — sa vyhodnotia v aktuálnom tíme (nastavenom middlewarom teams.context alebo cez Teams::switchTo()) a pri dedení rolí aj v tímoch nad ním, a to len pre aktívnych členov. Bez aktuálneho tímu, v režime viacerých tímov alebo pre nečlena zostane kontrola bez rozsahu. Váš vlastný resolveScopeUsing() v service provideri ho nahradí, pretože providery aplikácie štartujú po provideroch balíkov.

Upratovanie

  • Člen je odobratý (TeamMemberDeleted) alebo sa odstráni expirované členstvo (MembershipExpired) — priradenia člena v tíme sa zabudnú.
  • Vypršané členstvo sa znova pridá — to isté, pretože obnovené členstvo začína odznova a staré priradenia sa nesmú vrátiť. Priradenia urobené pred úplne novým členstvom zostanú.
  • Tím sa natrvalo zmaže — Permissions::forgetScope($team) odstráni jeho priradenia aj roly, ktoré vlastní. Mäkko zmazaný tím si ich ponechá, pretože ho možno obnoviť.

Nič z toho nie je potrebné pre správnosť — kontroly neaktívne členstvá ignorujú už samy —, udržiava to však tabuľky čisté a vracajúci sa člen nezdedí staré priradenia.

Roly definované tímom

Pre roly, ktoré si tím definuje sám, použite roly s vlastníkom z permissions-for-laravel — v rozsahu tímu má vlastná rola tímu prednosť pred globálnou s rovnakým názvom. Je to alternatíva k rolám upraveným pre konkrétny tím; tieto dva mechanizmy sa nezlučujú:

use RoundlyConsulting\Permissions\Facades\Permissions;

Permissions::owner($team)->role('auditor')->givePermissionTo('reports.view');
Teams::for($team)->members()->grant($user)->assignRole('auditor');   // the team's own auditor

Testovanie

Teams::fake() zaznamená každý zápis cez grant() ako GrantMemberAuthorization alebo RevokeMemberAuthorization s tímom, členom, slovesom a názvami; Permissions::fake() vidí aj samotný zápis v rozsahu:

$fake = Teams::fake();

Teams::for($team)->members()->grant($user)->assignRole('reviewer');

$fake->assertMemberGranted($team, $user, 'reviewer');
$fake->assertNoGrantRevoked();

// Permissions::fake() sees the underlying scoped write as well:
// assertRoleAssigned($user, 'reviewer', scope: $team, until: $membershipExpiry)

Bez mosta

Chcete si to prepojiť sami? Zjednotenie zaberie pár riadkov vo vlastnej gate či policy:

Gate::define('team-permission', fn (User $user, Team $team, string $permission): bool =>
    $team->memberHasPermission($user, $permission)
    || ($team->hasActiveMember($user) && Permissions::for($user)->in($team)->hasPermissionTo($permission)));

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 kryptomien

Odoslaní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.