Étape 2 sur 2 · environ 35 min

Lisez les vraies notes avec l’utilisateur authentifié

La route de la section précédente utilise déjà l’ORM, mais elle élève ses privilèges pour rester anonyme. Exigez maintenant une clé d’API et laissez Odoo appliquer les droits de son propriétaire.

1. Remplacez le contrôleur anonyme

Ouvrez le fichier utilisé à la section 2 et remplacez tout son contenu par cette version. L’URL, la méthode GET et la lecture ORM restent les mêmes. La route POST anonyme disparaît pour le moment ; vous la recréerez proprement dans la section suivante.

custom_addons/training_hello/controllers/notes_api.py · version complète
from odoo import http
from odoo.http import request


class TrainingNotesApiController(http.Controller):
    @http.route(
        "/training/api/notes",
        type="http",
        auth="bearer",
        methods=["GET"],
    )
    def list_notes(self):
        notes = request.env["training.note"].search_read(
            fields=["id", "title", "body"],
            order="id desc",
            limit=20,
        )
        for note in notes:
            note["body"] = note["body"] or ""

        return request.make_json_response({
            "notes": notes,
            "count": len(notes),
        })

auth="bearer" demande à Odoo d’examiner l’en-tête Authorization avant d’appeler list_notes(). Avec une clé valide, Odoo retrouve l’utilisateur propriétaire et place son identité dans request.env, l’environnement de l’ORM pour cette requête.

L’appel request.env["training.note"].search_read(...) applique donc l’ACL et les éventuelles règles sur les enregistrements de cet utilisateur. Il conserve les trois champs et la limite de vingt notes, mais n’utilise plus sudo(). Les règles de propriétaire du jour 5 ne sont pas encore en place ; à ce stade, vous observez les droits réellement définis au jour 2.

Le modèle du Jour 2 définit le contenu ainsi :

custom_addons/training_hello/models/training_note.py · champ déjà présent
body = fields.Text(string="Contenu")

Ce champ ne comporte pas required=True et peut donc ne contenir aucun texte. La boucle remplace la valeur vide par "" afin que body reste une chaîne dans le JSON. La réponse garde les deux clés de premier niveau notes et count.

Le client ne choisit pas l’utilisateur

La requête n’envoie ni identifiant utilisateur ni champ d’identité. Elle présente seulement la clé. Odoo détermine son propriétaire, puis l’ORM travaille avec les droits de ce compte.

2. Redémarrez Odoo

Action qui redémarre Odoo : redémarrez votre processus Odoo local, puis attendez que les journaux indiquent que le serveur est de nouveau prêt. Vous avez modifié du Python ; un rechargement du navigateur ne relit pas le contrôleur.

Vous n’avez modifié ni champ, ni XML, ni manifeste. Une mise à niveau du module n’est donc pas nécessaire pour ce seul remplacement.

3. Comparez les trois appels sous Linux ou macOS

Utilisez le même terminal que dans l’étape précédente. --include affiche le statut et les en-têtes HTTP avant le corps. Les trois commandes visent exactement la même route locale.

Clé acceptée

Linux ou macOS · clé valide
curl --include \
  --header "Authorization: Bearer YOUR_API_KEY" \
  http://127.0.0.1:8069/training/api/notes

Résultat attendu : la première ligne contient 200 OK, le Content-Type est JSON et le corps contient les notes que cet utilisateur peut lire.

Exemple de corps · les identifiants et le nombre peuvent différer
{
  "notes": [
    {
      "id": 3,
      "title": "Une base d'exercice",
      "body": "Nous pouvons y apprendre sans toucher à des données réelles."
    },
    {
      "id": 2,
      "title": "Observer avant de modifier",
      "body": "La mise à niveau est le moment où Odoo applique les fichiers du module."
    },
    {
      "id": 1,
      "title": "Bienvenue",
      "body": "Une note est un enregistrement stocké par Odoo."
    }
  ],
  "count": 3
}

Ne comparez pas les nombres id avec l’exemple : ils dépendent de votre base. Vérifiez plutôt l’ordre décroissant, les trois clés de chaque note et l’égalité entre count et la longueur de notes.

Clé absente

Linux ou macOS · aucun en-tête Authorization
curl --include \
  http://127.0.0.1:8069/training/api/notes

Résultat attendu : Odoo répond 401 Unauthorized, annonce l’authentification Bearer dans l’en-tête WWW-Authenticate et ne renvoie aucune note.

Clé invalide

Linux ou macOS · un caractère ajouté à la clé
curl --include \
  --header "Authorization: Bearer YOUR_API_KEYx" \
  http://127.0.0.1:8069/training/api/notes

Résultat attendu : Odoo répond encore 401 Unauthorized. Le serveur a reçu un secret, mais il ne correspond à aucune clé API active.

4. Exécutez les mêmes cas dans PowerShell

Dans PowerShell, écrivez curl.exe afin d’appeler explicitement le programme cURL. Remplacez YOUR_API_KEY dans chaque commande par votre clé.

PowerShell · clé valide
curl.exe --include --header "Authorization: Bearer YOUR_API_KEY" http://127.0.0.1:8069/training/api/notes
PowerShell · clé absente
curl.exe --include http://127.0.0.1:8069/training/api/notes
PowerShell · clé invalide
curl.exe --include --header "Authorization: Bearer YOUR_API_KEYx" http://127.0.0.1:8069/training/api/notes

Vous devez observer la même suite : 200 OK avec les notes, puis deux réponses 401 Unauthorized sans données. Dans les deux refus, Odoo arrête la requête avant la lecture de training.note ; le contrôleur ne compare jamais la clé lui-même.

5. Conservez la clé pour les deux sections suivantes

Gardez ce terminal ouvert : la création par l’API, puis le client Vue, utiliseront la même clé temporaire. Ne copiez toujours pas la valeur dans un fichier source. Vous révoquerez la clé et effacerez la variable à la toute fin du Jour 4.

Résultat de la section

La même URL renvoie les vraies notes avec une clé valide et refuse les appels sans clé ou avec une clé invalide. L’identité vient d’Odoo, puis l’ORM applique les droits de cet utilisateur.