Sécurité et autorisation
Arrel décide de l'accès sur le serveur, à chaque endpoint. Le frontend masque les boutons que vous ne pouvez pas utiliser, mais c'est une commodité : la vraie protection, c'est que l'API les refuse.
Couches d'une requête
Une requête vers l'API d'un Resource passe, dans cet ordre, par :
- Le middleware de
config('arrel.middleware')(par exemple, identifier le tenant). - La session Sanctum (
auth:sanctum). - La vérification de l'e-mail et le second facteur, s'ils sont activés (voir Authentification).
- Le middleware de
config('arrel.authenticated_middleware'). - L'autorisation du Resource, de la page ou de l'action.
Resources
Les cinq méthodes canViewAny(), canView(), canCreate(), canEdit() et canDelete() délèguent à la Policy du modèle, ou peuvent être remplacées (voir Resources).
Un Resource pour lequel canViewAny() est faux est fermé sur tous les endpoints : la liste, mais aussi le schéma, la création, l'édition, la suppression, les actions, les options des champs et les relations répondent 403. Sans cette règle, un modèle sans Policy laisserait canCreate() ou canEdit() ouverts de façon indépendante.
Cela signifie que, pour un modèle sans Policy, tout est permis à n'importe quel utilisateur authentifié. Si le Resource doit être restreint, définissez une Policy ou remplacez canViewAny().
Actions
- Une action avec
authorize()utilise cette closure, avec les mêmes arguments quehandle(). - Une action sans
authorize()exigecanEdit()sur l'enregistrement, oucanCreate()si elle eststandalone(). Déclarezauthorize()sur les actions qui doivent rester ouvertes à plus d'utilisateurs. - Les actions intégrées suivent leur habilité :
ViewActiondemandecanView(),EditActionetRestoreActiondemandentcanEdit(),DeleteActionetForceDeleteActiondemandentcanDelete(). - Les options qu'une action offre à ses champs de relation ne sont servies qu'aux utilisateurs qui peuvent l'exécuter.
Relations
Si un champ Relation déclare query(), la portée s'applique aussi à la sauvegarde : un enregistrement que la portée masque dans la liste est refusé avec une erreur de validation, même si quelqu'un envoie son identifiant à la main. C'est identique dans les formulaires d'un Resource, d'un Relation manager et d'une action.
Relation::make('author_id')
->related(User::class)
->query(fn (Builder $query): Builder => $query->where('team_id', auth()->user()->team_id))Dans la closure de query() d'un champ d'un Relation manager ou d'une action, l'enregistrement parent arrive comme troisième argument.
Envois de fichiers
- Les envois sont limités à 60 par minute et par utilisateur.
- À la sauvegarde d'un enregistrement, seuls les fichiers réellement envoyés dans le répertoire temporaire (
arrel-temp) sont déplacés. Une valeur qui ne correspond pas à un envoi réel n'est pas déplacée. - Le contenu des champs
RichEditorest assaini côté serveur à chaque sauvegarde.
Limites de tentatives
| Quoi | Limite |
|---|---|
| Connexion | 5 tentatives échouées par e-mail et adresse IP |
| Second facteur d'une connexion en attente | 5 codes incorrects, et expire au bout de 5 minutes |
| Envoi de l'e-mail de vérification | 3 par minute |
| Confirmer ou désactiver le second facteur | 10 par minute |
| Envois de fichiers | 60 par minute et par utilisateur |
Pages
Page::canView() décide si une page est visible et accessible. Une page qui ne peut pas être vue disparaît de la navigation et répond 403 sur l'API. Pour une CustomPage, visible() contrôle l'entrée de navigation ; l'autorisation des données que la page charge doit être faite dans les endpoints de votre application, qui sont votre code.
Liste de contrôle
- Chaque modèle exposé a une Policy, ou le Resource remplace les
can...(). - Les actions qui ne doivent pas être réservées aux éditeurs déclarent
authorize(). - Les champs
Relationqui montrent des enregistrements d'autrui ontquery(). sanctum.statefulne contient que les domaines de votre panneau.- Le second facteur est obligatoire (
isRequiredFor()) pour les rôles les plus privilégiés.