1. Créez et modifiez une note comme Alex
Connectez-vous comme Alex et ouvrez Notes de formation → Notes.
À observer dans la liste : Alex · visible avant la règle est présent et Sam · visible avant la règle est absent. La vue ne contient aucun domaine de propriétaire ; la règle sur les enregistrements limite la recherche de l'ORM avant l'affichage.
- Créez une note intitulée Alex · test temporaire avec le contenu Version créée par Alex., puis enregistrez-la.
- Rouvrez cette note, remplacez son contenu par Version modifiée par Alex., puis enregistrez de nouveau.
- Copiez l'URL de cette fiche et conservez-la pour le test avec Sam.
À observer : la création et la modification sont acceptées. Comme la création n'envoie pas user_id, le défaut du modèle renseigne Alex ; le domaine du propriétaire correspond donc à l'utilisateur courant.
2. Répétez les mêmes opérations comme Sam
Déconnectez Alex, connectez-vous comme Sam et ouvrez la même liste.
À observer dans la liste : Sam · visible avant la règle est présent. Les deux titres d'Alex sont absents.
- Créez Sam · test temporaire avec le contenu Version créée par Sam., puis enregistrez-la.
- Remplacez ce contenu par Version modifiée par Sam. et enregistrez de nouveau.
- Copiez l'URL de la fiche de Sam.
- Ouvrez maintenant l'URL de la fiche d'Alex conservée à l'étape précédente.
À observer : la création et la modification de Sam sont acceptées. En revanche, l'URL d'Alex provoque un refus d'accès ou indique que l'enregistrement est indisponible. Le texte exact peut varier, mais aucun titre ni contenu d'Alex ne doit apparaître dans la fiche.
Un domaine placé seulement sur une action ou une vue retirerait la ligne de cet écran. Ici, le domaine appartient à ir.rule : l'ORM refuse aussi l'ouverture directe de l'enregistrement, sans dépendre de la présentation.
3. Vérifiez l'autre sens, puis les suppressions
- Reconnectez-vous comme Alex et ouvrez l'URL copiée depuis la fiche Sam · test temporaire. Odoo doit refuser l'accès sans afficher son contenu.
- Revenez à Alex · test temporaire. Dans le menu Actions de la fiche, choisissez Supprimer et confirmez. La note disparaît de la liste d'Alex.
- Reconnectez-vous comme Sam, ouvrez Sam · test temporaire, puis supprimez-la de la même manière. Elle disparaît de la liste de Sam.
Chaque utilisateur a ainsi créé, lu, modifié et supprimé son propre enregistrement. Pour l'enregistrement de l'autre utilisateur, l'accès direct est arrêté avant même que la fiche propose une modification ou une suppression. Ces deux opérations sont soumises au même domaine de propriétaire.
4. Bilan des opérations observées
| Utilisateur authentifié | Enregistrement visé | Création | Lecture | Modification | Suppression |
|---|---|---|---|---|---|
| Alex | Note attribuée à Alex | Acceptée | Acceptée | Acceptée | Acceptée |
| Alex | Note attribuée à Sam | — | Refusée | Refusée | Refusée |
| Sam | Note attribuée à Sam | Acceptée | Acceptée | Acceptée | Acceptée |
| Sam | Note attribuée à Alex | — | Refusée | Refusée | Refusée |
La création n'a pas de cible existante, d'où le tiret dans les deux lignes croisées. Lorsqu'Alex ou Sam crée une note, le modèle remplace toute valeur de propriétaire proposée par l'identifiant de l'utilisateur authentifié. Le client ne peut donc pas créer une note au nom de l'autre compte.
5. Créez une clé d'API d'une journée pour chaque compte
Ouvrez deux sessions de navigateur distinctes, par exemple deux profils. Dans la première, connectez-vous comme Alex ; dans la seconde, connectez-vous comme Sam. Ouvrez Préférences → Sécurité → Clés d'API dans chacune, puis vérifiez le nom affiché en haut à droite.
Lancez le bloc adapté à votre terminal. Il attend chaque secret sans afficher les caractères saisis. Suivez les invites dans cet ordre :
- À l'invite d'Alex, créez dans sa session une clé nommée Jour 5 · Alex, valable 1 jour. Copiez le secret, collez-le immédiatement dans le terminal, puis validez. Ne générez pas encore la clé de Sam.
- À l'invite de Sam, créez dans sa session une clé nommée Jour 5 · Sam, également valable 1 jour. Copiez son secret, collez-le dans le terminal, puis validez.
- À la dernière invite, saisissez le nom exact de la base d'exercice.
printf "Clé d’API d’Alex : "
IFS= read -rs TRAINING_API_KEY_ALEX
printf "\nClé d’API de Sam : "
IFS= read -rs TRAINING_API_KEY_SAM
printf "\nBase d'exercice : "
IFS= read -r TRAINING_DATABASE
export TRAINING_API_KEY_ALEX TRAINING_API_KEY_SAM TRAINING_DATABASE$alexKey = Read-Host "Clé d’API d’Alex" -AsSecureString
$env:TRAINING_API_KEY_ALEX = [System.Net.NetworkCredential]::new("", $alexKey).Password
$samKey = Read-Host "Clé d’API de Sam" -AsSecureString
$env:TRAINING_API_KEY_SAM = [System.Net.NetworkCredential]::new("", $samKey).Password
$env:TRAINING_DATABASE = Read-Host "Base d'exercice"La clé d'Alex authentifie Alex ; celle de Sam authentifie Sam. Elle ne leur accorde aucune ACL et ne neutralise aucune règle sur les enregistrements. Ne placez jamais ces valeurs dans un fichier source, une capture d'écran ou une commande qui les affiche.
6. Appelez le même GET avec les deux identités
Envoyez deux requêtes vers le même point d'accès. Seule la variable utilisée dans l'en-tête Authorization change ; l'en-tête X-Odoo-Database sélectionne la même base d'exercice.
Linux ou macOS
curl --include \
--header "X-Odoo-Database: $TRAINING_DATABASE" \
--header "Authorization: Bearer $TRAINING_API_KEY_ALEX" \
http://127.0.0.1:8069/training/api/notescurl --include \
--header "X-Odoo-Database: $TRAINING_DATABASE" \
--header "Authorization: Bearer $TRAINING_API_KEY_SAM" \
http://127.0.0.1:8069/training/api/notesWindows avec PowerShell
curl.exe --include --header "X-Odoo-Database: ${env:TRAINING_DATABASE}" --header "Authorization: Bearer ${env:TRAINING_API_KEY_ALEX}" http://127.0.0.1:8069/training/api/notescurl.exe --include --header "X-Odoo-Database: ${env:TRAINING_DATABASE}" --header "Authorization: Bearer ${env:TRAINING_API_KEY_SAM}" http://127.0.0.1:8069/training/api/notesRéponse d'Alex : le statut est 200 OK. Le tableau notes contient Alex · visible avant la règle et ne contient pas Sam · visible avant la règle.
Réponse de Sam : le statut est également 200 OK. Le tableau contient Sam · visible avant la règle et ne contient pas le titre d'Alex. Dans chaque réponse, count compte uniquement les notes que le propriétaire de cette clé peut lire.
D'autres anciennes notes peuvent appartenir à l'un des deux comptes selon l'état de votre base d'exercice. Elles peuvent donc apparaître dans sa réponse. Le contrôle décisif reste le même : aucun enregistrement appartenant à l'autre utilisateur ne traverse la règle sur les enregistrements.
N'envoyez pas user_id, n'ajoutez aucune identité dans l'URL ou dans un corps de requête GET et ne filtrez pas la réponse après réception. La route utilise request.env avec l'utilisateur de la clé ; sa recherche ORM et la règle sur les enregistrements doivent produire directement la liste autorisée.
7. Gardez les deux clés pour la suite du Jour 5
Ne révoquez pas encore les clés d'Alex et de Sam et ne fermez pas le terminal qui contient leurs variables. Les sections 3 et 4 les réutiliseront pour comparer les interfaces. Vous révoquerez les deux clés et effacerez les variables lors du nettoyage final du Jour 5.
Point de contrôle — comparez quatre preuves visibles
La liste, l'URL directe, les opérations sur les notes temporaires et les deux réponses GET concordent. Alex atteint seulement les notes attribuées à Alex ; Sam atteint seulement celles attribuées à Sam. La session ou la clé établit l'identité, l'ACL accorde l'opération et la règle sur les enregistrements limite les notes accessibles.