I configuració dinàmica per BBDD?
Per passar la configuració de seguretat (grups i permisos) del sistema de fitxers de CodeIgniter 4 (com AuthGroups.php) a la Base de Dades, cal fer un canvi en la manera com Shield gestiona la persistència. Aquest seria un pas crític quan vols crear un panell d'administració on pots crear nous grups o assignar permisos sense haver de modificar codi PHP i pujar-lo al servidor.
Pas 1: Crear les taules de la BBDD
Shield ja porta incorporada la capacitat de gestionar grups i permisos a la BD, però necessita unes taules específiques per a la configuració "global" (no només la relació usuari-grup). Si vas executar php spark shield:setup, ja tens les taules d'assignació, però per a la configuració dinàmica necessitarem gestionar:
-
auth_groups_config: Per guardar els noms i descripcions dels grups. -
auth_permissions_config: Per guardar la llista de permisos disponibles. -
auth_groups_permissions: Per a la matriu de quins grups tenen quins permisos.
Pas 2: Canviar el Handler a app/Config/AuthGroups.php
Per defecte, Shield llegeix les arrays $groups, $permissions i $matrix. Per fer-ho dinàmic, hem d'estendre el comportament. CodeIgniter 4 permet sobreescriure aquestes configuracions en el constructor o mitjançant un Service. La millor manera és crear un Provider personalitzat. Tanmateix, per a un exemple d'apunts directe, modificarem el constructor de la classe AuthGroups:
namespace Config;
use CodeIgniter\Shield\Config\AuthGroups as ShieldGroups;
class AuthGroups extends ShieldGroups
{
public function __construct()
{
parent::__construct();
// 1. Aquí connectem amb la BBDD
$db = \Config\Database::connect();
// 2. Carreguem els Grups des de la taula
$this->groups = $this->loadGroupsFromDb($db);
// 3. Carreguem els Permisos des de la taula
$this->permissions = $this->loadPermissionsFromDb($db);
// 4. Carreguem la Matriu (quants permisos té cada grup)
$this->matrix = $this->loadMatrixFromDb($db);
}
private function loadGroupsFromDb($db) {
// Lògica per fer SELECT * FROM auth_groups_config i retornar l'array
}
// ... resta de mètodes de càrrega ...
}
Pas 3: Crear panell gestió (CRUD)
Ara que Shield mira a la base de dades, pots crear un controlador d'administració per gestionar-ho.
Exemple: controlador per afegir un permís nou
Recorda que amb el nostre sistema anterior, els permisos segueixen la convenció controlador.metode.
public function addPermission()
{
$newPermission = $this->request->getPost('permission'); // ex: 'api.inventory.update'
$description = $this->request->getPost('description');
$db = \Config\Database::connect();
$db->table('auth_permissions_config')->insert([
'name' => $newPermission,
'description' => $description
]);
return redirect()->to('/admin/permissions')->with('msg', 'Permís creat correctament.');
}
Avantatges
-
Edició en temps real: No cal reiniciar serveis ni fer deploy de codi per tancar l'accés a una part de l'API.
-
Interfície d'Usuari: Pots permetre que un "SuperAdmin" gestioni els permisos de la resta d'empleats des d'una taula visual (Checkboxes).
-
Auditabilitat: Pots saber exactament quan es va afegir un permís a un grup si afegeixes camps de
created_ata les taules de configuració.
I el rendiment, que tal? (Caching)
Llegir la base de dades en cada petició per carregar tota la matriu de permisos pot alentir l'aplicació. Per això, és obligatori usar el Cache de CodeIgniter 4:
public function __construct()
{
$cache = \Config\Services::cache();
if (! $this->groups = $cache->get('auth_groups_settings')) {
// Si no està en cache, ho busquem a la BD...
$this->groups = $this->loadGroupsFromDb($db);
// Ho guardem per a les properes vegades (ex: 24 hores)
$cache->save('auth_groups_settings', $this->groups, DAY);
}
}
ATENCIÓ: Cal esborrar la cache ($cache->delete('auth_groups_settings')) cada vegada que actualitzis un permís des del panell d'administració.
Amb aquesta arquitectura, tindriem un sistema Enterprise-Ready:
-
Seguretat: Shield + RBAC.
-
Automatització: Filtres per convenció
controller.method. -
Flexibilitat: Gestió total des de Base de Dades amb Cache per a màxim rendiment.