Passa al contenuto principale

Permessi ABAC

Efesto integra CASL per il controllo degli accessi basato sugli attributi (ABAC). L'intero contributo del framework è piccolo e preciso:

  1. Dichiari una tupla permission: [action, model] su un endpoint.
  2. Tu costruisci un'ability CASL e la metti sulla request/context.
  3. Prima di eseguire l'handler, Efesto verifica l'ability rispetto alla tupla e rifiuta la richiesta se non è consentita.

Tutto qui. Non ci sono decoratori di permessi, gerarchie di ruoli o loader di database integrati in Efesto: quelli sono pattern che costruisci sopra, con CASL.

1. Costruisci l'ability (il tuo codice)

L'ability è tua da creare, di solito nel middleware di autenticazione, a partire dall'utente autenticato. Entrambi gli stack se la aspettano su un campo di contesto chiamato ability per default.

Allega l'ability a req in un middleware che viene eseguito prima di Efesto:

import { defineAbility } from "@casl/ability";

app.use((req, res, next) => {
req.ability = defineAbility((can) => {
can("readAll", "User");
can("readOne", "User");
can("create", "User");
});
next();
});

app.use("/api/v1", efesto({ /* ... */ }));

2. Dichiara il permesso sull'endpoint

La tupla è [action, model] su entrambi gli stack. Efesto la verifica con ability.can(action, model) prima che l'handler venga eseguito.

Dichiara permission all'interno dell'oggetto _<method>Swagger del metodo. Viene scritto nello Swagger generato e applicato a runtime:

import { BaseApiService, SwaggerOptions } from "efesto";

class Users extends BaseApiService {
constructor() {
super(__filename);
}

_getSwagger: SwaggerOptions = {
operationId: "getUsers",
permission: ["readAll", "User"],
responses: { 200: { content: { "application/json": { schema: { type: "array", items: "@User" } } } } },
};

_get(req, res) {
return res.json(listUsers());
}
}
export default Users;

3. Cosa succede in caso di fallimento

Se l'ability non può eseguire l'azione, Efesto solleva un ForbiddenError di CASL prima che il metodo venga eseguito. Gestiscilo nel tuo errorMiddleware per modellare la risposta.

Nessuna ability, nessun controllo

Su entrambi gli stack il controllo è applicato solo quando un'ability è presente nel contesto. Se non ne alleghi mai una, permission è documentato ma non applicato. Il guard di Elysia rispecchia intenzionalmente il comportamento di Express in questo caso.

Configurazione

Regola l'applicazione tramite configurazione. I default corrispondono alle descrizioni sopra.

Nell'oggetto config di Efesto:

config: {
abacPermissions: {
actions: ["readAll", "readOne", "create", "update", "delete"], // azioni documentate
models: ["User", "Product"], // modelli documentati
checkPermissionBeforeResolver: true, // applica prima dell'handler (default true)
reqAbilityField: "ability", // dove Efesto legge l'ability (default "ability")
},
}
ProprietàTipoDescrizioneDefault
actionsstring[]Azioni disponibili (tipizzazione/aiuto per la tupla)
modelsstring[]Modelli disponibili
checkPermissionBeforeResolverbooleanApplica prima che il metodo venga eseguitotrue
reqAbilityFieldstringCampo di req che contiene l'ability"ability"

Oltre le basi

Ruoli, regole di proprietà, finestre temporali e permessi basati su database sono tutti possibili, ma sono funzionalità di CASL e logica della tua applicazione, non API di Efesto. Li esprimi quando fai defineAbility (passo 1); Efesto si limita a verificare l'ability risultante rispetto alla tupla dichiarata. Vedi la documentazione di CASL per condizioni e regole a livello di campo.

L'ability viene di solito costruita nel tuo livello di autenticazione.