Compare commits

...

21 Commits
test ... master

Author SHA1 Message Date
xdrm-brackets 7e68b19d82 Added api.core.Documentation (renamed 'des' to 'descriptin') 2017-12-13 13:02:06 +01:00
xdrm-brackets a2828fbd63 Added api.core.Documentation (human-readable parameter list) 2017-12-13 13:00:20 +01:00
xdrm-brackets 73925299a2 minmod: api.core.Documentation 2017-12-13 12:44:39 +01:00
xdrm-brackets 7f4662eaa6 Added api.core.Documentation (human-readable permission set) 2017-12-13 12:43:20 +01:00
xdrm-brackets 853d73a82b Added api.core.Documentation (uri_scheme) 2017-12-13 12:31:10 +01:00
xdrm-brackets ef63849ccc fix: api.core.Request (replaced 'rename' by 'ren' in configuration) 2017-12-12 22:31:10 +01:00
xdrm-brackets b1796535a3 upd: api.core.Request (shortened config keys) 2017-12-12 22:27:22 +01:00
xdrm-brackets ba6d721586 add: api.core.Documentation (doc builder only gives the configuration TODO: add formatted data) | upd: api.core.Request (can now give optional URI parameters with // (empty slashes)) 2017-12-12 19:01:28 +01:00
xdrm-brackets 1e9d6f3aa8 minfix: removed debug from api.core.Request + added Err 'use' clause in module.release 2017-12-11 18:46:14 +01:00
xdrm-brackets c3de2c3114 Default value test (release self by default) 2017-12-11 18:45:13 +01:00
xdrm-brackets be583ea9ea upd: api.core.Request (now checks for default param if not FILE nor NULL + added WrongDefaultParam (Err constant) + replaced 'name' by 'rename' for error handling) 2017-12-11 18:43:38 +01:00
xdrm-brackets 15e28c10ec upd: api.core.Request (added 'default' parameter spec + fixed root (/) uri parameters) 2017-12-11 18:30:29 +01:00
xdrm-brackets e39c9cebe6 minmod 2017-12-11 18:03:51 +01:00
xdrm-brackets c2f1c9e627 add: api.core.Config (Now config object is an apart singleton) | upd: api.core.Request (uses now the Config singleton) 2017-12-11 18:01:49 +01:00
xdrm-brackets c8c5ff24fb upd: api.core (Made configuration recursive for path) 2017-12-11 12:15:05 +01:00
xdrm-brackets ce05e32801 test prod@releaser@2 2017-12-11 11:37:57 +01:00
xdrm-brackets bd89c2aa25 upd: config.projects (renamed prod-releaser to 'self') 2017-12-10 23:40:43 +01:00
xdrm-brackets 617dc8c825 upd: api.module.release (make output when @step given consistent from when not given) 2017-12-10 23:37:52 +01:00
xdrm-brackets 8344ad73f2 upd: config.modules (made GET release @step parameter optional) 2017-12-10 23:36:11 +01:00
xdrm-brackets ba7b778b18 fixed api.module.release 2017-12-10 23:35:06 +01:00
xdrm-brackets e2474447ef self test@1 2017-12-10 23:34:25 +01:00
12 changed files with 669 additions and 208 deletions

138
build/api/core/Config.php Normal file
View File

@ -0,0 +1,138 @@
<?php
namespace api\core;
use \error\core\Error;
use \error\core\Err;
class Config{
/* (1) Attributes
---------------------------------------------------------*/
/* (1) Static */
private static $inst = null; // singleton instance
private static function config_path(){ return __ROOT__.'/config/modules.json'; }
public static $allowed_http_methods = [ "GET", "POST", "PUT", "DELETE" ];
/* (2) Instance */
private $raw;
public $index;
public $error;
/* (2) Private constructor
*
* @path<String> Configuration path
*
---------------------------------------------------------*/
private function __construct($path=null){
// Set default error
$this->error = new Error(Err::Success);
/* (1) Access file content
---------------------------------------------------------*/ {
/* (1) Vérification existence fichier config */
if( !file_exists($path) )
return $this->error->set(Err::UnreachableResource);
/* (2) Lecture fichier config */
$conf = @file_get_contents($path);
/* (3) Si erreur lecture */
if( $conf === false )
return $this->error->set(Err::UnreachableResource);
/* (4) Parsage json */
$this->raw = json_decode( $conf, true );
/* (5) Gestion de l'erreur de parsage */
if( $this->raw == null )
return $this->error->set(Err::ParsingFailed, 'json');
}
/* (2) Construction de l'index des chemins
---------------------------------------------------------*/ {
/* (1) Initialisation */
$this->index = [];
$ref = [ '/' => array_merge($this->raw) ];
/* (2) Tant qu'il reste des @ref à traiter */
while( count($ref) > 0 ){
/* (2.1) For each ref */
foreach($ref as $ref_path=>$ref_children){
/* (2.2) For each children */
foreach($ref_children as $path=>$method_or_subpath){
/* (2.2.1) If is an HTTP method -> add to index */
if( in_array($path, self::$allowed_http_methods) ){
/* (2.2.1.1) If no index for this path -> add it */
if( !isset($this->index[$ref_path]) )
$this->index[$ref_path] = [];
/* (2.2.1.2) Add the HTTP method definition */
$this->index[$ref_path][$path] = $method_or_subpath;
/* (2.2.2) If a sub path -> add it to next refs to process */
}else{
if( $ref_path == '/' )
$ref["$ref_path$path"] = $method_or_subpath;
else
$ref["$ref_path/$path"] = $method_or_subpath;
}
}
/* (2.3) In all cases -> remove current from ref */
unset($ref[$ref_path]);
}
}
}
}
/* (3) Static singleton 'get-or-create'
*
* @return inst<Config> Configuration singleton
*
---------------------------------------------------------*/
public static function get(){
/* (1) If @inst already exists -> return singleton */
if( self::$inst instanceof Config )
return self::$inst;
/* (2) If @inst not set -> create singleton and return it */
self::$inst = new self( self::config_path() );
return self::$inst;
}
}

View File

@ -0,0 +1,253 @@
<?php
namespace api\core;
use \error\core\Error;
use \error\core\Err;
use \api\core\Request;
use \api\core\Config;
class Documentation{
/* (1) Attributes
---------------------------------------------------------*/
/* (1) Static */
/* (2) Instance */
/* (2) Builds the documentation
*
---------------------------------------------------------*/
public static function generate(Request $rq=null){
/* (1) Get data from config
---------------------------------------------------------*/
/* (1) If no index for this path -> exit */
if( !isset(Config::get()->index[$rq->get('id')['path']]) )
return new Response(new Error(Err::WrongPathModule));
/* (2) Instance store: configuration for this path */
$cfg = Config::get()->index[$rq->get('id')['path']];
/* (2) For each method
---------------------------------------------------------*/
foreach($cfg as $method=>$spec){
/* (1) Build uri with args */
$cfg[$method]['uri_scheme'] = self::uri_scheme($rq->get('id')['path'], $spec);
/* (2) Rename 'des' to 'description' */
$cfg[$method]['description'] = $cfg[$method]['des'];
unset($cfg[$method]['des']);
/* (3) Build human-readable permission list */
$cfg[$method]['permissions'] = "accessible with:".self::permissions($spec);
unset($cfg[$method]['per']);
/* (4) Build ease parameter list */
$cfg[$method]['parameters'] = self::parameters($spec);
unset($cfg[$method]['par']);
}
$response = new Response();
// $response->append('uri', $built_uri);
$response->append('methods', $cfg);
return $response;
}
/* (3) Builds uri with GET parameter inside
*
* @uri<String> Base URI
* @spec<array> Specification
*
---------------------------------------------------------*/
private static function uri_scheme($uri=null, $spec=null){
/* (1) If no param return nothing */
if( !isset($spec['par']) || !is_array($spec['par']) || count($spec['par']) <= 0 )
return;
/* (2) If uri is only '/', reset to nothing */
if( $uri == '/' )
$uri = '';
/* (1) Manage GET parameters
---------------------------------------------------------*/
/* (1) Get highest 'URL' parameter available in the spec */
$highest = 0;
foreach($spec['par'] as $pname=>$pspec){
$is_url = strlen($pname) > 3 && substr($pname, 0, 3) == 'URL' && is_numeric(substr($pname, 3));
if( $is_url && intval(substr($pname, 3)) > $highest )
$highest = intval(substr($pname, 3));
}
/* (2) Add each GET parameter (even if not in spec) */
for( $i = 0 ; $i <= $highest ; $i++ ){
/* (2.1) If not in the spec -> set default to empty */
if( !isset($spec['par']["URL$i"]) ){
$uri .= '/';
continue;
}
$pspec = $spec['par']["URL$i"];
/* (2.2) If 'rename' set the rename content */
if( isset($pspec['ren']) && is_string($pspec['ren']) ){
$uri .= '/@'.$pspec['ren'];
continue;
}
/* (2.3) If no rename set the default name */
$uri .= "/@url$i";
}
return $uri;
}
/* (4) Builds a readable permission list
*
* @spec<array> Specification
*
---------------------------------------------------------*/
private static function permissions($spec=null){
/* (1) If no perm return nothing */
if( !isset($spec['per']) || !is_array($spec['per']) || count($spec['per']) <= 0 )
return 'anyone';
/* (1) Manage permission groups
---------------------------------------------------------*/
$perm = '';
$first_or = true;
foreach($spec['per'] as $or){
/* (1) Ignore non-array values */
if( !is_array($or) )
continue;
$perm .= !$first_or ? ') or' : '';
$first_or = false;
$first_and = true;
/* (2) Manage AND */
foreach($or as $and){
$perm .= $first_and ? ' (' : ' and ';
$perm .= "$and";
$first_and = false;
}
}
if( !$first_or )
$perm .= ')';
return $perm;
}
/* (5) Builds a readable parameter list
*
* @spec<array> Specification
*
---------------------------------------------------------*/
private static function parameters($spec=null){
/* (1) If no param return nothing */
if( !isset($spec['par']) || !is_array($spec['par']) || count($spec['par']) <= 0 )
return;
/* (2) Initialize parameter output */
$param = [
'GET' => [],
'POST' => []
];
$post_index = -1;
/* (1) Set 'URL' parameter available in the spec */
foreach($spec['par'] as $pname=>$pspec){
/* (1) Manage POST parameters
---------------------------------------------------------*/
if( strlen($pname) >= 3 && substr($pname, 0, 3) == 'URL' && is_numeric(substr($pname, 3)) ){
/* (1) Get the URL index (position) */
$index = intval(substr($pname,3));
/* (2) Manage 'rename' property */
$name = ( isset($pspec['ren']) && is_string($pspec['ren']) ) ? $pspec['ren'] : $pname;
/* (3) Set default values */
$param['GET'][$index] = [
'name' => $name,
'required' => !isset($pspec['opt']) || $pspec['opt'] !== true
];
/* (4) Manage 'default' property */
if( !$param['GET'][$index]['required'] )
$param['GET'][$index]['default'] = isset($pspec['def']) ? $pspec['def'] : null;
continue;
}
/* (2) Manage GET+POST parameters
---------------------------------------------------------*/
/* (1) Get the POST index */
$post_index = $post_index + 1;
/* (2) Manage 'rename' property */
$name = ( isset($pspec['ren']) && is_string($pspec['ren']) ) ? $pspec['ren'] : $pname;
/* (3) Set default values */
$param['POST'][$post_index] = [
'name' => $name,
'required' => !isset($pspec['opt']) || $pspec['opt'] !== true
];
/* (4) Manage 'default' property */
if( !$param['POST'][$post_index]['required'] )
$param['POST'][$post_index]['default'] = isset($pspec['def']) ? $pspec['def'] : null;
}
return $param;
}
}

View File

@ -27,18 +27,21 @@
/* (1) On gère les arguments */
$arguments = is_array($arguments) ? $arguments : [];
/* (2) On transforme @module en namespace */
/* (2) Exception: URI Racine */
if( $module == '/' )
$module = '/root';
/* (3) On transforme @module en namespace */
$module_ns = str_replace('/', '\\', $module);
/* (1) On vérifie que la classe existe */
if( !file_exists(__BUILD__."/api/module/$module.php") )
/* (4) On vérifie que la classe existe */
if( !file_exists(__BUILD__."/api/module$module.php") )
return false;
/* (2) On récupère la classe */
$class_name = "\\api\\module\\$module_ns";
/* (5) On récupère la classe */
$class_name = "\\api\\module$module_ns";
/* (3) On retourne une instance */
/* (6) On retourne une instance */
return new $class_name($arguments);
}

View File

@ -4,6 +4,7 @@
use \database\core\DatabaseDriver;
use \api\core\AuthSystem;
use \api\core\ModuleFactory;
use \api\core\Config;
use \error\core\Error;
use \error\core\Err;
@ -11,24 +12,17 @@
class Request{
// Constantes
public static function config_path(){ return __ROOT__.'/config/modules.json'; }
private static $default_options = [ 'download' => false ];
private static $authsystem = null;
// liste des methodes HTTP autorisées
private static $allowed_http_methods = [ "GET", "POST", "PUT", "DELETE" ];
// Attributs prives utiles (initialisation)
private $path; // chemin de base (uri)
private $id; // chemin extrait de l'URI
private $raw_params; // paramètres reçus
private $params; // paramètres donnés à la fonction
private $schema; // schema configuration
private $options; // options
private $http_method; // methode HTTP appelante
// Contiendra la reponse a la requete
public $answer;
// Contiendra l'etat de la requete
public $error;
@ -60,25 +54,21 @@
*
---------------------------------------------------------*/
private function buildRequestObject($uri=null, $params=null, $forced_method=null){
/* (1) Initialisation
---------------------------------------------------------*/
/* (1) Erreur par défaut */
$this->error = new Error(Err::Success);
/* (2) Si pas parametre manquant, on quitte */
if( $uri == null )
if( is_null($uri) )
return $this->error->set(Err::MissingPath);
/* (2) On met a jour la configuration
/* (2) On vérifie la configuration
---------------------------------------------------------*/
/* (1) Build from configuration */
$this->buildConfig();
/* (2) Dispatch if error */
if( $this->error->get() != Err::Success )
return;
/* (1) Dispatch if error */
if( Config::get()->error->get() != Err::Success )
return ($this->error = Config::get()->error);
/* (3) Verification des types des parametres
@ -87,45 +77,54 @@
if( !is_string($uri) ) // Si le type est incorrect
return $this->error->set(Err::WrongPathModule);
/* (2) Formattage @params en tableau */
/* (2) Add slash at the beginning of URI */
if( !preg_match('@^\/@', $uri) )
$uri = "/$uri";
/* (3) Formattage @params en tableau */
$this->raw_params = (is_array($params)) ? $params : [];
/* (3) On définit en constante la méthode HTTP */
/* (4) On définit en constante la méthode HTTP */
if( !isset($_SERVER['REQUEST_METHOD']) && !is_string($forced_method) )
return $this->error->set(Err::UnknownHttpMethod);
$this->http_method = is_string($forced_method) ? strtoupper($forced_method) : strtoupper($_SERVER['REQUEST_METHOD']);
/* (4) Verification du chemin (existence module+methode)
---------------------------------------------------------*/
if( !$this->checkURI($uri) ) // Verification de la coherence du chemin + attribution
return false; // checkURI() sets the error itself
/* (5) Verification des permissions
/* (5) Si requête de documentation -> on arrête la vérification
---------------------------------------------------------*/
if( $this->id['doc_request'] )
return true;
/* (6) Verification des permissions
---------------------------------------------------------*/
if( !$this->checkPermission() ) // Si on a pas les droits
return false; // checkPermission() sets the error itself
/* (6) Verification des parametres (si @type est defini)
/* (7) Verification des parametres (si @type est defini)
---------------------------------------------------------*/
if( !$this->checkParams() ) // Verification de tous les types
return false; // checkParams() sets the error itself
/* (7) Récupèration des options
/* (8) Récupèration des options
---------------------------------------------------------*/
$this->buildOptions();
/* (8) Construction de l'objet (add http method to params)
/* (9) Construction de l'objet
---------------------------------------------------------*/
$this->params['HTTP_METHOD'] = $this->http_method;
$this->error->set(Err::Success);
return true; // On retourne que tout s'est bien passe
}
@ -150,67 +149,9 @@
/* (3) Construction du schéma à partir de la configuration
/* (3) Verification du format et de la coherence du chemin specifie
*
---------------------------------------------------------*/
private function buildConfig(){
/* (1) Access file content
---------------------------------------------------------*/
/* (1) Vérification existence fichier config */
if( !file_exists(self::config_path()) )
return $this->error->set(Err::UnreachableResource);
/* (2) Lecture fichier config */
$conf = @file_get_contents(self::config_path());
/* (3) Si erreur lecture */
if( $conf === false )
return $this->error->set(Err::UnreachableResource);
/* (4) Parsage json */
$this->schema['raw'] = json_decode( $conf, true );
/* (5) Gestion de l'erreur de parsage */
if( $this->schema['raw'] == null )
return $this->error->set(Err::ParsingFailed, 'json');
/* (2) Construction des outils d'accès
---------------------------------------------------------*/
/* (1) Initialisation */
$this->schema['index'] = [];
/* (2) Pour chaque chemin */
foreach($this->schema['raw'] as $path=>$methods){
/* (2.1) Pour chaque méthode */
foreach($methods as $method=>$data){
/* (2.1.1) Suppression si pas dans les méthodes autorisées */
if( !in_array($method, self::$allowed_http_methods) ){
unset($this->schema[$path][$method]);
continue;
}
/* (2.1.2) Création de l'index pour le chemin si n'existe pas déja */
if( !isset($this->schema['index'][$path]) )
$this->schema['index'][$path] = [];
/* (2.1.3) Ajout de la méthode à l'index */
$this->schema['index'][$path][] = $method;
}
}
}
/* (4) Verification du format et de la coherence du chemin specifie
*
* @path<String> String correspondant au chemin de delegation ("module/methode")
* @URI<String> URI d'appel (commence par /)
*
* @return validity<Boolean> Retourne si oui ou non l'objet est correct
*
@ -220,9 +161,14 @@
/* (1) Verification format general
---------------------------------------------------------*/
/* (1) If wrong format -> exit */
if( !preg_match('@^[\w-]+(\/[\w-]+)*\/?$@', $uri, $matches) )
if( !preg_match('@^\/[^\/]*(\/[^\/]*)*\/?$@', $uri) )
return $this->error->set(Err::WrongPathModule);
/* (2) Add ending '/' if not there */
if( $uri[strlen($uri)-1] != '/' )
$uri = "$uri/";
/* (2) Verification de l'existence du chemin (conf)
---------------------------------------------------------*/
@ -230,12 +176,12 @@
$exists_size = 0;
$path = null;
foreach($this->schema['index'] as $key=>$void){
foreach(Config::get()->index as $key=>$void){
$match_size = strlen($key);
/* (1.1) Look for the longer match */
if( $match_size > $exists_size && substr($uri, 0, $match_size) == $key ){
$exists_size = $match_size;
/* (1.1) Look for the longer ( match | '/' ) */
if( $match_size > $exists_size && substr($uri, 0, $match_size+1) == "$key/" || $key == '/' ){
$exists_size = $key == '/' ? 0 : $match_size;
$path = $key;
}
@ -251,33 +197,43 @@
/* (1) Extract URI string after @path */
$uri_end = substr($uri, $exists_size);
/* (2) If invalid format, return error */
if( !preg_match('@^((?:\/[^\/]+)*)\/?$@', $uri_end, $uri_match) )
/* (2) Special case: add / if root uri arguments */
if( strlen($uri_end) > 0 && $uri_end[0] != '/' )
$uri_end = "/$uri_end";
/* (3) If invalid format, return error */
if( !preg_match('@^((?:\/[^\/]*)*)\/?$@', $uri_end, $uri_match) )
return $this->error->set(Err::InvalidURI);
/* (3) Add each URI parameter to the parameter store */
/* (4) Add each URI parameter to the parameter store */
$uri_args = array_slice( explode('/', $uri_match[1]), 1);
foreach($uri_args as $index=>$value)
$this->raw_params["URL$index"] = $value;
if( strlen($value) > 0 ) // do not store '//' empty values
$this->raw_params["URL$index"] = $value;
/* (4) Verification de l'existence de la methode (conf)
---------------------------------------------------------*/
/* (1) Check if HTTP method is in allowed methods */
if( !in_array($this->http_method, self::$allowed_http_methods) )
/* (1) If it is a documentation request */
$doc_req = $this->http_method == 'OPTIONS';
/* (2) Check if HTTP method is in allowed methods */
if( !in_array($this->http_method, Config::$allowed_http_methods) && !$doc_req )
return $this->error->set(Err::UnknownHttpMethod, $this->http_method);
/* (2) Check if HTTP method is defined for this @path */
if( !in_array($this->http_method, $this->schema['index'][$path]) )
/* (3) Check if HTTP method is defined for this @path */
if( !isset(Config::get()->index[$path][$this->http_method]) && !$doc_req )
return $this->error->set(Err::UnknownMethod, $this->http_method);
/* (5) Enregistrement du chemin et renvoi de SUCCESS
---------------------------------------------------------*/
$this->path = [
'path'=> $path,
'method'=> $this->http_method
$this->id = [
'path' => $path,
'method' => $this->http_method,
'doc_request' => $doc_req
];
return true;
@ -285,7 +241,7 @@
/* (5) Retourne si on a la permission d'executer cette methode
/* (4) Retourne si on a la permission d'executer cette methode
*
* @return permission<bool> Retourne si on a les droits ou pas pour executer cette methode
*
@ -295,10 +251,10 @@
/* (1) On recupere les informations utiles
---------------------------------------------------------*/
// On recupere le nom de la methode
$method = $this->schema['raw'][$this->path['path']][$this->path['method']];
$method = Config::get()->index[$this->id['path']][$this->id['method']];
// Si aucune permission n'est definie
if( !isset($method['permissions']) || !is_array($method['permissions']) || count($method['permissions']) < 1 )
if( !isset($method['per']) || !is_array($method['per']) || count($method['per']) < 1 )
return true;
/* (2) Vérification des permissions et de l'authentification
@ -316,7 +272,7 @@
}
// Check permission using user-implemented AuthSystem
$granted = self::$authsystem::permission( $method['permissions'] );
$granted = self::$authsystem::permission( $method['per'] );
/* (1) On retourne FAUX si aucun droit n'a ete trouve */
if( $granted->get() !== Err::Success ){
@ -332,7 +288,7 @@
/* (6) Verification du type des parametres envoyes
/* (5) Verification du type des parametres envoyes
*
* @return correct<bool> Retourne si oui ou non les parametres ont le bon type
*
@ -346,16 +302,16 @@
return $this->error->set(Err::MissingParam);
/* (2) On récupère les données de la méthode */
$method = $this->schema['raw'][$this->path['path']][$this->path['method']];
$method = Config::get()->index[$this->id['path']][$this->id['method']];
/* (3) Si pas 'parameters' dans la config */
if( !isset($method['parameters']) || !is_array($method['parameters']) )
if( !isset($method['par']) || !is_array($method['par']) )
return $this->error->set(Err::ConfigError);
/* (2) Si le type est defini, pour chaque param, on teste
---------------------------------------------------------*/
foreach($method['parameters'] as $name=>$config){
foreach($method['par'] as $name=>$config){
/* (2.1) Vérification des données
---------------------------------------------------------*/
@ -367,8 +323,8 @@
if( !is_array($config) )
return $this->error->set(Err::ConfigError);
/* (3) So @config['type] manquant ou incorrect */
if( !isset($config['type']) || !is_string($config['type']) )
/* (3) So @config['typ] manquant ou incorrect */
if( !isset($config['typ']) || !is_string($config['typ']) )
return $this->error->set(Err::ConfigError);
@ -376,19 +332,35 @@
---------------------------------------------------------*/
/* (1) On récupère le paramètre RENAME */
$rename = $name;
if( isset($config['rename']) && is_string($config['rename']) && preg_match('@^\w+$@', $config['rename']) )
$rename = $config['rename'];
if( isset($config['ren']) && is_string($config['ren']) && preg_match('@^\w+$@', $config['ren']) )
$rename = $config['ren'];
/* (1) On récupère si le paramètre est optionnel ou pas */
$optional = isset($config['optional']) && $config['optional'] === true;
/* (2) On récupère si le paramètre est optionnel ou pas */
$optional = isset($config['opt']) && $config['opt'] === true;
/* (2) Si de type 'FILE' + fichier existe => on enregistre la ref. */
if( $config['type'] == 'FILE' && isset($_FILES[$name]) )
/* (3) Gestion du paramètre DEFAULT */
$default = null;
/* (3.1) Check if default NOT (NULL || FILE) -> matches TYPE */
if( isset($config['def']) ){
/* (3.1.1) Set default value from config */
$default = $config['def'];
/* (3.1.2) If FILE and not null -> Check type */
if( $config['typ'] != 'FILE' || $default != null )
if( !Checker::run($config['typ'], $default) )
return $this->error->set(Err::WrongDefaultParam, $rename, $config['typ']);
}
/* (4) Si de type 'FILE' + fichier existe => on enregistre la ref. */
if( $config['typ'] == 'FILE' && isset($_FILES[$name]) )
$this->params[$rename] = &$_FILES[$name];
/* (3) Si param obligatoire et manquant -> erreur */
/* (4) Si param obligatoire et manquant -> erreur */
if( !isset($this->raw_params[$name]) && !$optional )
return $this->error->set(Err::MissingParam, $name);
return $this->error->set(Err::MissingParam, $rename);
/* (2.3) Gestion des valeurs
@ -396,15 +368,15 @@
/* (1) Si le paramètre est optionnel et manquant */
if( $optional && !isset($this->raw_params[$name]) ){
// On le crée le param optionnel avec la valeur NULL
$this->params[$rename] = null;
// On le crée le param optionnel avec la valeur @default
$this->params[$rename] = $default;
/* (2) Si le paramètre est renseigné (sauf FILE) */
}elseif( $config['type'] != 'FILE'){
}elseif( $config['typ'] != 'FILE' ){
// Si la verification est fausse, on retourne faux
if( !Checker::run($config['type'], $this->raw_params[$name]) )
return $this->error->set(Err::WrongParam, $name, $config['type']);
if( !Checker::run($config['typ'], $this->raw_params[$name]) )
return $this->error->set(Err::WrongParam, $rename, $config['typ']);
// Sinon, on ajoute aux params qu'on enverra à l'appel
else
@ -423,7 +395,7 @@
/* (7) Ajout des options a partir de la configuration
/* (6) Ajout des options a partir de la configuration
*
* @return correct<bool> Retourne FAUS en cas d'erreur
*
@ -432,17 +404,17 @@
/* (1) On récupère les options de la méthode en cours
---------------------------------------------------------*/
$method = $this->schema['raw'][$this->path['path']][$this->path['method']];
$method = Config::get()->index[$this->id['path']][$this->id['method']];
/* (1) Si 'option' n'est pas défini (ou incorrect), on met les valeurs par défaut */
if( !isset($method['options']) || !is_array($method['options']) )
if( !isset($method['opt']) || !is_array($method['opt']) )
return true;
/* (2) Par défaut on définit les options par défaut */
$this->options = self::$default_options;
/* (3) On récupère les options données */
$options = $method['options'];
$options = $method['opt'];
/* (2) Gestion des différentes options
@ -468,41 +440,45 @@
/* (8) Execute le traitement associe et remplie la reponse
/* (7) Execute le traitement associe et remplie la reponse
*
* @return answer<Response> Retourne une reponse de type <Response> si tout s'est bien passe
*
---------------------------------------------------------*/
public function dispatch(){
/* (1) On verifie qu'aucune erreur n'a ete signalee
/* (1) Vérifications de niveau 0
---------------------------------------------------------*/
if( $this->error->get() !== Err::Success ) // si il y a une erreur
return new Response($this->error); // on la passe a la reponse
/* (1) Si erreur -> on dispatch à la réponse */
if( $this->error->get() !== Err::Success )
return new Response($this->error);
/* (2) S'il requête de documentation -> on génère la documentation */
if( $this->id['doc_request'] )
return Documentation::generate($this);
/* (2) On essaie d'instancier le module
---------------------------------------------------------*/
$instance = ModuleFactory::getModule($this->path['path']);
$instance = ModuleFactory::getModule($this->id['path']);
if( $instance instanceof Error ){
$this->error->set(Err::UncallableModule, $this->path['path']);
$this->error->set(Err::UncallableModule, $this->id['path']);
return new Response($this->error);
}
/* (3) On verifie que la methode est amorcable
---------------------------------------------------------*/
if( !is_callable([$instance, $this->path['method']]) ){
$this->error->set(Err::UncallableMethod, $this->path['method']);
if( !is_callable([$instance, $this->id['method']]) ){
$this->error->set(Err::UncallableMethod, $this->id['method']);
return new Response($this->error);
}
/* (4) On amorce la methode
---------------------------------------------------------*/
/* (1) On lance la fonction */
$returned = call_user_func( [$instance, $this->path['method']], $this->params );
$returned = call_user_func( [$instance, $this->id['method']], $this->params );
/* (2) On appelle le destructeur (si défini) */
$instance = null;
@ -527,7 +503,7 @@
/* EXECUTE LE TRAITEMENT ASSOCIE ET RENVOIE UN FICHIER AVEC LE HEADER ET LE BODY SPECIFIE
/* (8) Gestion d'un téléchargement HTTP
*
*/
public function download(){
@ -615,6 +591,27 @@
}
/* (9) Getter générique
*
* @index<String> Index de l'attribut
*
---------------------------------------------------------*/
public function get($index=null){
switch($index){
case 'id': return $this->id; break;
case 'raw_params': return $this->raw_params; break;
case 'params': return $this->params; break;
case 'options': return $this->options; break;
case 'http_method': return $this->http_method; break;
}
return null;
}
}
?>

View File

@ -3,6 +3,7 @@
namespace api\module;
use \error\core\Error;
use \error\core\Err;
class release{
@ -13,7 +14,7 @@
* @step<id> [OPT] Step to run
*
*/
public function post($args){
public function get($args){
extract($args);
/* (1) Load projects' configuration
@ -61,7 +62,7 @@
exec($js[$project]['cmd'][$step], $stdout);
/* (2.3) Dispatch output */
return [ $js[$project]['cmd'][$step] => $stdout ];
return [ 'stdout' => [ $js[$project]['cmd'][$step] => $stdout ] ];
}

20
build/api/module/root.php Normal file
View File

@ -0,0 +1,20 @@
<?php
namespace api\module;
use \error\core\Error;
class root{
/* Generates the API documentation
*
*/
public function get($args){
extract($args);
return [ 'args' => $args ];
}
}

View File

@ -61,10 +61,12 @@
const MissingParam = 16;
/* (11) Paramètre incorrect */
const WrongParam = 17;
/* (12) Erreur dans le traitement */
const ModuleError = 18;
/* (13) URI Invalide */
const InvalidURI = 19;
/* (12) Valeur par défaut incorrecte */
const WrongDefaultParam = 18;
/* (13) Erreur dans le traitement */
const ModuleError = 19;
/* (14) URI Invalide */
const InvalidURI = 20;
/* [5] Database
@ -72,50 +74,50 @@
/* (1) Base de données
---------------------------------------------------------*/
/* (1) Erreur lors de la creation d'un objet PDO (connection) */
const PDOConnection = 20;
const PDOConnection = 21;
/* (2) Repositories
---------------------------------------------------------*/
/* (1) Verification de la coherence du chemin (existe dans la conf) */
const WrongPathRepo = 21;
const WrongPathRepo = 22;
/* (2) Module non specifie dans la conf */
const UnknownRepo = 22;
const UnknownRepo = 23;
/* (3) Erreur dans le traitement */
const RepoError = 23;
const RepoError = 24;
/* (3) ORM
---------------------------------------------------------*/
/* (1) Table n'existe pas */
const UnknownTable = 24;
const UnknownTable = 25;
/* (2) Pas permissions de lire le schéma */
const NotAllowedSchema = 25;
const NotAllowedSchema = 26;
/* [6] Erreurs diverses
=========================================================*/
/* (1) Aucune donnée trouvée */
const NoMatchFound = 26;
const NoMatchFound = 27;
/* (2) Mauvais chemin de template */
const UnknownTemplate = 27;
const UnknownTemplate = 28;
/* (3) géolocalisation échouée */
const UnknownAddress = 28;
const UnknownAddress = 29;
/* (4) Erreur inconnue */
const UnknownError = 29;
const UnknownError = 30;
/* (5) Entrée existante */
const AlreadyExists = 30;
const AlreadyExists = 31;
/* (6) Corps manquant */
const MissingBody = 31;
const MissingBody = 32;
/* (7) Header manquant */
const MissingHeaders = 32;
const MissingHeaders = 33;
}
?>

View File

@ -74,9 +74,10 @@
case Err::UncallableModule: return $this->UncallableModule(); break;
case Err::UncallableMethod: return $this->UncallableMethod(); break;
case Err::UnknownHttpMethod: return $this->UnknownHttpMethod(); break;
case Err::ConfigError: return $this->ConfigError(); break;
case Err::ConfigError: return $this->ConfigError(); break;
case Err::MissingParam: return $this->MissingParam(); break;
case Err::WrongParam: return $this->WrongParam(); break;
case Err::WrongDefaultParam: return $this->WrongDefaultParam(); break;
case Err::ModuleError: return $this->ModuleError(); break;
case Err::InvalidURI: return $this->InvalidURI(); break;
case Err::PDOConnection: return $this->PDOConnection(); break;
@ -161,6 +162,14 @@
return 'wrong param \''.$this->arguments[0].'\'';
else
return 'wrong param';
}private function WrongDefaultParam(){
if( count($this->arguments) > 0 )
if( count($this->arguments) > 1 )
return 'wrong default param \''.$this->arguments[0].'\' expected to be of type \''.$this->arguments[1].'\'';
else
return 'wrong default param \''.$this->arguments[0].'\'';
else
return 'wrong default param';
}private function ModuleError(){
if( count($this->arguments) > 0 )
return 'module error: \''.$this->arguments[0].'\'';

View File

@ -1,68 +1,106 @@
{
"GET": {
"des": "Returns the API documentation",
"per": [],
"par": {
"URL0": { "des": "Method name", "typ": "varchar(1,30)", "ren": "method_name", "opt": true, "def": null }
}
},
"admin": {
"POST": {
"description": "Creates a new administrator",
"permissions": [["admin"]],
"parameters": {
"username": { "description": "The new administrator username", "type": "varchar(3,20,alphanumeric)" },
"mail": { "description": "The new administrator email address", "type": "mail" },
"password": { "description": "The new administrator passowrd", "type": "text" }
"des": "Creates a new administrator",
"per": [["admin"]],
"par": {
"username": { "des": "The new administrator username", "typ": "varchar(3,20,alphanumeric)" },
"mail": { "des": "The new administrator email address", "typ": "mail" },
"password": { "des": "The new administrator passowrd", "typ": "text" }
}
},
"PUT": {
"description": "Updates an existing administrator's data",
"permissions": [["admin"]],
"parameters": {
"URL0": { "description": "The UID of the wanted administrator.", "type": "id", "rename": "id_admin" },
"mail": { "description": "The new administrator email address", "type": "mail", "optional": true },
"password": { "description": "The new administrator passowrd", "type": "text", "optional": true }
"des": "Updates an existing administrator's data",
"per": [["admin"]],
"par": {
"URL0": { "des": "The UID of the wanted administrator.", "typ": "id", "ren": "id_admin" },
"mail": { "des": "The new administrator email address", "typ": "mail", "opt": true },
"password": { "des": "The new administrator passowrd", "typ": "text", "opt": true }
}
},
"DELETE": {
"description": "Deletes an administrator",
"permissions": [["admin"]],
"parameters": {
"URL0": { "description": "The UID of the wanted administrator.", "type": "id", "optional": true, "rename": "id_admin" }
"des": "Deletes an administrator",
"per": [["admin"]],
"par": {
"URL0": { "des": "The UID of the wanted administrator.", "typ": "id", "opt": true, "ren": "id_admin" }
}
},
"GET": {
"description": "Gets an administrator | Gets all administrators if no id defined",
"permissions": [["admin"]],
"parameters": {
"URL0": { "description": "The UID of the wanted administrator.", "type": "id", "optional": true, "rename": "id_admin" }
"des": "Gets an administrator | Gets all administrators if no id defined",
"per": [["admin"]],
"par": {
"URL0": { "des": "The UID of the wanted administrator.", "typ": "id", "opt": true, "ren": "id_admin" }
}
}
},
"token/renew": {
"POST": {
"description": "Renewal of the cyclic hashing system.",
"permission": ["cyclic-hash"],
"parameters": {
"hash": { "description": "new hash to store.", "type": "hash" }
}
}
},
"release": {
"GET": {
"description": "Pulls project from git branch.",
"permissions": [["admin"]],
"parameters": {
"URL0": { "description": "Name of the project to release", "type": "alphanumeric", "rename": "project" },
"URL1": { "description": "Step to run, if not given, all steps will be run", "type": "id", "rename": "step" }
"des": "Pulls project from git branch.",
"per": [["admin"]],
"par": {
"URL0": { "des": "Name of the project to release", "typ": "alphanumeric", "ren": "project", "opt": true, "def": "self" },
"URL1": { "des": "Step to run, if not given, all steps will be run", "typ": "id", "ren": "step", "opt": true }
}
}
},
"a": {
"b": {
"c": {
"PUT": {
"des": "PUT A/B/C.",
"per": [],
"par": {}
},
"DELETE": {
"des": "DELETE A/B/C.",
"per": [],
"par": {}
}
},
"PUT": {
"des": "PUT A/B.",
"per": [],
"par": {}
},
"DELETE": {
"des": "DELETE A/B.",
"per": [],
"par": {}
}
},
"GET": {
"des": "GET A.",
"per": [],
"par": {}
},
"POST": {
"des": "POST A.",
"per": [],
"par": {}
}
}
}

View File

@ -1,6 +1,6 @@
{
"prod-releaser": {
"self": {
"dir": "/vhost/prod-releaser",
"cmd" : [
"git pull origin master"
@ -10,7 +10,7 @@
"dir": "/vhost/ndli1718",
"cmd" : [
"git pull origin master",
"npm run release"
"npm run build"
]
}

View File

@ -1,12 +1,12 @@
{
"methods": [ "GET", "POST", "PUT", "DELETE", "VIEW" ],
"methods": [ "GET", "POST", "PUT", "DELETE", "OPTIONS" ],
"routes": {
"/api/v/1.0/{uri}": {
"methods": ["GET", "POST", "PUT", "DELETE", "VIEW"],
"methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
"controller": "api:call",
"arguments": {
"uri": ".*"

View File

@ -16,5 +16,5 @@
Request::setAuthSystem(new AuthSystemDefault);
/* (4) launch router */
Router::launch($_GET['url']);
Router::launch($_SERVER['REQUEST_URI']);