L'invitation API avec le paramètre group_names renvoie 403 pour le propriétaire du groupe s'il n'est pas administrateur

Résumé

Un utilisateur non administrateur qui est propriétaire d’un groupe Discourse peut inviter avec succès de nouveaux membres avec ce groupe assigné via la boîte de dialogue d’invitation de l’interface web. L’action identique via l’API REST (/invites.json, clé API de portée globale, Api-Username correct) renvoie une erreur 403 invalid_access — mais uniquement lorsque group_names/group_ids est inclus dans la charge utile. Cela se produit quel que soit le format de group_names transmis, en tant que chaîne simple (par ex. "group_names": "my-group") ou en tant que tableau (par ex. "group_names": ["my-group"]) — les deux formats produisent la même erreur 403.

Il est crucial de noter que l’attribution du statut Modérateur à l’utilisateur ne corrige pas l’appel API — seul l’attribution du statut Administrateur complet le fait, bien que le statut Modérateur soit suffisant pour tous les autres scénarios testés (interface web, invitation API sans groupe).

Environnement

  • Version de Discourse : [à compléter — page Administration → Mise à niveau]
  • Type de clé API : Portée globale, Api-Username = nom d’utilisateur exact de l’utilisateur de test

Étapes pour reproduire

  1. Créer un utilisateur non administrateur et non modérateur (<userid>), et le rendre propriétaire du groupe <group_name>.
  2. Interface web, en tant que <userid> : invitation sans groupe → succès. Invitation avec <group_name> assigné → succès.
  3. API, en tant que <userid> (clé de portée globale, Api-Username=<userid>):
    • POST /invites.json sans group_names → succès.
    • POST /invites.json avec group_names="<group_name>" (format chaîne) → 403 invalid_access.
    • POST /invites.json avec group_names=["<group_name>"] (format tableau) → 403 invalid_access (échec identique, les deux formats testés).
  4. Promouvoir <userid> au rang de Modérateur. Répéter les appels API groupés de l’étape 3 (les deux formats) → toujours 403 invalid_access.
  5. Promouvoir <userid> au rang d’Administrateur. Répéter les appels API groupés de l’étape 3, même clé, mêmes charges utiles → succès.

Comportement attendu

Puisque la simple propriété d’un groupe est une permission suffisante pour qu’un utilisateur non membre du personnel assigne ce groupe lors d’une invitation via l’interface web, l’API — authentifiée en tant que le même utilisateur via Api-Username — devrait respecter la même permission. À tout le moins, le statut Modérateur (qui est du personnel) ne devrait pas se comporter de manière identique à celle d’un utilisateur non privilégié ici ; le fait que le Modérateur échoue de la même manière qu’un utilisateur sans rôle, et que seul l’Administrateur réussisse, suggère que le chemin de code de l’API vérifie spécifiquement user.admin? plutôt que la propriété du groupe ou même le statut de personnel général (user.staff?, qui est vrai pour les modérateurs).

Comportement réel

L’API renvoie une erreur 403 pour toute invitation groupée (format paramètre chaîne ou tableau) à moins que l’utilisateur agissant ne soit un Administrateur complet. La propriété du groupe (vérifiée comme fonctionnant via l’interface web) et le statut Modérateur/personnel (vérifié via un test de promotion directe) sont tous deux insuffisants pour le chemin API, bien que l’un ou l’autre soit suffisant via l’interface web ou pour le cas API sans groupe.

Question pour l’équipe Discourse

Le chemin de code d’invitation avec groupe authentifié via l’API exige-t-il explicitement user.admin?, plutôt que de vérifier la propriété du groupe ou user.staff? comme le fait le chemin d’interface web / authentifié par session ? Si c’est le cas, est-ce intentionnel (restriction spécifique à l’API non documentée) ou s’agit-il d’un bug où la vérification du gardien de l’API diverge de la vérification du gardien de l’interface web pour cette action ?

Je suis prêt à fournir les journaux complets de requêtes/réponses (clé masquée) sur demande.