API
Routes d'administration et routes publiques de partage du module Fichiers.
Toutes les routes sont servies sous /lrvo/api/ par le gestionnaire générique du core. Aucun fichier de route n'est à monter dans le projet.
Routes d'administration
Elles demandent une session administrateur et la permission indiquée.
Espaces
| Méthode | Chemin | Permission |
|---|---|---|
GET | /drive/spaces | drive.view |
GET | /drive/stats | drive.view |
GET | /drive/folder-tree | drive.view |
GET /drive/spaces renvoie aussi la configuration utile au client : taille d'une tranche d'envoi, taille maximale d'un fichier, rétention de corbeille, nombre de versions conservées, couleur des icônes. GET /drive/shared-with-me porte le même bloc config, réduit à la couleur des icônes : c'est la seule vue d'administration qui n'appelle pas /drive/spaces.
GET /drive/stats rend l'occupation des espaces que l'appelant ouvre, et global, le volume total du serveur face à son quota. global vaut null sans drive.storage : ce total compte les espaces personnels des autres.
GET /drive/folder-tree rend les dossiers d'un espace, désigné par spaceId. Avec rootId, l'arbre se limite à ce dossier et à ce qu'il contient, la racine sortant sans parent. C'est la forme à utiliser dans un dossier reçu en partage interne : l'arbre de l'espace nommerait tous les dossiers du propriétaire.
Navigation
| Méthode | Chemin | Permission |
|---|---|---|
GET | /drive/nodes | drive.view |
GET | /drive/nodes/:id | drive.view |
PATCH | /drive/nodes/:id | drive.manage |
DELETE | /drive/nodes/:id | drive.delete |
POST | /drive/nodes/bulk-delete | drive.delete |
POST | /drive/folders | drive.manage |
GET /drive/nodes accepte spaceId, parentId, sort, direction, page et limit, plus quatre paramètres de recherche :
| Paramètre | Valeurs | Effet |
|---|---|---|
q | Texte libre | Ne garde que les noms qui contiennent ce terme, sans égard à la casse. |
scope | folder, subtree, space | Où chercher. folder par défaut. |
kind | folder, file | Ne garde que les dossiers, ou que les fichiers. |
type | document, spreadsheet, archive, image, other | Ne garde que les fichiers de cette famille. L'emporte sur kind. |
scope décide seul de la portée : folder s'en tient aux enfants directs de parentId, subtree descend dans tout ce qu'il contient, et space ignore parentId pour fouiller l'espace entier. Sans parentId, subtree vaut space. Fournir q sans scope cherche dans le dossier, pas dans l'espace.
Une valeur inconnue de scope, kind ou type vaut son absence.
Avec subtree ou space, chaque nœud porte location : le chemin du dossier qui le contient, en tableau de { id, name }, compté depuis le point de départ de la recherche. Il est vide pour un enfant direct de ce point de départ, et absent avec folder.
Quand parentId est fourni, c'est le dossier qui décide de l'espace : spaceId devient facultatif, et un spaceId qui ne correspond pas à celui du dossier répond « introuvable ». Sans parentId, la route liste la racine de spaceId, ou celle de l'espace partagé à défaut.
Cette règle est ce qui ouvre un dossier reçu en partage interne, qui vit dans un espace que l'appelant ne peut pas désigner lui-même. La réponse se referme alors sur ce que le propriétaire a ouvert :
pathcommence à la racine du partage, pas à celle de l'espace ;spacene porte queid,typeetname, sans occupation ni quota ;scope=spaceest ramené àsubtree: l'espace entier contient ce qui n'a pas été partagé. Le dossier demandé étant atteint par le partage, son sous-arbre l'est aussi, etlocationne nomme aucun dossier rangé au-dessus ;grantporterootId,canDownload,canAdd,canEditetcanDelete, pour que le client n'offre pas une action que le serveur refuserait.
Hors partage, grant vaut null et la réponse est complète.
GET /drive/nodes/:id suit la même règle. Par un partage interne, path commence à la racine du partage, et shares comme internalShares sortent vides : les jetons des liens publics et la liste des autres destinataires regardent le propriétaire.
Chaque nœud rendu porte deux booléens de partage, calculés par la requête de listage : has_link_share, vrai quand un lien public utilisable vise ce nœud, c'est à dire ni révoqué, ni expiré, ni arrivé à son plafond de téléchargements, et has_internal_share, vrai quand le nœud est ouvert à au moins un compte de l'application. Les deux ne comptent que les partages directs : un fichier dans un dossier diffusé les a tous les deux à faux. Ils évitent au navigateur une requête de partages par ligne affichée. Les routes publiques ne les exposent pas.
PATCH /drive/nodes/:id couvre le renommage et le déplacement : fournir name, parentId, ou les deux. Les deux gestes partagent une route parce qu'ils sont une seule intention côté utilisateur.
Un élément atteint par un partage interne ne se déplace que vers un dossier atteint lui aussi par un partage, avec le droit d'y ajouter. La racine d'un espace est refusée : le déplacement ferait sortir l'élément de ce que le destinataire peut voir.
POST /drive/folders accepte name, parentId et spaceId. Comme pour un dépôt, parentId décide de l'espace : créer un dossier dans un dossier reçu en partage demande le droit d'ajouter, et spaceId ne sert qu'à créer à la racine d'un espace.
Lecture
| Méthode | Chemin | Permission |
|---|---|---|
GET | /drive/nodes/:id/raw | drive.view |
GET | /drive/nodes/:id/thumbnail | drive.view |
GET | /drive/nodes/:id/download | drive.view |
POST | /drive/download-zip | drive.view |
Les deux voies streament le binaire à travers l'application, sans limite de taille, mais elles ne servent pas le même usage.
raw sert la consommation en ligne : aperçu, balise img, lecteur vidéo. Elle honore les plages d'octets, ce qui permet à une vidéo de démarrer sans être entièrement chargée et à la barre de défilement de fonctionner. Elle ne journalise rien : une vidéo lue jusqu'au bout émet des dizaines de requêtes.
download sert le bouton de téléchargement, en pièce jointe. Elle n'annonce pas les plages, et c'est elle qui écrit au journal et qui décompte le plafond d'un partage : un clic vaut une entrée. Voir Fichiers acceptés.
POST /drive/download-zip attend ids, cent au plus. Un identifiant que l'appelant n'atteint pas, ou qu'un partage interne lui ouvre sans le droit de télécharger, est écarté de l'archive sans faire échouer le reste. La route répond « introuvable » quand il ne reste rien.
Dépôt et versions
| Méthode | Chemin | Permission |
|---|---|---|
POST | /drive/upload | drive.upload |
POST | /drive/upload/session | drive.upload |
POST | /drive/upload/:id/part/:partNumber | drive.upload |
POST | /drive/upload/:id/complete | drive.upload |
GET | /drive/upload/:id | drive.upload |
DELETE | /drive/upload/:id | drive.upload |
GET | /drive/nodes/:id/versions | drive.view |
POST | /drive/nodes/:id/versions/:versionId | drive.upload |
/drive/upload attend un multipart/form-data avec file, et accepte spaceId, parentId et replace. Elle refuse un corps plus gros qu'une tranche.
Dans un dossier reçu en partage interne, déposer demande le droit d'ajouter. replace y demande en plus le droit de modifier, sur les deux voies de dépôt : remplacer un fichier du même nom change un contenu existant, ce n'est plus un ajout. Restaurer une version relève du même droit, pour la même raison. Lire l'historique des versions ne demande que d'atteindre le fichier.
Protocole de téléversement par tranches
Trois appels, pour tout fichier plus gros qu'une tranche.
1. Ouvrir la session. POST /drive/upload/session, corps JSON avec filename, size, et au choix spaceId, parentId, replace.
{ "uploadId": "…", "chunkSize": 8388608, "partCount": 25, "expiresIn": 3600, "receivedParts": [] }La taille de tranche vient du serveur et ne se négocie pas : le stockage exige que toutes les parts sauf la dernière fassent exactement la même taille.
2. Envoyer les tranches. POST /drive/upload/:id/part/:partNumber, corps binaire brut, numéros à partir de 1. Les tranches peuvent partir dans n'importe quel ordre et en parallèle. Renvoyer un numéro déjà envoyé le remplace, ce qui rend une reprise sûre.
{ "partNumber": 3, "received": 3, "total": 25 }Cette route porte son propre budget de rate limit : un envoi découpé dépense une requête par tranche, et le budget partagé de l'API n'y suffirait pas.
3. Assembler. POST /drive/upload/:id/complete. Une tranche manquante répond 409 avec la liste des numéros absents, pour que le client comble les trous au lieu de tout recommencer.
GET /drive/upload/:id rend receivedParts, et DELETE /drive/upload/:id renonce à la session en libérant immédiatement les tranches déjà stockées. Une session ne se poursuit que depuis le compte, ou le partage, qui l'a ouverte.
Corbeille
| Méthode | Chemin | Permission |
|---|---|---|
GET | /drive/trash | drive.trash |
POST | /drive/trash/empty | drive.trash |
POST | /drive/trash/:id/restore | drive.trash |
DELETE | /drive/trash/:id | drive.trash |
La corbeille appartient à l'espace. Restaurer et purger ne servent que les éléments d'un espace que l'appelant ouvre lui-même : un partage interne n'y donne pas accès, quels que soient ses droits, et la réponse est « introuvable ».
Partages
| Méthode | Chemin | Permission |
|---|---|---|
GET | /drive/shares | drive.share |
POST | /drive/shares | drive.share |
PATCH | /drive/shares/:id | drive.share |
DELETE | /drive/shares/:id | drive.share |
GET | /drive/nodes/:id/internal-shares | drive.share |
POST | /drive/nodes/:id/internal-shares | drive.share |
DELETE | /drive/internal-shares/:id | drive.share |
GET | /drive/share-recipients | drive.share |
GET | /drive/shared-with-me | drive.view |
GET /drive/shares rend les liens d'un élément quand nodeId est fourni. Sans lui, elle rend ceux des espaces que l'appelant ouvre lui-même, l'espace partagé et son espace personnel : les liens posés sur l'espace personnel des autres n'en sortent pas, jetons compris. includeRevoked=true ajoute les liens révoqués.
PATCH /drive/shares/:id, DELETE /drive/shares/:id et DELETE /drive/internal-shares/:id désignent un partage par son identifiant, qui ne dit rien de l'espace où vit l'élément. Elles vérifient donc que l'appelant atteint cet élément par son espace, et répondent « introuvable » sinon, comme pour un identifiant inconnu. Un élément en corbeille reste atteint : ses partages se révoquent encore.
PATCH /drive/shares/:id accepte label, expiresAt, maxDownloads, notifyCadence, notifyEmails, password et permissions. Trois précisions :
- le mode n'est pas modifiable : il faut révoquer et recréer ;
permissionsn'est prise en compte que sur un lien en modemanage, et ignorée sans erreur ailleurs ;passwordabsent laisse le mot de passe inchangé,passwordvide le retire. Dans les deux cas où il change, les sessions ouvertes sur le lien sont fermées.
POST /drive/nodes/:id/internal-shares met à jour les droits d'un partage existant au lieu d'échouer : une seule route sert donc à ouvrir un accès et à en changer le niveau.
GET /drive/share-recipients rend les comptes à qui l'appelant peut partager un élément : recipients, chacun avec id, name et email, et truncated, vrai quand la liste a été coupée à son plafond de 500 comptes. Ne sortent que les comptes qui peuvent ouvrir le drive, ceux qui détiennent admin.access et drive.view, l'appelant excepté. La route existe pour que partager ne demande pas users.view : cette permission ouvre l'administration des comptes, avec leurs rôles, et désigner un collègue n'en a pas besoin.
GET /drive/shared-with-me rend, pour chaque élément, les droits du partage (can_download, can_add, can_edit, can_delete), space_type et reachable_by_space. Ce dernier est vrai quand l'élément vit dans un espace que l'appelant ouvre lui-même, l'espace partagé le plus souvent : les routes le servent alors par cet espace, et les droits du partage ne retirent rien à ce que son rôle permet.
Droits d'un partage interne
Un élément atteint par un partage interne, et non par son espace, demande un droit du partage en plus de la permission de la route. Chaque route nomme le droit qu'elle exige au moment où elle charge l'élément : aucune ne sert un élément partagé sans l'avoir fait.
| Droit exigé | Routes |
|---|---|
| Atteindre l'élément | GET /drive/nodes avec parentId, GET /drive/nodes/:id, GET /drive/folder-tree avec rootId, GET /drive/nodes/:id/versions |
| Télécharger | raw, thumbnail, download, POST /drive/download-zip |
| Ajouter | POST /drive/upload, POST /drive/upload/session, POST /drive/folders, la destination d'un déplacement |
| Modifier | PATCH /drive/nodes/:id, POST /drive/nodes/:id/versions/:versionId, un dépôt avec replace |
| Supprimer | DELETE /drive/nodes/:id, POST /drive/nodes/bulk-delete |
| Aucun ne suffit | GET /drive/shares avec nodeId, POST /drive/shares, PATCH et DELETE /drive/shares/:id, GET et POST /drive/nodes/:id/internal-shares, DELETE /drive/internal-shares/:id, les deux routes de corbeille par élément |
Un droit manquant répond « interdit ». Les routes qui désignent un partage par son identifiant et celles de la corbeille répondent « introuvable » : elles ne confirment pas qu'un partage ou un élément supprimé existe. Les routes de lot ne s'arrêtent pas pour autant : download-zip écarte l'élément refusé, bulk-delete le range dans failed.
Historique
| Méthode | Chemin | Permission |
|---|---|---|
GET | /drive/activity | drive.activity |
Filtres : spaceId, action, actorType, actorUserId, shareId, nodeId, q, from, to, page, limit. La réponse porte aussi la liste des acteurs présents dans le journal, pour peupler les filtres sans second appel.
Routes publiques de partage
Sans session. Le jeton du lien est le seul justificatif, et chaque route refait la chaîne complète de vérifications : existence, révocation, expiration, plafond de téléchargements, session de mot de passe, droit demandé, appartenance de l'élément au sous-arbre partagé.
| Méthode | Chemin | Rôle |
|---|---|---|
GET | /drive/public/:token | Métadonnées du lien, ou demande de mot de passe. |
POST | /drive/public/:token/unlock | Vérifie le mot de passe et ouvre une session. |
GET | /drive/public/:token/nodes | Contenu. Répond vide en mode dépôt. |
GET | /drive/public/:token/nodes/:id/raw | Binaire. |
GET | /drive/public/:token/nodes/:id/thumbnail | Miniature. |
GET | /drive/public/:token/nodes/:id/download | Binaire en pièce jointe, journalisé et décompté. |
GET | /drive/public/:token/download-zip | Le dossier consulté en archive, journalisé et décompté. |
PATCH | /drive/public/:token/nodes/:id | Renommage, si le lien l'autorise. |
DELETE | /drive/public/:token/nodes/:id | Suppression, si le lien l'autorise. |
POST | /drive/public/:token/upload | Dépôt en une requête. |
POST | /drive/public/:token/upload/session | Ouverture d'une session par tranches. |
POST | /drive/public/:token/upload/:id/part/:partNumber | Une tranche. |
POST | /drive/public/:token/upload/:id/complete | Assemblage. |
GET | /drive/public/:token/upload/:id | Tranches déjà reçues. |
DELETE | /drive/public/:token/upload/:id | Abandon de la session. |
GET /drive/public/:token renvoie share, summary et config. share porte le plafond de téléchargements et ce qu'il en reste, null en l'absence de plafond. Il ne porte pas le nom du lien : ce nom est une note interne du propriétaire, décrite dans Partages, et la réponse verrouillée qui précède la saisie du mot de passe ne le porte pas davantage. summary porte le nombre d'éléments à la racine, ou la taille pour un lien sur un fichier, et vaut null en mode dépôt. config porte la taille d'une tranche d'envoi, la taille maximale d'un fichier et la couleur des icônes.
GET /drive/public/:token/nodes renvoie une projection des éléments, pas la ligne de la table : identifiant, nom, nature, taille, type, date de modification, numéro de version, et un booléen has_thumbnail. La clé de stockage, la clé de miniature, l'espace d'origine et le nom de l'auteur du dépôt n'en font pas partie. Ce dernier est une donnée personnelle d'un tiers, que rien ne justifiait de servir au détenteur d'un lien.
Cette route accepte parentId, sort, direction, page et limit, et renvoie sa pagination. Elle n'accepte ni q ni scope : un partage se parcourt, il ne se fouille pas, et relayer scope aurait rendu la portée du lien inopérante.
GET /drive/public/:token/download-zip sert en pièce jointe l'archive du dossier désigné par parentId, la racine du partage à défaut. Elle exige le droit de télécharger, refuse un lien qui ne porte qu'un fichier, et n'accepte aucune liste d'identifiants : la cible est un dossier du partage, et le visiteur n'a pas de sélection à composer. L'archive vaut un seul téléchargement sur le plafond du lien, pas un par fichier, et une seule entrée au journal. Elle est assemblée à la volée, entrée par entrée, dans les mêmes limites que celle de l'administration.
Aucune de ces routes n'est exemptée du contrôle CSRF : les dépôts partent de la page publique du même site, donc le contrôle d'origine du routeur les laisse passer sans exception.
Le protocole de dépôt est le même qu'en administration, aux deux différences près qu'impose un visiteur anonyme : replace n'est jamais accepté, donc un dépôt n'écrase jamais rien, et chaque route de session vérifie que la session vient bien de ce partage. Sans ce dernier contrôle, un identifiant deviné laisserait pousser des octets dans le dépôt d'un autre lien.
En mode dépôt, /nodes répond une collection vide et la lecture d'un élément est refusée, y compris pour un identifiant deviné.