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…
Authentification
eCorpus combine deux notions d’autorité distinctes sur chaque requête :
- un niveau utilisateur global à l’instance, et
- un niveau d’accès propre à chaque scène.
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é surPOST /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 :
- l’attribution explicite par utilisateur (voir
PATCH /auth/access/{scene}), - toute attribution héritée d’un groupe dont l’utilisateur est membre,
- le
default_accessde la scène (s’applique à tout utilisateur connecté ; plafonné àwrite), - le
public_accessde la scène (s’applique à tout le monde, visiteurs anonymes compris ; plafonné àread), - la dérogation administrateur (les utilisateurs
adminobtiennent toujoursadmin).
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 :
- 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 un401immédiat (jamais de repli silencieux vers l’anonyme). - Cookie de session — le mode de connexion du navigateur. Le cookie
sessionne 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 :
- Envoyez l’utilisateur sur
GET /auth/oauth/authorizeavecclient_id, uneredirect_uriexacte,response_type=code, unscopeexplicite et uncode_challenge(+code_challenge_method=S256). - 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=nonesonde sans interface,prompt=consentforce l’affichage de la page. - L’application échange le
codeà usage unique surPOST /auth/oauth/tokenavec soncode_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.