Étape 1 sur 1 · environ 25 min

Protégez le composant Owl contre un IDOR

Le composant Owl s’exécute dans le navigateur. Il utilise la session Odoo, mais la protection réelle reste côté serveur : l’ORM applique les ACL et la record rule.

1. La record rule protège les notes côté serveur

Une record rule est une condition qu’Odoo ajoute aux recherches et aux opérations sur un modèle. Dans la section suivante, elle conservera seulement les notes dont le propriétaire est l’utilisateur connecté.

Ce qu’Owl apporte déjà

Le service this.orm envoie la demande avec la session Odoo. L’ORM connaît donc l’utilisateur et applique les ACL, puis la record rule lorsqu’elle existe. Owl n’a pas de mécanisme de sécurité séparé à ajouter.

Le composant peut demander les notes de l'utilisateur actif pour garder une requête lisible. Ce filtre JavaScript reste une aide d'affichage : la record rule est nécessaire pour empêcher un IDOR côté serveur.

2. Lisez les notes avec le service ORM

Importez d'abord l'utilisateur de la session Odoo :

custom_addons/training_hello/static/src/training_notes/training_notes.js · import à ajouter
import { user } from "@web/core/user";

Dans loadNotes(), utilisez user.userId dans le domaine. Quand la record rule sera créée, Odoo appliquera aussi ce même filtre côté serveur.

custom_addons/training_hello/static/src/training_notes/training_notes.js · loadNotes()
async loadNotes() {
    this.state.notes = await this.orm.searchRead(
        "training.note",
        [["user_id", "=", user.userId]],
        ["title", "body", "user_id"]
    );
}

Pour une relation Many2one, searchRead() renvoie l’identifiant lié et son nom affiché. Le gabarit peut donc montrer le nom du propriétaire avec user_id[1]. Modifier ce domaine dans le navigateur ne contourne pas la record rule de la section suivante.

3. Créez une note sans envoyer son propriétaire

Le composant envoie seulement ce que la personne a saisi. Comme il n'envoie pas user_id, le défaut du modèle utilise env.user côté serveur.

custom_addons/training_hello/static/src/training_notes/training_notes.js · createNote()
async createNote() {
    const title = this.state.title.trim();
    if (!title) {
        return;
    }

    await this.orm.create("training.note", [{
        title,
        body: this.state.body,
    }]);

    this.state.title = "";
    this.state.body = "";
    await this.loadNotes();
}

N’ajoutez pas user_id aux valeurs envoyées. Même une valeur cachée dans la page vient du navigateur et ne constitue pas une identité fiable.

4. Affichez le propriétaire renvoyé par Odoo

Ajoutez la ligne du propriétaire dans la boucle des notes déjà présente :

custom_addons/training_hello/static/src/training_notes/training_notes.xml · boucle des notes
<li t-foreach="state.notes" t-as="note" t-key="note.id">
    <strong t-esc="note.title"/>
    <small>
        Propriétaire : <t t-esc="note.user_id[1]"/>
    </small>
    <p t-esc="note.body"/>
</li>

Le nom affiché est une information de présentation. Il aide à vérifier le résultat, mais ce n’est pas lui qui limite les notes visibles. t-esc affiche chaque valeur comme du texte et échappe le HTML : le contenu ne devient pas du balisage dans la page.

5. Vérifiez que le filtre Owl ne suffit pas

Ce test montre pourquoi un filtre dans le navigateur n'est pas une protection. Ajoutez temporairement debugger; au début de loadNotes(), puis mettez le module à niveau et rechargez Notes Owl.

custom_addons/training_hello/static/src/training_notes/training_notes.js · pause temporaire
async loadNotes() {
    debugger;
    this.state.notes = await this.orm.searchRead(
        "training.note",
        [["user_id", "=", user.userId]],
        ["title", "body", "user_id"]
    );
}

Lorsque le navigateur s'arrête sur cette ligne, ouvrez la console et exécutez :

Console du navigateur · depuis la pause dans loadNotes()
this.orm.searchRead(
    "training.note",
    [],
    ["title", "body", "user_id"]
).then((notes) => console.log(notes));

À observer avant la record rule : la console affiche toutes les notes que l'ACL autorise à lire, y compris celles de l'autre utilisateur. Le domaine écrit dans Owl a été retiré par le navigateur. Cela ne donne pas des droits supplémentaires : la session et les ACL restent appliquées.

Retirez ensuite debugger;. Après la section 4, rejouez exactement la même commande : la record rule filtrera aussi cette requête et ne laissera revenir que les notes du compte connecté.

6. Préparez le test de la section suivante

Mettez Hello Odoo à niveau, puis rechargez Notes Owl. Créez une note comme Alex, puis une autre comme Sam. Comme le composant ne fournit pas de propriétaire, le défaut du modèle utilise déjà le bon compte dans les deux cas.

La record rule n’est pas encore créée à ce stade. Après la section 4, relancez ce même test. Alex ne verra plus les notes de Sam, et Sam ne verra plus celles d’Alex, même si quelqu'un modifie ou retire le filtre Owl.

Point de contrôle — distinguez le composant de la protection

Owl demande les notes de user.userId et crée les notes avec la session Odoo. Sans user_id envoyé par Owl, le défaut du modèle renseigne le propriétaire ; puis la record rule limite les notes accessibles dans toutes les interfaces. C’est cette règle serveur qui empêche l’IDOR.