Rôle et slug¶
Objectif : comprendre la brique rôle, son nom lisible et son slug stable.
Ce que vous allez apprendre : un rôle a un nom (« Éditeur en chef ») et un
slug identifiant (editeur-en-chef). normalize_role_slug dérive le slug ;
validate_role refuse un rôle invalide.
Troisième palier du niveau débutant de la progression RBAC.
Module opt-in
Ce starter suppose forge-mvc-rbac installé (palier « Installation »).
Ce que ce starter montre¶
normalize_role_slug(name)→ slug stable ;validate_role(name, slug)→ validité ;- une transformation pure.
Classes Forge utilisées¶
| Classe / fonction | Rôle dans ce starter | Référence |
|---|---|---|
forge_mvc_rbac.normalize_role_slug |
Dériver un slug depuis un nom de rôle. | RBAC |
forge_mvc_rbac.validate_role |
Refuser un rôle invalide. | RBAC |
Tester¶
Ouvrez https://localhost:8000/rbac-role?name=Éditeur en chef → slug
editeur-en-chef.
Le contrôleur¶
Créez le contrôleur mvc/controllers/rbac_role_controller.py :
# mvc/controllers/rbac_role_controller.py
from core.http.request import Request
from core.http.response import Response
from core.mvc.controller.base_controller import BaseController
from forge_mvc_rbac import RbacValidationError, normalize_role_slug, validate_role
_DEMO_NAME = "Éditeur en chef"
def _role_view(name: str) -> dict:
slug = normalize_role_slug(name)
try:
validate_role(name, slug)
return {"name": name, "slug": slug, "valid": True, "error": None}
except RbacValidationError as exc:
return {"name": name, "slug": slug, "valid": False, "error": str(exc)}
class RbacRoleController(BaseController):
"""Starter pédagogique : dériver et valider un rôle (nom + slug)."""
@staticmethod
def index(request: Request) -> Response:
name = request.query("name") or _DEMO_NAME
return BaseController.render(
"rbac_role/index.html", context=_role_view(name), request=request
)
Comprendre ce code¶
- Le slug est l'identifiant stable du rôle ; il ne change pas même si le nom
d'affichage évolue. - Séparer nom et slug évite de coder en dur des libellés dans les comparaisons.
validate_rolegarantit un couple nom/slug cohérent.
La vue¶
Créez la vue mvc/views/rbac_role/index.html :
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Rôle et slug - Forge</title>
</head>
<body>
<h1>Rôle et slug</h1>
<form method="get" action="/rbac-role">
<input type="text" name="name" value="{{ name }}" size="40">
<button type="submit">Dériver le slug</button>
</form>
<ul>
<li>Nom : <code>{{ name }}</code></li>
<li>Slug : <code>{{ slug }}</code></li>
<li>Valide : <strong>{% if valid %}oui{% else %}non{% endif %}</strong>{% if error %} - {{ error }}{% endif %}</li>
</ul>
<p>Le <strong>slug</strong> est l'identifiant stable du rôle ; le <strong>nom</strong>
est l'affichage. Un rôle accorde des permissions via le contrat RBAC.</p>
</body>
</html>
La route¶
Ajoutez l'import et la route dans le groupe public de mvc/routes.py :
# mvc/routes.py
from mvc.controllers.rbac_role_controller import RbacRoleController
with router.group("", public=True) as public:
public.add("GET", "/rbac-role", RbacRoleController.index, name="rbac_role_index")
À retenir¶
- Un rôle = un nom (affichage) + un slug (identité stable).
- Le slug est ce qui apparaît dans le contrat et les associations.
- Nom et slug se valident ensemble.
Après ce starter¶
Vous avez les briques (permission, rôle). La suite (intermédiaire) : les confronter.