Compare commits

..

2 Commits
master ... v2

Author SHA1 Message Date
xdrm-brackets a4ba4fdc9a POST api.module.admin (added create) | upgraded autoloader.php 2017-12-10 22:42:09 +01:00
xdrm-brackets 5cdc2f9945 GET api.module.admin (added get by id + get all) 2017-12-10 22:33:23 +01:00
15 changed files with 266 additions and 846 deletions

View File

@ -1,138 +0,0 @@
<?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

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

View File

@ -4,7 +4,6 @@
use \database\core\DatabaseDriver;
use \api\core\AuthSystem;
use \api\core\ModuleFactory;
use \api\core\Config;
use \error\core\Error;
use \error\core\Err;
@ -12,17 +11,24 @@
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 $id; // chemin extrait de l'URI
private $path; // chemin de base (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;
@ -54,21 +60,25 @@
*
---------------------------------------------------------*/
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( is_null($uri) )
if( $uri == null )
return $this->error->set(Err::MissingPath);
/* (2) On vérifie la configuration
/* (2) On met a jour la configuration
---------------------------------------------------------*/
/* (1) Dispatch if error */
if( Config::get()->error->get() != Err::Success )
return ($this->error = Config::get()->error);
/* (1) Build from configuration */
$this->buildConfig();
/* (2) Dispatch if error */
if( $this->error->get() != Err::Success )
return;
/* (3) Verification des types des parametres
@ -77,54 +87,45 @@
if( !is_string($uri) ) // Si le type est incorrect
return $this->error->set(Err::WrongPathModule);
/* (2) Add slash at the beginning of URI */
if( !preg_match('@^\/@', $uri) )
$uri = "/$uri";
/* (3) Formattage @params en tableau */
/* (2) Formattage @params en tableau */
$this->raw_params = (is_array($params)) ? $params : [];
/* (4) On définit en constante la méthode HTTP */
/* (3) 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) Si requête de documentation -> on arrête la vérification
---------------------------------------------------------*/
if( $this->id['doc_request'] )
return true;
/* (6) Verification des permissions
/* (5) Verification des permissions
---------------------------------------------------------*/
if( !$this->checkPermission() ) // Si on a pas les droits
return false; // checkPermission() sets the error itself
/* (7) Verification des parametres (si @type est defini)
/* (6) Verification des parametres (si @type est defini)
---------------------------------------------------------*/
if( !$this->checkParams() ) // Verification de tous les types
return false; // checkParams() sets the error itself
/* (8) Récupèration des options
/* (7) Récupèration des options
---------------------------------------------------------*/
$this->buildOptions();
/* (9) Construction de l'objet
/* (8) Construction de l'objet (add http method to params)
---------------------------------------------------------*/
$this->params['HTTP_METHOD'] = $this->http_method;
$this->error->set(Err::Success);
return true; // On retourne que tout s'est bien passe
}
@ -149,9 +150,67 @@
/* (3) Verification du format et de la coherence du chemin specifie
/* (3) Construction du schéma à partir de la configuration
*
* @URI<String> URI d'appel (commence par /)
---------------------------------------------------------*/
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")
*
* @return validity<Boolean> Retourne si oui ou non l'objet est correct
*
@ -161,14 +220,9 @@
/* (1) Verification format general
---------------------------------------------------------*/
/* (1) If wrong format -> exit */
if( !preg_match('@^\/[^\/]*(\/[^\/]*)*\/?$@', $uri) )
if( !preg_match('@^\w+(\/\w+)*\/?$@', $uri, $matches) )
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)
---------------------------------------------------------*/
@ -176,12 +230,12 @@
$exists_size = 0;
$path = null;
foreach(Config::get()->index as $key=>$void){
foreach($this->schema['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+1) == "$key/" || $key == '/' ){
$exists_size = $key == '/' ? 0 : $match_size;
/* (1.1) Look for the longer match */
if( $match_size > $exists_size && substr($uri, 0, $match_size) == $key ){
$exists_size = $match_size;
$path = $key;
}
@ -197,43 +251,33 @@
/* (1) Extract URI string after @path */
$uri_end = substr($uri, $exists_size);
/* (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) )
/* (2) If invalid format, return error */
if( !preg_match('@^((?:\/[^\/]+)*)\/?$@', $uri_end, $uri_match) )
return $this->error->set(Err::InvalidURI);
/* (4) Add each URI parameter to the parameter store */
/* (3) Add each URI parameter to the parameter store */
$uri_args = array_slice( explode('/', $uri_match[1]), 1);
foreach($uri_args as $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) 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 )
/* (1) Check if HTTP method is in allowed methods */
if( !in_array($this->http_method, self::$allowed_http_methods) )
return $this->error->set(Err::UnknownHttpMethod, $this->http_method);
/* (3) Check if HTTP method is defined for this @path */
if( !isset(Config::get()->index[$path][$this->http_method]) && !$doc_req )
/* (2) Check if HTTP method is defined for this @path */
if( !in_array($this->http_method, $this->schema['index'][$path]) )
return $this->error->set(Err::UnknownMethod, $this->http_method);
/* (5) Enregistrement du chemin et renvoi de SUCCESS
---------------------------------------------------------*/
$this->id = [
'path' => $path,
'method' => $this->http_method,
'doc_request' => $doc_req
$this->path = [
'path'=> $path,
'method'=> $this->http_method
];
return true;
@ -241,7 +285,7 @@
/* (4) Retourne si on a la permission d'executer cette methode
/* (5) 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
*
@ -251,10 +295,10 @@
/* (1) On recupere les informations utiles
---------------------------------------------------------*/
// On recupere le nom de la methode
$method = Config::get()->index[$this->id['path']][$this->id['method']];
$method = $this->schema['raw'][$this->path['path']][$this->path['method']];
// Si aucune permission n'est definie
if( !isset($method['per']) || !is_array($method['per']) || count($method['per']) < 1 )
if( !isset($method['permissions']) || !is_array($method['permissions']) || count($method['permissions']) < 1 )
return true;
/* (2) Vérification des permissions et de l'authentification
@ -272,7 +316,7 @@
}
// Check permission using user-implemented AuthSystem
$granted = self::$authsystem::permission( $method['per'] );
$granted = self::$authsystem::permission( $method['permissions'] );
/* (1) On retourne FAUX si aucun droit n'a ete trouve */
if( $granted->get() !== Err::Success ){
@ -288,7 +332,7 @@
/* (5) Verification du type des parametres envoyes
/* (6) Verification du type des parametres envoyes
*
* @return correct<bool> Retourne si oui ou non les parametres ont le bon type
*
@ -302,16 +346,16 @@
return $this->error->set(Err::MissingParam);
/* (2) On récupère les données de la méthode */
$method = Config::get()->index[$this->id['path']][$this->id['method']];
$method = $this->schema['raw'][$this->path['path']][$this->path['method']];
/* (3) Si pas 'parameters' dans la config */
if( !isset($method['par']) || !is_array($method['par']) )
if( !isset($method['parameters']) || !is_array($method['parameters']) )
return $this->error->set(Err::ConfigError);
/* (2) Si le type est defini, pour chaque param, on teste
---------------------------------------------------------*/
foreach($method['par'] as $name=>$config){
foreach($method['parameters'] as $name=>$config){
/* (2.1) Vérification des données
---------------------------------------------------------*/
@ -323,8 +367,8 @@
if( !is_array($config) )
return $this->error->set(Err::ConfigError);
/* (3) So @config['typ] manquant ou incorrect */
if( !isset($config['typ']) || !is_string($config['typ']) )
/* (3) So @config['type] manquant ou incorrect */
if( !isset($config['type']) || !is_string($config['type']) )
return $this->error->set(Err::ConfigError);
@ -332,35 +376,19 @@
---------------------------------------------------------*/
/* (1) On récupère le paramètre RENAME */
$rename = $name;
if( isset($config['ren']) && is_string($config['ren']) && preg_match('@^\w+$@', $config['ren']) )
$rename = $config['ren'];
if( isset($config['rename']) && is_string($config['rename']) && preg_match('@^\w+$@', $config['rename']) )
$rename = $config['rename'];
/* (2) On récupère si le paramètre est optionnel ou pas */
$optional = isset($config['opt']) && $config['opt'] === true;
/* (1) On récupère si le paramètre est optionnel ou pas */
$optional = isset($config['optional']) && $config['optional'] === true;
/* (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]) )
/* (2) Si de type 'FILE' + fichier existe => on enregistre la ref. */
if( $config['type'] == 'FILE' && isset($_FILES[$name]) )
$this->params[$rename] = &$_FILES[$name];
/* (4) Si param obligatoire et manquant -> erreur */
/* (3) Si param obligatoire et manquant -> erreur */
if( !isset($this->raw_params[$name]) && !$optional )
return $this->error->set(Err::MissingParam, $rename);
return $this->error->set(Err::MissingParam, $name);
/* (2.3) Gestion des valeurs
@ -368,15 +396,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 @default
$this->params[$rename] = $default;
// On le crée le param optionnel avec la valeur NULL
$this->params[$rename] = null;
/* (2) Si le paramètre est renseigné (sauf FILE) */
}elseif( $config['typ'] != 'FILE' ){
}elseif( $config['type'] != 'FILE'){
// Si la verification est fausse, on retourne faux
if( !Checker::run($config['typ'], $this->raw_params[$name]) )
return $this->error->set(Err::WrongParam, $rename, $config['typ']);
if( !Checker::run($config['type'], $this->raw_params[$name]) )
return $this->error->set(Err::WrongParam, $name, $config['type']);
// Sinon, on ajoute aux params qu'on enverra à l'appel
else
@ -395,7 +423,7 @@
/* (6) Ajout des options a partir de la configuration
/* (7) Ajout des options a partir de la configuration
*
* @return correct<bool> Retourne FAUS en cas d'erreur
*
@ -404,17 +432,17 @@
/* (1) On récupère les options de la méthode en cours
---------------------------------------------------------*/
$method = Config::get()->index[$this->id['path']][$this->id['method']];
$method = $this->schema['raw'][$this->path['path']][$this->path['method']];
/* (1) Si 'option' n'est pas défini (ou incorrect), on met les valeurs par défaut */
if( !isset($method['opt']) || !is_array($method['opt']) )
if( !isset($method['options']) || !is_array($method['options']) )
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['opt'];
$options = $method['options'];
/* (2) Gestion des différentes options
@ -440,45 +468,41 @@
/* (7) Execute le traitement associe et remplie la reponse
/* (8) 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) Vérifications de niveau 0
/* (1) On verifie qu'aucune erreur n'a ete signalee
---------------------------------------------------------*/
/* (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);
if( $this->error->get() !== Err::Success ) // si il y a une erreur
return new Response($this->error); // on la passe a la reponse
/* (2) On essaie d'instancier le module
---------------------------------------------------------*/
$instance = ModuleFactory::getModule($this->id['path']);
$instance = ModuleFactory::getModule($this->path['path']);
if( $instance instanceof Error ){
$this->error->set(Err::UncallableModule, $this->id['path']);
$this->error->set(Err::UncallableModule, $this->path['path']);
return new Response($this->error);
}
/* (3) On verifie que la methode est amorcable
---------------------------------------------------------*/
if( !is_callable([$instance, $this->id['method']]) ){
$this->error->set(Err::UncallableMethod, $this->id['method']);
if( !is_callable([$instance, $this->path['method']]) ){
$this->error->set(Err::UncallableMethod, $this->path['method']);
return new Response($this->error);
}
/* (4) On amorce la methode
---------------------------------------------------------*/
/* (1) On lance la fonction */
$returned = call_user_func( [$instance, $this->id['method']], $this->params );
$returned = call_user_func( [$instance, $this->path['method']], $this->params );
/* (2) On appelle le destructeur (si défini) */
$instance = null;
@ -503,7 +527,7 @@
/* (8) Gestion d'un téléchargement HTTP
/* EXECUTE LE TRAITEMENT ASSOCIE ET RENVOIE UN FICHIER AVEC LE HEADER ET LE BODY SPECIFIE
*
*/
public function download(){
@ -591,27 +615,6 @@
}
/* (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

@ -50,7 +50,7 @@
* @mail<string> Adresse mail de l'administrateur
* @password<string> Mot de passe de l'administrateur
*
* @return admin<array> Données de l'administrateur crée
* @return id_admin<id> UID de l'administrateur crée
*
---------------------------------------------------------*/
public static function post($args){
@ -64,69 +64,7 @@
return [ 'error' => new Error(Err::RepoError) ];
/* (3) Renvoi @id_admin */
return [ 'id_admin' => Repo::request('admin', 'getById', $id_created) ];
}
/* (3) Updates an existing administrator
*
* @id_admin<id> UID de l'administrateur
* @mail<string> [OPT] Adresse mail de l'administrateur
* @password<string> [OPT] Mot de passe de l'administrateur
*
* @return admin<array> The new administrator data
*
---------------------------------------------------------*/
public static function put($args){
extract($args);
/* (1) If @mail given
---------------------------------------------------------*/
if( !is_null($mail) ){
/* (1) Update mail address */
$updated = Repo::request('admin', 'setMail', $id_admin, $mail);
/* (2) Gestion erreur */
if( $updated === false )
return [ 'error' => new Error(Err::RepoError) ];
}
/* (2) If @password given
---------------------------------------------------------*/
if( !is_null($password) ){
/* (1) Update password */
$updated = Repo::request('admin', 'setPassword', $id_admin, $password);
/* (2) Gestion erreur */
if( $updated === false )
return [ 'error' => new Error(Err::RepoError) ];
}
/* (3) Renvoi @id_admin */
return [ 'id_admin' => Repo::request('admin', 'getById', $id_admin) ];
}
/* (4) Deletes an existing administrator
*
* @id_admin<id> UID de l'administrateur
*
* @return removed<bool> Whether the admin has been removed
*
---------------------------------------------------------*/
public static function delete($args){
extract($args);
/* (1) Dispatch du status */
return [ 'removed' => Repo::request('admin', 'delete', $id_admin) ];
return [ 'id_admin' => $id_created ];
}

View File

@ -0,0 +1,32 @@
<?php
namespace api\module;
use \error\core\Error;
class authentification{
/* RENEW CYCLING HASH
*
* @hash<String> New hash
*
*/
public static function renew($args){
extract($args);
/* (1) Fetch cyclic-hashing-system -> check file */
$fn = __BUILD__.'/api/chs/hash';
if( !is_file($fn) )
return ['ModuleError'=>Error::UnreachableResource];
/* (2) Stores new hash */
file_put_contents($fn, $hash);
return [];
}
}

View File

@ -3,85 +3,62 @@
namespace api\module;
use \error\core\Error;
use \error\core\Err;
class release{
/* Releases a project
/* PULLS A BRANCH FROM GIT
*
* @project<String> Project's name
* @step<id> [OPT] Step to run
* @branch<String> Git branch
*
*/
public function get($args){
public static function pull($args){
extract($args);
/* (1) Load projects' configuration
---------------------------------------------------------*/
/* [1] Load projects' configuration
=========================================================*/
/* (1) Fetch file */
$fc = file_get_contents(__CONFIG__.'/projects.json');
if( !$fc )
return [ 'error' => new Error(Err::UnreachableResource) ];
return ['ModuleError'=>Error::UnreachableResource];
/* (2) Checks json format */
$js = json_decode( $fc, true );
if( !$js )
return [ 'error' => new Error(Err::ParsingFailed) ];
return ['ModuleError'=>Error::ParsingFailed];
/* (2) Checks @project argument and files
---------------------------------------------------------*/
/* [2] Checks @project argument and files
=========================================================*/
/* (1) Checks @project */
if( !isset($js[$project]) )
return [ 'error' => new Error(Err::UnreachableResource) ];
return ['ModuleError'=>Error::UnreachableResource];
/* (2) Checks @project's folder */
if( !is_dir($js[$project]['dir']) )
return [ 'error' => new Error(Err::UnreachableResource) ];
if( !is_dir($js[$project]['git']) )
return ['ModuleError'=>Error::UnreachableResource];
/* (3) Checks @git directory */
if( !is_dir($js[$project]['dir']) )
return [ 'error' => new Error(Err::UnreachableResource) ];
if( !is_dir($js[$project]['git'].'/.git') )
return ['ModuleError'=>Error::UnreachableResource];
/* (3) Launch script
---------------------------------------------------------*/
/* (1) 'cd' to project dir */
chdir($js[$project]['dir']);
/* [3] Launch script
=========================================================*/
/* (1) Launch command + test */
$cmd = 'cd '.$js[$project]['git'].'; git pull origin '.$branch.';';
$stdout = shell_exec($cmd);
/* (2) If given step, only do this one */
if( !is_null($step) ){
/* (2) If error, raise error */
if( is_null($stdout) )
return ['ModuleError'=>Error::PermissionError, 'command'=>$cmd];
/* (2.1) If step does not exist */
if( !isset($js[$project]['cmd'][$step]) )
return [ 'error' => new Error(Err::ModuleError, 'step out of bounds') ];
/* (2.2) Execute step */
exec($js[$project]['cmd'][$step], $stdout);
/* (2.3) Dispatch output */
return [ 'stdout' => [ $js[$project]['cmd'][$step] => $stdout ] ];
}
/* (3) Execute each step one by one */
$stdout = [];
foreach($js[$project]['cmd'] as $step=>$cmd){
/* (3.1) Pre-create stdout */
$stdout[$cmd] = '';
/* (3.2) Execute step */
exec($cmd, $stdout[$cmd]);
}
/* (4) Dispatch stdout */
return [ 'stdout' => $stdout ];
/* [4] Return success error
=========================================================*/
return [];
}
}

View File

@ -1,20 +0,0 @@
<?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

@ -181,40 +181,7 @@
}
/* (7) Set the mail address for a admin
*
* @id_admin<String> The admin UID
* @mail<String> The mail address to set
*
* @return set<bool> Whether the mail address has been set or not
*
---------------------------------------------------------*/
public function setMail(int $id_admin, String $mail){
/* (1) Check @mail is unique
---------------------------------------------------------*/
/* (1) If @mail already exists -> abort */
if( is_array($this->getByMail($mail)) )
return false;
/* (2) Update mail address
---------------------------------------------------------*/
/* (1) Prepare Statement */
$pst = $this->pdo->prepare("UPDATE `admin` SET `mail` = :mail WHERE `id_admin` = :id_admin");
/* (3) Bind variables */
$pst->bindParam(':mail', $mail, \PDO::PARAM_STR, 50);
$pst->bindParam(':id_admin', $id_admin, \PDO::PARAM_INT);
/* (4) Execute -> dispatch status */
return $pst->execute();
}
/* (8) Creates a new admin
/* (7) Creates a new admin
*
* @username<String> The username (must be unique)
* @mail<String> The mail address (must be unique)
@ -278,29 +245,6 @@
}
/* (9) Deletes an admin
*
* @id_admin<String> The admin UID
*
* @return removed<bool> Whether the admin has been removed or not
*
---------------------------------------------------------*/
public function delete(int $id_admin){
/* (1) Deletes the admin
---------------------------------------------------------*/
/* (1) Prepare Statement */
$pst = $this->pdo->prepare("DELETE FROM `admin` WHERE `id_admin` = :id_admin");
/* (3) Bind variables */
$pst->bindParam(':id_admin', $id_admin, \PDO::PARAM_INT);
/* (4) Execute -> dispatch status */
return $pst->execute();
}
}

View File

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

View File

@ -77,7 +77,6 @@
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;
@ -162,14 +161,6 @@
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,106 +1,63 @@
{
"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": {
"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" }
"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" }
}
},
"PUT": {
"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 }
"description": "Gets an administrator's data",
"permissions": [],
"parameters": {
"URL0": { "description": "Some string token", "type": "text", "rename": "id_article" },
"postdata": { "description": "Some string token", "type": "text" }
}
},
"DELETE": {
"des": "Deletes an administrator",
"per": [["admin"]],
"par": {
"URL0": { "des": "The UID of the wanted administrator.", "typ": "id", "opt": true, "ren": "id_admin" }
}
"description": "Deletes an administrator",
"permissions": [["admin"]],
"parameters": {}
},
"GET": {
"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" }
"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" }
}
}
},
"release": {
"GET": {
"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": {}
},
"token/renew": {
"POST": {
"des": "POST A.",
"per": [],
"par": {}
"description": "Renewal of the cyclic hashing system.",
"permission": ["cyclic-hash"],
"parameters": {
"hash": { "description": "new hash to store.", "type": "hash" }
}
}
},
"release/pull": {
"POST": {
"description": "Pulls project from git branch.",
"permissions": ["cyclic-hash"],
"parameters": {
"project": { "description": "Project's name.", "type": "varchar(2,30,alphanumeric)" },
"branch": { "description": "Git release branch.", "type": "varchar(2,30,alphanumeric)" }
}
}
}
}

View File

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

View File

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

View File

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