1
0
mirror of https://github.com/devcode-it/openstamanager.git synced 2025-03-11 16:50:09 +01:00

Miglioramento della struttura delle classi

This commit is contained in:
Thomas Zilio 2017-09-04 16:04:45 +02:00
parent 90e7a23852
commit a688230c0d
6 changed files with 111 additions and 93 deletions

View File

@ -90,7 +90,7 @@ In particolare, ogni modulo può specificare una determinata serie di operazioni
Di seguito lo schema attraverso cui l'API individua la presenza delle possibili richieste supportate dai moduli (cartelle **api/** e **custom/api/**): Di seguito lo schema attraverso cui l'API individua la presenza delle possibili richieste supportate dai moduli (cartelle **api/** e **custom/api/**):
- `POST` - File `create.php`. - `POST` - File `create.php`.
- `GET` - File `eetrieve.php`. - `GET` - File `retrieve.php`.
- `PUT` - File `update.php`. - `PUT` - File `update.php`.
- `DELETE` - File `delete.php`. - `DELETE` - File `delete.php`.

View File

@ -43,9 +43,7 @@ class API extends \Util\Singleton
*/ */
public function __construct() public function __construct()
{ {
$user = Auth::user(); if (!self::isAPIRequest() || (!Auth::check() && self::getRequest()['resource'] != 'login')) {
if (!self::isAPIRequest() || (empty($user) && self::getRequest()['resource'] != 'login')) {
throw new InvalidArgumentException(); throw new InvalidArgumentException();
} }
} }
@ -62,81 +60,70 @@ class API extends \Util\Singleton
$user = Auth::user(); $user = Auth::user();
$table = ''; $table = '';
$select = '*'; $select = '*';
// Selezione personalizzata
$display = $request['display'];
$select = !empty($display) ? explode(',', substr($display, 1, -1)) : $select;
$where = []; $where = [];
$order = [];
// Selezione personalizzata
$select = !empty($request['display']) ? explode(',', substr($request['display'], 1, -1)) : $select;
// Ricerca personalizzata // Ricerca personalizzata
$filter = (array) $request['filter']; foreach ((array) $request['filter'] as $key => $value) {
foreach ($filter as $key => $value) { // Rimozione delle parentesi
$value = substr($value, 1, -1); $value = substr($value, 1, -1);
$result = [];
if (str_contains($value, ',')) { // Individuazione della tipologia (array o string)
$or = []; $where[$key] = str_contains($value, ',') ? explode(',', $value) : $value;
$temp = explode(',', $value);
foreach ($temp as $value) {
$or[] = [$key => $value];
}
$result[] = ['OR' => $or];
} else {
$result[$key] = $value;
}
$where[] = $result;
} }
$order = [];
// Ordinamento personalizzato // Ordinamento personalizzato
$order_request = (array) $request['order']; foreach ((array) $request['order'] as $value) {
foreach ($order_request as $value) {
$pieces = explode('|', $value); $pieces = explode('|', $value);
$order[] = empty($pieces[1]) ? $pieces[0] : [$pieces[0] => $pieces[1]]; $order[] = empty($pieces[1]) ? $pieces[0] : [$pieces[0] => $pieces[1]];
} }
// Date di interesse // Paginazione automatica dell'API
$updated = $request['upd'];
$created = $request['crd'];
// Paginazione dell'API
$page = (int) $request['page'] ?: 0; $page = (int) $request['page'] ?: 0;
$length = Settings::get('Lunghezza pagine per API'); $length = Settings::get('Lunghezza pagine per API');
$database = Database::getConnection(); $database = Database::getConnection();
$dbo = $database;
$kind = 'retrieve'; $kind = 'retrieve';
$resources = self::getResources()[$kind]; $resources = self::getResources()[$kind];
$resource = $request['resource']; $resource = $request['resource'];
if (!in_array($resource, array_keys($resources))) { if (in_array($resource, array_keys($resources))) {
$excluded = explode(',', Settings::get('Tabelle escluse per la sincronizzazione API automatica')); $dbo = $database;
if (!in_array($resource, $excluded)) {
$table = $resource;
if (empty($order)) { // Esecuzione delle operazioni personalizzate
$order[] = $dbo->fetchArray('SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '.prepare($table)." AND EXTRA LIKE '%AUTO_INCREMENT%' AND TABLE_SCHEMA = ".prepare($dbo->getDatabaseName()))[0]['COLUMN_NAME'];
}
}
} else {
$filename = DOCROOT.'/modules/'.$resources[$resource].'/api/'.$kind.'.php'; $filename = DOCROOT.'/modules/'.$resources[$resource].'/api/'.$kind.'.php';
include $filename; include $filename;
} elseif (!in_array($resource, explode(',', Settings::get('Tabelle escluse per la sincronizzazione API automatica')))) {
$table = $resource;
// Individuazione della colonna AUTO_INCREMENT per l'ordinamento automatico
if (empty($order)) {
$order[] = $database->fetchArray('SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '.prepare($table)." AND EXTRA LIKE '%AUTO_INCREMENT%' AND TABLE_SCHEMA = ".prepare($database->getDatabaseName()))[0]['COLUMN_NAME'];
}
} }
// Generazione automatica delle query // Generazione automatica delle query
if (empty($results) && !empty($table)) { if (empty($results) && !empty($table)) {
try { try {
// Date di interesse
if (!empty($request['upd'])) {
$where['#updated_at'] = 'updated_at >= '.prepare($request['upd']);
}
if (!empty($request['crd'])) {
$where['#created_at'] = 'created_at >= '.prepare($request['crd']);
}
// Query per ottenere le informazioni // Query per ottenere le informazioni
$results = $dbo->select($table, $select, $where, $order, [$page * $length, $length]); $results = $database->select($table, $select, $where, $order, [$page * $length, $length]);
// Informazioni aggiuntive // Informazioni aggiuntive
$query = $dbo->select($table, $select, $where, $order, [], true); $query = $database->select($table, $select, $where, $order, [], true);
$cont = $dbo->fetchArray('SELECT COUNT(*) as `records`, CEIL(COUNT(*) / '.$length.') as `pages` FROM ('.$query.') AS `count`'); $cont = $database->fetchArray('SELECT COUNT(*) as `records`, CEIL(COUNT(*) / '.$length.') as `pages` FROM ('.$query.') AS `count`');
if (!empty($cont)) { if (!empty($cont)) {
$results['records'] = $cont[0]['records']; $results['records'] = $cont[0]['records'];
$results['pages'] = $cont[0]['pages']; $results['pages'] = $cont[0]['pages'];
@ -207,12 +194,13 @@ class API extends \Util\Singleton
$database = Database::getConnection(); $database = Database::getConnection();
$dbo = $database; $dbo = $database;
$dbo->query('START TRANSACTION'); $database->query('START TRANSACTION');
// Esecuzione delle operazioni
$filename = DOCROOT.'/modules/'.$resources[$resource].'/api/'.$kind.'.php'; $filename = DOCROOT.'/modules/'.$resources[$resource].'/api/'.$kind.'.php';
include $filename; include $filename;
$dbo->query('COMMIT'); $database->query('COMMIT');
return self::response($results); return self::response($results);
} }
@ -249,29 +237,32 @@ class API extends \Util\Singleton
$resources = []; $resources = [];
$operations = glob(DOCROOT.'/modules/*/api/{retrieve,create,update,delete}.php', GLOB_BRACE); $operations = glob(DOCROOT.'/modules/*/api/{retrieve,create,update,delete}.php', GLOB_BRACE);
if (!empty($operations)) { foreach ($operations as $operation) {
foreach ($operations as $operation) { // Individua la tipologia e il modulo delle operazioni
$module = basename(dirname(dirname($operation))); $module = basename(dirname(dirname($operation)));
$kind = basename($operation, '.php'); $kind = basename($operation, '.php');
$resources[$kind] = (array) $resources[$kind]; $resources[$kind] = (array) $resources[$kind];
$temp = str_replace('/api/', '/custom/api/', $operation); // Controllo sulla presenza di eventuali personalizzazioni
$operation = file_exists($temp) ? $temp : $operation; $temp = str_replace('/api/', '/custom/api/', $operation);
$operation = file_exists($temp) ? $temp : $operation;
$api = include $operation; // Individuazione delle operazioni
$api = is_array($api) ? array_unique($api) : []; $api = include $operation;
$api = is_array($api) ? array_unique($api) : [];
$keys = array_keys($resources[$kind]); $keys = array_keys($resources[$kind]);
$results = []; // Registrazione delle operazioni individuate
foreach ($api as $value) { $results = [];
$value .= in_array($value, $keys) ? $module : ''; foreach ($api as $value) {
$results[$value] = $module; $value .= in_array($value, $keys) ? $module : '';
} $results[$value] = $module;
$resources[$kind] = array_merge($resources[$kind], $results);
} }
// Salvataggio delle operazioni
$resources[$kind] = array_merge($resources[$kind], $results);
} }
self::$resources = $resources; self::$resources = $resources;
@ -289,16 +280,19 @@ class API extends \Util\Singleton
*/ */
public static function response($array) public static function response($array)
{ {
// Controllo sulla compatibilità dell'API
if (!self::isCompatible()) { if (!self::isCompatible()) {
$array = [ $array = [
'status' => self::$status['incompatible']['code'], 'status' => self::$status['incompatible']['code'],
]; ];
} }
// Agiunta dello status di default
if (empty($array['status'])) { if (empty($array['status'])) {
$array['status'] = self::$status['ok']['code']; $array['status'] = self::$status['ok']['code'];
} }
// Aggiunta del messaggio in base allo status
if (empty($array['message'])) { if (empty($array['message'])) {
$codes = array_column(self::$status, 'code'); $codes = array_column(self::$status, 'code');
$messages = array_column(self::$status, 'message'); $messages = array_column(self::$status, 'message');
@ -307,6 +301,7 @@ class API extends \Util\Singleton
} }
$flags = JSON_FORCE_OBJECT; $flags = JSON_FORCE_OBJECT;
// Beautify forzato dei risultati
if (get('beautify') !== null) { if (get('beautify') !== null) {
$flags |= JSON_PRETTY_PRINT; $flags |= JSON_PRETTY_PRINT;
} }
@ -339,10 +334,15 @@ class API extends \Util\Singleton
*/ */
public static function getRequest() public static function getRequest()
{ {
$request = (array) json_decode(file_get_contents('php://input'), true); $request = [];
if ($_SERVER['REQUEST_METHOD'] == 'GET' && empty($request)) { if (self::isAPIRequest()) {
$request = Filter::getGET(); $request = (array) json_decode(file_get_contents('php://input'), true);
// Fallback nel caso la richiesta sia effettuata da browser
if ($_SERVER['REQUEST_METHOD'] == 'GET' && empty($request)) {
$request = Filter::getGET();
}
} }
return $request; return $request;

View File

@ -51,6 +51,7 @@ class Auth extends \Util\Singleton
$database = Database::getConnection(); $database = Database::getConnection();
if ($database->isInstalled()) { if ($database->isInstalled()) {
// Controllo dell'accesso da API
if (API::isAPIRequest()) { if (API::isAPIRequest()) {
$token = API::getRequest()['token']; $token = API::getRequest()['token'];
@ -81,6 +82,7 @@ class Auth extends \Util\Singleton
{ {
session_regenerate_id(); session_regenerate_id();
// Controllo sulla disponibilità dell'accesso (brute-forcing non in corso)
if (self::isBrute()) { if (self::isBrute()) {
return false; return false;
} }
@ -105,15 +107,18 @@ class Auth extends \Util\Singleton
$this->password_check($password, $user['password'], $user['id_utente']) && $this->password_check($password, $user['password'], $user['id_utente']) &&
!empty($module) !empty($module)
) { ) {
// Accesso completato
$log['id_utente'] = $this->infos['id_utente']; $log['id_utente'] = $this->infos['id_utente'];
$log['stato'] = self::$status['success']['code']; $log['stato'] = self::$status['success']['code'];
// Salvataggio nella sessione
$this->saveToSession(); $this->saveToSession();
} else { } else {
if (empty($module)) { if (empty($module)) {
$log['stato'] = self::$status['unauthorized']['code']; $log['stato'] = self::$status['unauthorized']['code'];
} }
// Logout automatico
$this->destory(); $this->destory();
} }
} else { } else {
@ -121,6 +126,7 @@ class Auth extends \Util\Singleton
} }
} }
// Salvataggio dello stato nella sessione
if ($log['stato'] != self::$status['success']['code']) { if ($log['stato'] != self::$status['success']['code']) {
foreach (self::$status as $key => $value) { foreach (self::$status as $key => $value) {
if ($log['stato'] == $value['code']) { if ($log['stato'] == $value['code']) {
@ -130,6 +136,7 @@ class Auth extends \Util\Singleton
} }
} }
// Salvataggio del tentativo nel database
$database->insert('zz_logs', $log); $database->insert('zz_logs', $log);
return $this->isAuthenticated(); return $this->isAuthenticated();

View File

@ -472,7 +472,7 @@ class Database extends Util\Singleton
{ {
if ( if (
!is_string($table) || !is_string($table) ||
(!empty($order) && !is_string($order) && !is_array($limit)) || (!empty($order) && !is_string($order) && !is_array($order)) ||
(!empty($limit) && !is_string($limit) && !is_array($limit)) (!empty($limit) && !is_string($limit) && !is_array($limit))
) { ) {
throw new UnexpectedValueException(); throw new UnexpectedValueException();
@ -541,7 +541,7 @@ class Database extends Util\Singleton
$sync = array_unique((array) current($list)); $sync = array_unique((array) current($list));
if (!empty($field)) { if (!empty($field)) {
$results = array_column($this->fetchArray('SELECT '.$this->quote($field).' FROM '.$this->quote($table).' WHERE '.$this->whereStatement($conditions)), $field); $results = array_column($this->select($table, $field, $conditions), $field);
$detachs = array_unique(array_diff($results, $sync)); $detachs = array_unique(array_diff($results, $sync));
$this->detach($table, $conditions, [$field => $detachs]); $this->detach($table, $conditions, [$field => $detachs]);
@ -573,7 +573,7 @@ class Database extends Util\Singleton
$sync = array_unique((array) current($list)); $sync = array_unique((array) current($list));
if (!empty($field)) { if (!empty($field)) {
$results = array_column($this->fetchArray('SELECT '.$this->quote($field).' FROM '.$this->quote($table).' WHERE '.$this->whereStatement($conditions)), $field); $results = array_column($this->select($table, $field, $conditions), $field);
$inserts = array_unique(array_diff($sync, $results)); $inserts = array_unique(array_diff($sync, $results));
foreach ($inserts as $insert) { foreach ($inserts as $insert) {
@ -605,14 +605,9 @@ class Database extends Util\Singleton
$sync = array_unique((array) current($list)); $sync = array_unique((array) current($list));
if (!empty($field) && !empty($sync)) { if (!empty($field) && !empty($sync)) {
$where = $this->whereStatement($conditions); $conditions[$field] = $sync;
$in = []; $this->query('DELETE FROM '.$this->quote($table).' WHERE '.$this->whereStatement($conditions));
foreach ($sync as $value) {
$in[] = $this->prepare($value);
}
$this->query('DELETE FROM '.$this->quote($table).' WHERE '.$where.(!empty($where) ? ' AND ' : '').$this->quote($field).' IN ('.implode(', ', $in).')');
} }
} }
@ -653,26 +648,40 @@ class Database extends Util\Singleton
{ {
$result = []; $result = [];
if (is_array($where)) { foreach ($where as $key => $value) {
foreach ($where as $key => $value) { // Query personalizzata
if (is_array($value)) { if (starts_with($key, '#')) {
$key = strtoupper($key); $result[] = $this->prepareValue($key, $value);
$key = (in_array($key, ['AND', 'OR'])) ? $key : 'AND'; } else {
// Ulteriori livelli di complessità
if (is_array($value) && in_array(strtoupper($key), ['AND', 'OR'])) {
$result[] = '('.$this->whereStatement($value, $key == 'AND').')'; $result[] = '('.$this->whereStatement($value, $key == 'AND').')';
} elseif (starts_with($value, '#') && ends_with($value, '#')) { }
$result[] = substr($value, 1, -1); // Condizione IN
} elseif (starts_with($value, '%') || ends_with($value, '%')) { elseif (is_array($value)) {
if (!empty($value)) {
$in = [];
foreach ($value as $v) {
$in[] = $this->prepareValue($key, $v);
}
$result[] = $this->quote($key).' IN ('.implode(',', $in).')';
}
}
// Condizione LIKE
elseif (str_contains($value, '%') || str_contains($value, '_')) {
$result[] = $this->quote($key).' LIKE '.$this->prepareValue($key, $value); $result[] = $this->quote($key).' LIKE '.$this->prepareValue($key, $value);
} elseif (str_contains($value, '|')) { }
// Condizione BETWEEN
elseif (str_contains($value, '|')) {
$pieces = explode('|', $value); $pieces = explode('|', $value);
$result[] = $this->quote($key).' BETWEEN '.$this->prepareValue($key, $pieces[0]).' AND '.$this->prepareValue($key, $pieces[1]); $result[] = $this->quote($key).' BETWEEN '.$this->prepareValue($key, $pieces[0]).' AND '.$this->prepareValue($key, $pieces[1]);
} else { }
// Condizione di uguaglianza
else {
$result[] = $this->quote($key).' = '.$this->prepareValue($key, $value); $result[] = $this->quote($key).' = '.$this->prepareValue($key, $value);
} }
} }
} else {
$result[] = $where;
} }
$cond = !empty($and) ? 'AND' : 'OR'; $cond = !empty($and) ? 'AND' : 'OR';

View File

@ -10,6 +10,7 @@ switch ($resource) {
$tokens = $database->fetchArray('SELECT `token` FROM `zz_tokens` WHERE `enabled` = 1 AND `id_utente` = '.prepare($user['id_utente'])); $tokens = $database->fetchArray('SELECT `token` FROM `zz_tokens` WHERE `enabled` = 1 AND `id_utente` = '.prepare($user['id_utente']));
if (empty($tokens)) { if (empty($tokens)) {
$token = secure_random_string(); $token = secure_random_string();
$database->insert('zz_tokens', [ $database->insert('zz_tokens', [
'id_utente' => $user['id_utente'], 'id_utente' => $user['id_utente'],
'token' => $token, 'token' => $token,
@ -38,6 +39,7 @@ switch ($resource) {
// Operazione di logout // Operazione di logout
case 'logout': case 'logout':
if (!empty($request['token']) && !empty($user)) { if (!empty($request['token']) && !empty($user)) {
// Cancellazione della chiave
$database->query('DELETE FROM `zz_tokens` WHERE `token` = '.prepare($request['token']).' AND `id_utente` = '.prepare($user['id_utente'])); $database->query('DELETE FROM `zz_tokens` WHERE `token` = '.prepare($request['token']).' AND `id_utente` = '.prepare($user['id_utente']));
} else { } else {
$results = [ $results = [

View File

@ -680,7 +680,7 @@ ALTER TABLE `zz_semaphores` ADD FOREIGN KEY (`id_utente`) REFERENCES `zz_users`(
CREATE TABLE IF NOT EXISTS `zz_tokens` ( CREATE TABLE IF NOT EXISTS `zz_tokens` (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int(11) NOT NULL AUTO_INCREMENT,
`id_utente` int(11) NOT NULL, `id_utente` int(11) NOT NULL,
`token` varchar(255) NOT NULL UNIQUE, `token` varchar(255) NOT NULL,
`descrizione` varchar(255), `descrizione` varchar(255),
`enabled` boolean NOT NULL DEFAULT 1, `enabled` boolean NOT NULL DEFAULT 1,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),