Utiliser l’API

eCorpus fournit une API complète qui couvre les besoins de DPO Voyager en y ajoutant des interfaces de gestion des utilisateurs, contrôle des droits d’accès, organisation des scènes en collections, etc…

Documentation de l'API

Authentification

eCorpus combine deux notions d’autorité distinctes sur chaque requête :

Note : l’authentification HTTP Basic avec un nom d’utilisateur et un mot de passe a été supprimée dans eCorpus v0.3.0. Authorization: Basic … ne sert plus qu’à authentifier un client OAuth enregistré sur POST /auth/oauth/token. Si votre instance utilise encore la v0.2.x, consultez le guide d’authentification de l’ancienne version.

Niveaux utilisateur

Chaque compte a exactement un niveau. Ils sont ordonnés — un niveau supérieur inclut les capacités des niveaux inférieurs :

Niveau Signification
none Niveau de quarantaine : le compte peut se connecter, mais ne détient aucune portée account:* — il ne peut donc ni créer ni révoquer ses propres identifiants. L’interface ne l’attribue jamais. Une requête anonyme, elle, n’a aucun compte associé.
use Utilisateur authentifié. Peut consulter les scènes auxquelles il a accès, mais ne peut pas créer de scènes.
create Niveau par défaut d’un compte nouvellement créé. Peut créer des scènes.
manage Peut en plus gérer les groupes.
admin Administrateur de l’instance. Dispose implicitement d’un accès admin sur toutes les scènes et peut atteindre les routes /admin.

Niveaux d’accès par scène

Indépendamment de son niveau, un utilisateur se voit accorder un niveau d’accès sur chaque scène, ordonné none < read < write < admin. L’accès effectif sur une scène est le maximum de :

Un visiteur anonyme n’obtient jamais plus que le public_access d’une scène.

Authentifier une requête

Une requête est identifiée, par ordre de précédence :

  1. Jeton Bearer — envoyez Authorization: Bearer ec_…. Utilisé par les scripts, services et clients en ligne de commande. Un jeton présenté mais invalide/révoqué provoque un 401 immédiat (jamais de repli silencieux vers l’anonyme).
  2. Cookie de session — le mode de connexion du navigateur. Le cookie session ne transporte qu’un identifiant de session opaque ; l’identité (et le niveau actuel du compte) est relue côté serveur à chaque requête : déconnexions, changements de mot de passe et changements de niveau prennent effet immédiatement. Les sessions durent 31 jours et se renouvellent automatiquement (fenêtre glissante).

Créez un jeton depuis l’interface web (ou avec POST /auth/tokens depuis une session connectée), puis utilisez-le comme jeton porteur :

curl -XGET -H "Authorization: Bearer ec_xxxxxxxx" https://ecorpus.holusion.com/[...]

Vous pouvez aussi ouvrir une session de type navigateur et réutiliser son cookie :

# Connexion, en enregistrant le cookie de session
curl -c cookies.txt -XPOST https://ecorpus.holusion.com/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username":"<username>","password":"<password>"}'

# Réutilisation du cookie sur les requêtes suivantes
curl -b cookies.txt -XGET https://ecorpus.holusion.com/[...]

Dans ce cas un jeton d’authentification “session” sera stocké sur votre disque. Ce jeton donne un accès sans restriction à votre compte.

Jetons d’accès personnels

Un utilisateur connecté crée un jeton avec POST /auth/tokens, depuis une session interactive uniquement — un jeton ne peut jamais créer un autre jeton, même avec la portée all. Vous choisissez un nom, un ensemble de portées (scopes) et une expiration optionnelle ; le secret ec_… n’est renvoyé qu’une seule fois et n’est jamais stocké côté serveur. Un jeton ne peut jamais faire plus que ce que le niveau actuel de son propriétaire permet, et ses portées le restreignent davantage.

Une portée s’écrit <famille>:<niveau>, et détenir un niveau implique tous ceux du dessous (read ⊂ write ⊂ admin) :

Portée Autorise
all Toutes les portées délégables — un raccourci pour l’ensemble du tableau ci-dessous.
corpus:read La base d’identité, « utilisateur reconnu de cette instance ». Portée par tout jeton, quelles que soient les portées demandées.
corpus:write Ajouter des scènes à la collection (création de scène, import d’archive).
scenes:read / scenes:write / scenes:admin Plafonne le niveau obtenable sur les scènes auxquelles l’ACL donne déjà accès (la visibilité est inchangée).
tasks:read / tasks:write / tasks:admin L’API /tasks.
users:read / users:write Administration des autres comptes : inventaire, création, révocation de leurs jetons.
groups:read / groups:admin Inventaire des groupes et gestion des membres.
instance:read Statistiques et inventaire de la configuration de l’instance (supervision).
account:read / account:write Lister et révoquer ses propres sessions, jetons et autorisations OAuth.

Trois portées sont non délégables : account:admin (créer des identifiants, changer son mot de passe ou son adresse e-mail), users:admin (liens de connexion, création d’administrateurs) et instance:write (réécriture de la configuration, registre des clients OAuth). Aucun jeton — pas même de portée all — ne les porte : elles exigent une session interactive.

Listez et révoquez vos jetons avec GET/DELETE /auth/tokens. Quiconque détient un jeton peut le révoquer via POST /auth/oauth/revoke.

OAuth2 (code d’autorisation + PKCE)

Pour les applications tierces. Un administrateur enregistre un client (POST /auth/oauth/clients) avec une ou plusieurs URI de redirection ; les clients confidentiels reçoivent un secret, les clients publics (CLI, SPA) reposent uniquement sur PKCE (Proof Key for Code Exchange). Le flux est un octroi par code d’autorisation standard avec PKCE (S256) obligatoire :

  1. Envoyez l’utilisateur sur GET /auth/oauth/authorize avec client_id, une redirect_uri exacte, response_type=code, un scope explicite et un code_challenge (+ code_challenge_method=S256).
  2. L’utilisateur se connecte (une session est requise) et approuve sur la page de consentement (POST /auth/oauth/authorize). L’approbation est persistée en tant que grant, si bien que les demandes ultérieures couvertes par un grant existant sont accordées silencieusement — pratique pour les renouvellements. prompt=none sonde sans interface, prompt=consent force l’affichage de la page.
  3. L’application échange le code à usage unique sur POST /auth/oauth/token avec son code_verifier, et reçoit un jeton d’accès Bearer valable 30 jours.

Les utilisateurs consultent les applications qu’ils ont approuvées avec GET /auth/oauth/grants et en révoquent une avec DELETE /auth/oauth/grants/{clientId} — ce qui révoque aussi tous les jetons que ce client détient pour eux. Les métadonnées du serveur sont découvrables sur /.well-known/oauth-authorization-server.

Sessions et CSRF

Les utilisateurs listent leurs sessions actives (GET /auth/sessions) et peuvent en révoquer par identifiant ; un changement de mot de passe évince toutes les sessions du compte. Les méthodes non sûres des requêtes authentifiées par cookie sont protégées contre le CSRF par des vérifications Sec-Fetch-Site/Origin ; les requêtes par jeton Bearer et les requêtes anonymes en sont exemptées (un header ne voyage pas de lui-même entre sites).

Le détail des routes /auth est documenté (en anglais) dans la section auth de la référence de l’API. Pour la logique de conception derrière ce modèle (vocabulaire des scopes, middleware de garde, contrat de codes de statut), voir le document de conception Identity & Access Control (en anglais).

Organisation des scenes

Organisation des fichiers :

├── foo/
│   ├── scene.svx.json
│   ├── scene-image-thumb.jpg
│   ├── models/
│   │   └── foo.glb
│   └── articles/
│       └── foo-FR.html
└── bar/
    ├── scene.svx.json
    ├── scene-image-thumb.jpg
    ├── models/
    │   └── bar.glb
    └── articles/
        └── bar-FR.html

Exportation des données

Ainsi pour récupérer un modèle :

curl -XGET -H "Authorization: Bearer ${TOKEN}" https://${HOSTNAME}/scenes/foo/models/foo.glb

Pour récupérer une ou plusieurs scènes :

curl -XGET https://${HOSTNAME}/scenes?name=${NAME}&format=zip

Vous pouvez ajouter autant de paramètres name="..." que nécessaire, séparés par des caractères &.

Importation des données

Pour importer une scène ou une collection de scènes exportées d’une instance eCorpus :

curl -XPOST https://${HOSTNAME}/scenes --data-binary "@${ZIP_FILE}" -H "Authorization: Bearer ${TOKEN}" | jq .

Le jeton doit porter à la fois corpus:write et scenes:write (ou être de portée all). Chaque scène de l’archive est ensuite vérifiée individuellement : écraser une scène existante demande un accès write sur celle-ci, et en créer une nouvelle demande au moins le niveau create.

Cette requête retourne une liste des changements effectués qui peut être assez longue. Vous pouvez filtrer les échecs en utilisant jq .fail ou si vous n’avez pas jq installé, vous pouvez utiliser curl en mode silencieux et inspecter uniquement le status de la réponse : curl -s --fail -o /dev/null -w "%{http_code}".

API REST et spécification

Les verbes GET PUT MOVE DELETE MKCOL et PROPFIND sont supportés, avec un comportement se conformant généralement à la spécification. Attention tout de même : Il s’agit d’une implémentation partielle de la spécification (COPY et LOCK/UNLOCK ne sont pas implémentés).

L’API REST est documentée via un schéma OpenAPI v3.2.0, téléchargeable ici : openapi.yml. L’API est présentée sous forme lisible en anglais uniquement sur ce site à cette page : https://ecorpus.eu/en/doc/hosting/apiDoc.html.