API pour Cumulus (brouillon)

Rédaction d'un début de spécifications pour le système de stockage de fichiers "Cumulus" :
  • API REST pour le webservice
  • API pour la couche de stockage

API REST pour le webservice

Par cas d'utilisation. Conventions :
  • la racine du service dans cet exemple est http://tb.org/cumulus.php
  • un fichier est désigné par une clef qui peut être un nom de fichier (ex: fichier.pdf) ou une chaîne arbitraire (ex: 84d97e6a67775858b9ebeb7e7d6598f9)
    • la clef pourra être générée à partir du nom de fichier (slug)
  • les attributs d'un fichier sont toutes les données associées autre que le contenu du fichier ou la clef
  • { a: ..., b : ... } désigne les paramètres de la requête (body) pour POST et PUT
  • le service devrait fonctionner en mode minimal sans aucun paramètre autre que le contenu des fichiers envoyés
    • la gestion des mots-clefs fait l'objet de la 1ère extension
    • la gestion des groupes fait l'objet de la 2ème extension
    • la gestion des droits / du propriétaire fait l'objet de la 3ème extension
  • un paramètre meta permet d'ajouter des métadonnées arbitraires en JSON
  • l'envoi de fichier utilisera le type de requête application/x-www-form-urlencoded (vérifier si ça marche avec PUT)
  • si un Header HTTP "Authorization" est présent et contient un jeton SSO valide, l'utilisateur sera désigné propriétaire du fichier (PUT / POST) ou ses droits seront comparés au propriétaire du fichier (GET) => voir comment rendre générique sans SSO

Points d'entrée


POST / PUT : ajouter / modifier un fichier

REST dit en gros ceci :
  • POST
    • POST est un ajout de ressource non ciblée à une ressource parente
    • on ne fournit pas le nom de ce qu'on POSTe
    • si on POSTe plusieurs fois le même fichier au même endroit, on obtient plusieurs fichiers stockés sous différents noms
  • PUT
    • PUT est un ajout de ressource ciblée, différents appels à PUT sont idempotents
    • on fournit le nom de ce qu'on PUTe
    • si on PUTe plusieurs fois le même fichier au même endroit, on met à jour le fichier

Oui mais : PHP ne prévoit rien pour traiter facilement le PUT (pas de $_PUT) et dans le cas d'un envoi avec Content-type: multipart/form-data , il ne charge pas la variable $_FILES. On va donc traiter les cas d'utilisation PUT avec POST. Quoiqu'il soit désagréable de modifier son architecture en fonction du langage, la chiantise est dans ce cas supérieure au bénéfice d'une part, et d'autre part une gestion de PUT pourra être ajoutée par la suite.
Seul inconvénient : si POST est utilisé pour ou devient (à l'avenir) un alias pour PUT, on se prive (encore qu'on pourrait se débrouiller) du cas où on POSTe un fichier sans le nommer, dans une ressource parente (plusieurs appels non idempotents); ce cas de figure ne correspond pas au stockage de documents, alors on peut raisonnablement considérer que "tant pis".

Trois moyens peuvent être employés pour envoyer un fichier :
  • multipart/form-data (envoi de formulaire)
  • contenu du fichier dans le paramètre file de la requête, encodé en  Base64
  • contenu du fichier dans le body de la requête, sans paramètres

Modification d'un fichier : Si le fichier existe déjà, son contenu sera écrasé.

Modification des métadonnées d'un fichier : Si des paramètres et une clef sont passés, mais aucun contenu de fichier, les métadonnées seront modifiées si la paire clef / chemin existe dans la base de données.

Avec un envoi de formulaire avec fichier - Content-type: multipart/form-data
POST http://tb.org/cumulus.php/chemin/arbitraire/nom
{
  • file : le fichier (input type="file")
  • keywords : les mots-clefs à associer (Array)
  • groups : les groupes auxquels associer le fichier (Array)
  • permissions : les permissions
  • license : la licence du fichier
  • meta : portion de JSON libre
}
Ajoute au stockage le fichier uploadé; lui donne une clef; lui donne comme répertoire parent /chemin/arbitraire et comme nom nom; les autres paramètres sont explicites.
Seront détectés : mimetype, original_name, user (si un jeton d'authentification est présent). creation_date et last_modification_date seront définis à la date courante.
Si file est une URL, le fichier sera un pointeur sur cette URL.
Renvoie les attributs.

Avec le contenu du fichier dans le paramètre "file" - Content-type: application/json
POST http://tb.org/cumulus.php/chemin/arbitraire/nom
{
  • file : le contenu du fichier envoyé, encodé en  Base64
  • keywords : les mots-clefs à associer (Array)
  • groups : les groupes auxquels associer le fichier (Array)
  • permissions : les permissions
  • license : la licence du fichier
  • meta : portion de JSON libre
}
Ajoute au stockage le fichier présent dans file; lui donne une clef; lui donne comme répertoire parent /chemin/arbitraire et comme nom nom; les autres paramètres sont explicites.
Seront détectés : mimetype, original_name, user (si un jeton d'authentification est présent). creation_date et last_modification_date seront définis à la date courante.
Si file est une URL, le fichier sera un pointeur sur cette URL.
Renvoie les attributs.

Avec un envoi en flux - contenu du fichier dans le body de la requête - Content-type : application/octet-stream ou application/x-www-form-urlencoded
POST http://tb.org/cumulus.php/chemin/arbitraire/nom
{
}
Ajoute au stockage le fichier contenu dans le corps de la requête; lui donne une clef; lui donne comme répertoire parent /chemin/arbitraire et comme nom nom.
Renvoie les attributs.

GET : obtenir un ou des fichiers

GET http://tb.org/cumulus.php/clef
GET http://tb.org/cumulus.php/chemin/arbitraire/nom
Récupère le fichier identifié par clef, ou nommé nom et contenu dans le répertoire /chemin/arbitraire (déclenche son téléchargement)
GET http://tb.org/cumulus.php/chemin/arbitraire/dossier
Récupère le contenu du dossier identifié par le chemin, càd ses sous-dossiers et ses fichiers
GET http://tb.org/cumulus.php/chemin/arbitraire/get-folders
Retourne la liste des sous-dossiers du chemin en cours

GET http://tb.org/cumulus.php/api/by-name/compte rendu
GET http://tb.org/cumulus.php/api/by-name/compte rendu?LIKE (par défaut)
GET http://tb.org/cumulus.php/api/by-name/compte rendu?STRICT
Renvoie une liste de fichiers (les clefs et les attributs) correspondant au nom ou à la / aux portion(s) de nom fournie(s), quels que soient leurs emplacements

GET http://tb.org/cumulus.php/api/by-path/mon/super/chemin
Renvoie une liste de fichiers (les clefs et les attributs) présents dans un dossier dont le chemin est /mon/super/chemin
GET http://tb.org/cumulus.php/api/by-path/mon/super/chemin?R
Renvoie une liste de fichiers (les clefs et les attributs) présents dans un dossier dont le chemin est /mon/super/chemin ou un sous-dossier de celui-ci

GET http://tb.org/cumulus.php/api/by-keywords/foo
GET http://tb.org/cumulus.php/api/by-keywords/foo,bar,couscous
GET http://tb.org/cumulus.php/api/by-keywords/foo,bar,couscous?AND (par défaut)
GET http://tb.org/cumulus.php/api/by-keywords/foo,bar,couscous?OR
Renvoie une liste de fichiers (les clefs et les attributs) correspondant à un ou plusieurs mots-clefs

GET http://tb.org/cumulus.php/api/search/foo,bar
Recherche floue parmi les noms et les mots-clefs
GET http://tb.org/cumulus.php/api/search?keywords=foo,bar&user=jean-bernard@tela-botanica.org&date=...
Recherche avancée

GET http://tb.org/cumulus.php/api/by-user/jean-bernard@tela-botanica.org
Renvoie une liste de fichiers (les clefs et les attributs) appartenant à l'utilisateur jean-bernard@tela-botanica.org

GET http://tb.org/cumulus.php/api/by-group/botanique-à-bort-les-orgues
Renvoie une liste de fichiers (les clefs et les attributs) appartenant au groupe "botanique-à-bort-les-orgues"

GET http://tb.org/cumulus.php/api/by-mimetype/image/png
Renvoie une liste de fichiers (les clefs et les attributs) ayant un type MIME "image/png"

GET http://tb.org/cumulus.php/api/by-date/2015-02-04
Renvoie une liste de fichiers (les clefs et les attributs) datant exactement du 04/02/2015
GET http://tb.org/cumulus.php/api/by-date/2015-02-04?BEFORE
Renvoie une liste de fichiers (les clefs et les attributs) datant d'avant le 04/02/2015 (exclu)
GET http://tb.org/cumulus.php/api/by-date/2015-02-04?AFTER
Renvoie une liste de fichiers (les clefs et les attributs) datant d'après 04/02/2015 (exclu)
GET http://tb.org/cumulus.php/api/by-date/2014-07-13/2015-02-04
Renvoie une liste de fichiers (les clefs et les attributs) datant d'entre le 13/07/2014 et le 04/02/2015

Rajouter /dl à la fin de toute URL GET : si l'URL retourne un seul fichier, le téléchargement de celui-ci sera déclenché.
Note : ne fonctionne pas forcément en combinaison avec des paramètres GET, à tester.

OPTIONS : obtenir les attributs d'un fichier

OPTIONS http://tb.org/cumulus.php/chemin/arbitraire/clef
Récupère les attributs du fichier clef contenu dans le répertoire /chemin/arbitraire, mais pas le contenu du fichier

DELETE : supprimer un fichier

DELETE http://tb.org/cumulus.php/chemin/arbitraire/clef
Supprime le fichier clef contenu dans le répertoire /chemin/arbitraire

Format de sortie

Format des attributs de fichiers :
{
  • fkey : clef
  • original_name : nom du fichier
  • path : chemin du fichier (dossier parent)
  • mimetype : type MIME du fichier
  • size : taille du fichier en octets
  • owner : propriétaire du fichier
  • groups : groupes (Array)
  • permissions : permissions du fichier
  • keywords : mots-clefs associés (Array)
  • license : licence du fichier
  • meta : portion de JSON libre
  • creation_date : date de création
  • last_modification_date : date de dernière modification
  • href : lien de téléchargement du fichier
}

Permissions

Les permissions sont gérées par les trois champs owner, permissions, groups.
Si owner est NULL ou vide, ou si permissions est NULL ou vide, le fichier est public (lecture et écriture pour tous).
Si l'utilisateur est propriétaire du fichier, il a tous les droits.
Sinon, les permissions sont inspirées d'UNIX et tiennent sur deux caractères. Le premier concerne les groupes, et le second les "autres". Le caractère peut être "r" (lecture), "w" (lecture et écriture - inclut la suppression), ou "-" (aucun droit).
Exemples:
  • "r-" : lecture pour les membres d'un des groupes, aucun droit pour les autres
  • "wr" : lecture et écriture pour les membres d'un des groupes, lecture pour les autres
  • "ww" : lecture et écriture pour tous (équivalent à NULL ou vide)
  • "--" : seul le propriétaire a les droits