Karbantartás menedzsment rendszer - 8. rész: Jogosultsági rendszer elemeinek összeépítése

Attila | 2023. 10. 31. 15:00 | Olvasási idő: 3 perc

Címkék: #Digitalizáció (Digitalization) #Felhasználók (Users) #Filament #Integráció (Integration) #Jogosultság (Permission) #Szerepkörök (Roles)

Építsük össze az eddig meglévő elemeinket, és így elérhetünk a célhoz, amelyet én a jogosultsági alrendszer tervezésének elején kitűztem magunk elé. Szerepkörökhöz (roles) fogjuk rendelni a jogosultságokat (permissions), mivel így implicit módon az egyes felhasználókhoz is meg tudjuk határozni, hogy ők milyen funkcionalitások használatára lesznek képesek a Karbantartás Menedzsment Rendszerben.
rbac_filament

Engedélyeztetés

A menüpontok, funkciók elérését és használatát úgynevezett Policy osztályok segítségével valósítjuk meg. Az authentikáció része, hogy kit enged be a webalkalmazás az adminisztrációs felületére, de onnantól kezdve, ha már bent van a felhasználó, akkor az engedélyeztetés játszik szerepet abban, hogy mit tud majd ott elérni és használni. A belső házirendünket kell tehát felépítenünk és minden erőforrásnál meghatározzuk, hogy milyen szerepkörű felhasználók férhetnek majd hozzá.

Az engedélyezéshez a Filament betartja az alkalmazásban regisztrált szabályokat. A következő módszereket használja:

  • A viewAny() segítségével teljesen elrejti az erőforrásokat a navigációs menüből, és megakadályozza, hogy a felhasználó bármilyen funkciójához hozzáférjen.
  • A view() egy rekord megtekintésének vezérlésére szolgál.
  • A create() az új rekordok létrehozásának vezérlésére szolgál.
  • Az update() egy rekord szerkesztésének vezérlésére szolgál.
  • A delete() arra szolgál, hogy megakadályozhassa egyetlen rekord törlését.
  • A deleteAny() arra szolgál, hogy megakadályozhassa a rekordok tömeges törlését.
    • A Filament a deleteAny() metódust használja, mivel a több rekordon való iterálás és a delete() házirend ellenőrzése nem túl hatékony.
  • A forceDelete() arra szolgál, hogy megakadályozhassa egy törlésre kijelölt rekord kényszertörlését.
  • A forceDeleteAny() arra szolgál, hogy megakadályozhassa a rekordok tömeges kényszertörlését.
    • A Filament a forceDeleteAny() metódust használja, mivel a több rekordon való iterálás és a forceDelete() házirend ellenőrzése nem túl hatékony.
  • A restore() arra szolgál, hogy megakadályozhassa egyetlen "soft delete" opcióval törölt rekord visszaállítását.
  • A restoreAny() arra szolgál, hogy megakadályozhassa a rekordok tömeges visszaállítását.
    • A Filament a restoreAny() metódust használja, mivel a több rekordon való iterálás és a restore() házirend ellenőrzése nem túl hatékony.
  • A reorder() a rekordok újrarendezésének ellenőrzésére szolgál.

A Policy osztályokkal tehát egy-egy Model-hez vagy erőforráshoz való hozzáférést tudjuk egy helyen szabályozni, például, hogy lehessen-e egy berendezést törölni vagy frissíteni a rendszerben. De még mielőtt a Karbantartással kapcsolatos funkciókra rátérnénk, előbb határozzuk meg, hogy az adminisztrációs menüben szereplő elemekhez kik férhetnek hozzá.

php artisan make:policy PermissionPolicy --model=Permission

Az utasítás hatására létrejön az app mappában a Policies mappa, benne pedig a PermissionPolicy.php fájl.

A fájl importálásainál cseréljük ki az App\Models\Permission -t erre: Spatie\Permission\Models\Permission

Innentől kezdve viszont aránylag könnyű dolgunk lesz:

  1. Meg kell vizsgálni, hogy a legenerált metódusok szükségesek-e az erőforrásunk kezelésénél, vagy éppen van olyan metódus, ami hiányzik az alapból legeneráltakból és nekünk szükségünk lenne rá.
  2. A metódusok magja pedig megegyezik azzal, amit a korábbi seeder osztályokban definiáltunk permission-öket, vagyis azt vizsgáljuk, hogy az adott felhasználó "tudja-e" vagy "képes-e" megcsinálni például a jogosultságot, a szerepkörén keresztül ellenőrzi le ezt a rendszer. Ne akarjunk egyes felhasználókhoz jogosultságokat rendelni, mert az a logikával szembe menne, maradjunk a szerepkörök alapján történő jogosultság kiosztásnál és ellenőrzésnél.

A PermissionPolicy osztályon bemutatom a működést: minden metódus visszatérési típusa bool, vagyis igaz/hamis lehet. Ha a visszatérési érték igaz, akkor az adott jogosultsággal rendelkező szerepkör és annak felhasználói hozzáférnek ahhoz a művelethez. Az osztály tartalma:

/**
 * Determine whether the user can view any models.
 */
public function viewAny(User $user): bool
{
  return $user->can('read permissions');
}

/**
 * Determine whether the user can view the model.
 */
public function view(User $user, Permission $permission): bool
{
  return $user->can('read permissions');
}

/**
 * Determine whether the user can create models.
 */
public function create(User $user): bool
{
  return $user->can('create permissions');
}

/**
 * Determine whether the user can update the model.
 */
public function update(User $user, Permission $permission): bool
{
  return $user->can('update permissions');
}

/**
 * Determine whether the user can delete the model.
 */
public function delete(User $user, Permission $permission): bool
{
  return $user->can('delete permissions');
}

/**
 * Determine whether the user can restore the model.
 */
public function restore(User $user, Permission $permission): bool
{
  return false;
}

/**
 * Determine whether the user can permanently delete the model.
 */
public function forceDelete(User $user, Permission $permission): bool
{
  return false;
}

A forceDelete() és restore() metódusok nem is kellenének, hiszen ennél az érintett Permission Model osztálynál nem alkalmazzuk a "soft delete" technikát, de a példa kedvéért bennhagytam őket és false értékkel térnek vissza mindig. A későbbiekben, ha mégis úgy döntenénk, hogy a Permission-öknél is szeretnénk alkalmazni a soft delete-et, akkor ahhoz át kell alakítanunk a Model osztályát és a permissions adattáblát is, majd utána kell itt foglalkozni a forceDelete() és restore() metódusokkal.

A szerepkörökhöz tartozó RolePolicy osztály gyakorlatilag tökéletesen ugyanígy rekonstruálható. Arra figyeljünk csak, hogy az importálásnál ne a "mi" Role Model osztályunkat emelje be, hanem a Spatie\Permission\Models\Role osztályt.

php artisan make:policy RolePolicy --model=Role

A felhasználók már érdekesebbek lesz, mivel ott szükség van a restore() metódus megvalósítására ténylegesen (forceDelete()-et itt nem engedünk), de a korábbi seeder osztályunk még nem volt felkészítve arra, hogy ezt a "soft delete" funkcionalitást kell majd alkalmazni a felhasználóknál, úgyhogy ezt az új jogosultságot létre kell hoznunk "manuálisan" az alkalmazásunk jogosultságokat adminisztráló oldalán, majd az új jogosultságot hozzá kell rendelni az admin szerepkörhöz is az adminisztrációs felületen szintén! A létrehozandó jogosultság neve legyen ez: restore users

A "Válassz..." bemeneti mezőnél már akkor feldobja az egyetlen, eddig még nem hozzáadott jogosultságot, amikor rákattintunk (fókuszba helyezzük) a bemeneti mezőre. Ezután hozzuk létre a UserPolicy osztályt:

php artisan make:policy UserPolicy --model=User

Csak a restore() metódust emelem ki az új UserPolicy osztályból (a többi ugyanolyan felépítésű, mint azt korábban láthattuk):

public function restore(User $user, User $model): bool
{
  return $user->can('restore users');
}

Ezzel elkészült a jogosultsági rendszerhez szükséges három Policy osztály, viszont érvényre még nem juttattuk őket. Ehhez az kell, hogy regisztráljuk a Policy osztályokat itt: app / Providers / AuthServiceProvider.php A megnyitott fájlban a $policies tömbhöz kell hozzáadni az új fájljainkat:

protected $policies = [
  Permission::class => PermissionPolicy::class,
  Role::class => RolePolicy::class,
  User::class => UserPolicy::class,
];

Importáljuk is be őket a fájl tetején:

use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
use App\Models\User;
use App\Policies\PermissionPolicy;
use App\Policies\RolePolicy;
use App\Policies\UserPolicy;

Ha most belépünk egy másik (típusú) böngészőben vagy egy inkognitó ablakban a webes alkalmazásunkba egy nem admin szerepkörű felhasználóval (például a repairer@admin.hu - password felhasználónév-jelszó párossal), akkor már nem is fogja mutatni az alkalmazás a menüstruktúrában a jogosultsági rendszerrel kapcsolatos menüpontokat:

Ha pedig közvetlenül szeretnénk elérni például a felhasználók kezelését ugyanitt (http://127.0.0.1:8000/users), akkor 403 | Forbidden HTTP hibakódot kapnánk, ami arra utal mindig, hogy nincs engedélyezve a hozzáférés ennek a felhasználónak.

Az admin szerepkörű felhasználónál viszont még ugyanúgy elérhetőek a Szerepkörök, Jogosultságok és Felhasználók menüpontok és funkcionalitásaik.

Ezek után már nem okozhat problémát a Berendezés típusok, Berendezések, Dokumentumok Policy osztályainak létrehozása és a metódus magjainak feltöltése, majd a végén az AuthServiceProvider.php fájlban a Policy osztályok beregisztrálása. Akinek esetleg mégsem menne, az ebben a GitHub commit-ben tudja megvizsgálni a megvalósítás részleteit.

Ezután a karbantartó és gépkezelő szerepkörű felhasználók is már csak olvasni tudják a berendezések és dokumentumok listáját és részleteiket (lásd az iménti képernyőképet). A berendezés típusokhoz már hozzá sem férnek. Ez amiatt van, mert a két szerepkörhöz a korábban lefuttatott seeder osztályunk csak a "read devices" és "read documents" jogosultságokat rendelte hozzá. Az már egy döntés kérdése, hogy adunk-e még további jogköröket esetleg, de a jelenlegi alapértelmezett állapotban csak olvasni tudják a részleteket ennél a két erőforrás típusnál (berendezések és dokumentumok). További jogosultságokra akkor lesz szükség, ha a hibabejelentési űrlapok is bekerülnek a rendszerbe, akkor érdemes meghatározni azt, hogy milyen jogosultságokkal rendelkezzenek a hibabejelentő űrlapok kapcsán az említett szerepkörökhöz (karbantartó, gépkezelő) tartozó felhasználók.


Dolgozzunk együtt: egyéni oktatás, mentorálás, fejlesztés, tanácsadás

Ha egyéni oktatás, mentorálás, vagy fejlesztési projekt kapcsán szeretnél segítséget kérni tőlem, esetleg együttműködni velem, akkor keress meg a weboldalamon található elérhetőségeken keresztül!