mirror of
https://github.com/devcode-it/openstamanager.git
synced 2024-12-22 13:26:38 +01:00
Miglioramento della struttura delle classi
This commit is contained in:
parent
90e7a23852
commit
a688230c0d
@ -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/**):
|
||||
|
||||
- `POST` - File `create.php`.
|
||||
- `GET` - File `eetrieve.php`.
|
||||
- `GET` - File `retrieve.php`.
|
||||
- `PUT` - File `update.php`.
|
||||
- `DELETE` - File `delete.php`.
|
||||
|
||||
|
@ -43,9 +43,7 @@ class API extends \Util\Singleton
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
if (!self::isAPIRequest() || (empty($user) && self::getRequest()['resource'] != 'login')) {
|
||||
if (!self::isAPIRequest() || (!Auth::check() && self::getRequest()['resource'] != 'login')) {
|
||||
throw new InvalidArgumentException();
|
||||
}
|
||||
}
|
||||
@ -62,81 +60,70 @@ class API extends \Util\Singleton
|
||||
$user = Auth::user();
|
||||
|
||||
$table = '';
|
||||
|
||||
$select = '*';
|
||||
// Selezione personalizzata
|
||||
$display = $request['display'];
|
||||
$select = !empty($display) ? explode(',', substr($display, 1, -1)) : $select;
|
||||
|
||||
$where = [];
|
||||
$order = [];
|
||||
|
||||
// Selezione personalizzata
|
||||
$select = !empty($request['display']) ? explode(',', substr($request['display'], 1, -1)) : $select;
|
||||
|
||||
// Ricerca personalizzata
|
||||
$filter = (array) $request['filter'];
|
||||
foreach ($filter as $key => $value) {
|
||||
foreach ((array) $request['filter'] as $key => $value) {
|
||||
// Rimozione delle parentesi
|
||||
$value = substr($value, 1, -1);
|
||||
$result = [];
|
||||
|
||||
if (str_contains($value, ',')) {
|
||||
$or = [];
|
||||
|
||||
$temp = explode(',', $value);
|
||||
foreach ($temp as $value) {
|
||||
$or[] = [$key => $value];
|
||||
}
|
||||
|
||||
$result[] = ['OR' => $or];
|
||||
} else {
|
||||
$result[$key] = $value;
|
||||
}
|
||||
|
||||
$where[] = $result;
|
||||
// Individuazione della tipologia (array o string)
|
||||
$where[$key] = str_contains($value, ',') ? explode(',', $value) : $value;
|
||||
}
|
||||
|
||||
$order = [];
|
||||
// Ordinamento personalizzato
|
||||
$order_request = (array) $request['order'];
|
||||
foreach ($order_request as $value) {
|
||||
foreach ((array) $request['order'] as $value) {
|
||||
$pieces = explode('|', $value);
|
||||
$order[] = empty($pieces[1]) ? $pieces[0] : [$pieces[0] => $pieces[1]];
|
||||
}
|
||||
|
||||
// Date di interesse
|
||||
$updated = $request['upd'];
|
||||
$created = $request['crd'];
|
||||
|
||||
// Paginazione dell'API
|
||||
// Paginazione automatica dell'API
|
||||
$page = (int) $request['page'] ?: 0;
|
||||
$length = Settings::get('Lunghezza pagine per API');
|
||||
|
||||
$database = Database::getConnection();
|
||||
$dbo = $database;
|
||||
|
||||
$kind = 'retrieve';
|
||||
$resources = self::getResources()[$kind];
|
||||
$resource = $request['resource'];
|
||||
|
||||
if (!in_array($resource, array_keys($resources))) {
|
||||
$excluded = explode(',', Settings::get('Tabelle escluse per la sincronizzazione API automatica'));
|
||||
if (!in_array($resource, $excluded)) {
|
||||
$table = $resource;
|
||||
if (in_array($resource, array_keys($resources))) {
|
||||
$dbo = $database;
|
||||
|
||||
if (empty($order)) {
|
||||
$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 {
|
||||
// Esecuzione delle operazioni personalizzate
|
||||
$filename = DOCROOT.'/modules/'.$resources[$resource].'/api/'.$kind.'.php';
|
||||
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
|
||||
if (empty($results) && !empty($table)) {
|
||||
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
|
||||
$results = $dbo->select($table, $select, $where, $order, [$page * $length, $length]);
|
||||
$results = $database->select($table, $select, $where, $order, [$page * $length, $length]);
|
||||
|
||||
// Informazioni aggiuntive
|
||||
$query = $dbo->select($table, $select, $where, $order, [], true);
|
||||
$cont = $dbo->fetchArray('SELECT COUNT(*) as `records`, CEIL(COUNT(*) / '.$length.') as `pages` FROM ('.$query.') AS `count`');
|
||||
$query = $database->select($table, $select, $where, $order, [], true);
|
||||
$cont = $database->fetchArray('SELECT COUNT(*) as `records`, CEIL(COUNT(*) / '.$length.') as `pages` FROM ('.$query.') AS `count`');
|
||||
if (!empty($cont)) {
|
||||
$results['records'] = $cont[0]['records'];
|
||||
$results['pages'] = $cont[0]['pages'];
|
||||
@ -207,12 +194,13 @@ class API extends \Util\Singleton
|
||||
$database = Database::getConnection();
|
||||
$dbo = $database;
|
||||
|
||||
$dbo->query('START TRANSACTION');
|
||||
$database->query('START TRANSACTION');
|
||||
|
||||
// Esecuzione delle operazioni
|
||||
$filename = DOCROOT.'/modules/'.$resources[$resource].'/api/'.$kind.'.php';
|
||||
include $filename;
|
||||
|
||||
$dbo->query('COMMIT');
|
||||
$database->query('COMMIT');
|
||||
|
||||
return self::response($results);
|
||||
}
|
||||
@ -249,29 +237,32 @@ class API extends \Util\Singleton
|
||||
$resources = [];
|
||||
|
||||
$operations = glob(DOCROOT.'/modules/*/api/{retrieve,create,update,delete}.php', GLOB_BRACE);
|
||||
if (!empty($operations)) {
|
||||
foreach ($operations as $operation) {
|
||||
$module = basename(dirname(dirname($operation)));
|
||||
$kind = basename($operation, '.php');
|
||||
foreach ($operations as $operation) {
|
||||
// Individua la tipologia e il modulo delle operazioni
|
||||
$module = basename(dirname(dirname($operation)));
|
||||
$kind = basename($operation, '.php');
|
||||
|
||||
$resources[$kind] = (array) $resources[$kind];
|
||||
$resources[$kind] = (array) $resources[$kind];
|
||||
|
||||
$temp = str_replace('/api/', '/custom/api/', $operation);
|
||||
$operation = file_exists($temp) ? $temp : $operation;
|
||||
// Controllo sulla presenza di eventuali personalizzazioni
|
||||
$temp = str_replace('/api/', '/custom/api/', $operation);
|
||||
$operation = file_exists($temp) ? $temp : $operation;
|
||||
|
||||
$api = include $operation;
|
||||
$api = is_array($api) ? array_unique($api) : [];
|
||||
// Individuazione delle operazioni
|
||||
$api = include $operation;
|
||||
$api = is_array($api) ? array_unique($api) : [];
|
||||
|
||||
$keys = array_keys($resources[$kind]);
|
||||
$keys = array_keys($resources[$kind]);
|
||||
|
||||
$results = [];
|
||||
foreach ($api as $value) {
|
||||
$value .= in_array($value, $keys) ? $module : '';
|
||||
$results[$value] = $module;
|
||||
}
|
||||
|
||||
$resources[$kind] = array_merge($resources[$kind], $results);
|
||||
// Registrazione delle operazioni individuate
|
||||
$results = [];
|
||||
foreach ($api as $value) {
|
||||
$value .= in_array($value, $keys) ? $module : '';
|
||||
$results[$value] = $module;
|
||||
}
|
||||
|
||||
// Salvataggio delle operazioni
|
||||
$resources[$kind] = array_merge($resources[$kind], $results);
|
||||
}
|
||||
|
||||
self::$resources = $resources;
|
||||
@ -289,16 +280,19 @@ class API extends \Util\Singleton
|
||||
*/
|
||||
public static function response($array)
|
||||
{
|
||||
// Controllo sulla compatibilità dell'API
|
||||
if (!self::isCompatible()) {
|
||||
$array = [
|
||||
'status' => self::$status['incompatible']['code'],
|
||||
];
|
||||
}
|
||||
|
||||
// Agiunta dello status di default
|
||||
if (empty($array['status'])) {
|
||||
$array['status'] = self::$status['ok']['code'];
|
||||
}
|
||||
|
||||
// Aggiunta del messaggio in base allo status
|
||||
if (empty($array['message'])) {
|
||||
$codes = array_column(self::$status, 'code');
|
||||
$messages = array_column(self::$status, 'message');
|
||||
@ -307,6 +301,7 @@ class API extends \Util\Singleton
|
||||
}
|
||||
|
||||
$flags = JSON_FORCE_OBJECT;
|
||||
// Beautify forzato dei risultati
|
||||
if (get('beautify') !== null) {
|
||||
$flags |= JSON_PRETTY_PRINT;
|
||||
}
|
||||
@ -339,10 +334,15 @@ class API extends \Util\Singleton
|
||||
*/
|
||||
public static function getRequest()
|
||||
{
|
||||
$request = (array) json_decode(file_get_contents('php://input'), true);
|
||||
$request = [];
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'GET' && empty($request)) {
|
||||
$request = Filter::getGET();
|
||||
if (self::isAPIRequest()) {
|
||||
$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;
|
||||
|
@ -51,6 +51,7 @@ class Auth extends \Util\Singleton
|
||||
$database = Database::getConnection();
|
||||
|
||||
if ($database->isInstalled()) {
|
||||
// Controllo dell'accesso da API
|
||||
if (API::isAPIRequest()) {
|
||||
$token = API::getRequest()['token'];
|
||||
|
||||
@ -81,6 +82,7 @@ class Auth extends \Util\Singleton
|
||||
{
|
||||
session_regenerate_id();
|
||||
|
||||
// Controllo sulla disponibilità dell'accesso (brute-forcing non in corso)
|
||||
if (self::isBrute()) {
|
||||
return false;
|
||||
}
|
||||
@ -105,15 +107,18 @@ class Auth extends \Util\Singleton
|
||||
$this->password_check($password, $user['password'], $user['id_utente']) &&
|
||||
!empty($module)
|
||||
) {
|
||||
// Accesso completato
|
||||
$log['id_utente'] = $this->infos['id_utente'];
|
||||
$log['stato'] = self::$status['success']['code'];
|
||||
|
||||
// Salvataggio nella sessione
|
||||
$this->saveToSession();
|
||||
} else {
|
||||
if (empty($module)) {
|
||||
$log['stato'] = self::$status['unauthorized']['code'];
|
||||
}
|
||||
|
||||
// Logout automatico
|
||||
$this->destory();
|
||||
}
|
||||
} else {
|
||||
@ -121,6 +126,7 @@ class Auth extends \Util\Singleton
|
||||
}
|
||||
}
|
||||
|
||||
// Salvataggio dello stato nella sessione
|
||||
if ($log['stato'] != self::$status['success']['code']) {
|
||||
foreach (self::$status as $key => $value) {
|
||||
if ($log['stato'] == $value['code']) {
|
||||
@ -130,6 +136,7 @@ class Auth extends \Util\Singleton
|
||||
}
|
||||
}
|
||||
|
||||
// Salvataggio del tentativo nel database
|
||||
$database->insert('zz_logs', $log);
|
||||
|
||||
return $this->isAuthenticated();
|
||||
|
@ -472,7 +472,7 @@ class Database extends Util\Singleton
|
||||
{
|
||||
if (
|
||||
!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))
|
||||
) {
|
||||
throw new UnexpectedValueException();
|
||||
@ -541,7 +541,7 @@ class Database extends Util\Singleton
|
||||
$sync = array_unique((array) current($list));
|
||||
|
||||
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));
|
||||
$this->detach($table, $conditions, [$field => $detachs]);
|
||||
@ -573,7 +573,7 @@ class Database extends Util\Singleton
|
||||
$sync = array_unique((array) current($list));
|
||||
|
||||
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));
|
||||
foreach ($inserts as $insert) {
|
||||
@ -605,14 +605,9 @@ class Database extends Util\Singleton
|
||||
$sync = array_unique((array) current($list));
|
||||
|
||||
if (!empty($field) && !empty($sync)) {
|
||||
$where = $this->whereStatement($conditions);
|
||||
$conditions[$field] = $sync;
|
||||
|
||||
$in = [];
|
||||
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).')');
|
||||
$this->query('DELETE FROM '.$this->quote($table).' WHERE '.$this->whereStatement($conditions));
|
||||
}
|
||||
}
|
||||
|
||||
@ -653,26 +648,40 @@ class Database extends Util\Singleton
|
||||
{
|
||||
$result = [];
|
||||
|
||||
if (is_array($where)) {
|
||||
foreach ($where as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
$key = strtoupper($key);
|
||||
$key = (in_array($key, ['AND', 'OR'])) ? $key : 'AND';
|
||||
|
||||
foreach ($where as $key => $value) {
|
||||
// Query personalizzata
|
||||
if (starts_with($key, '#')) {
|
||||
$result[] = $this->prepareValue($key, $value);
|
||||
} else {
|
||||
// Ulteriori livelli di complessità
|
||||
if (is_array($value) && in_array(strtoupper($key), ['AND', 'OR'])) {
|
||||
$result[] = '('.$this->whereStatement($value, $key == 'AND').')';
|
||||
} elseif (starts_with($value, '#') && ends_with($value, '#')) {
|
||||
$result[] = substr($value, 1, -1);
|
||||
} elseif (starts_with($value, '%') || ends_with($value, '%')) {
|
||||
}
|
||||
// Condizione IN
|
||||
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);
|
||||
} elseif (str_contains($value, '|')) {
|
||||
}
|
||||
// Condizione BETWEEN
|
||||
elseif (str_contains($value, '|')) {
|
||||
$pieces = explode('|', $value);
|
||||
$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);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result[] = $where;
|
||||
}
|
||||
|
||||
$cond = !empty($and) ? 'AND' : 'OR';
|
||||
|
@ -10,6 +10,7 @@ switch ($resource) {
|
||||
$tokens = $database->fetchArray('SELECT `token` FROM `zz_tokens` WHERE `enabled` = 1 AND `id_utente` = '.prepare($user['id_utente']));
|
||||
if (empty($tokens)) {
|
||||
$token = secure_random_string();
|
||||
|
||||
$database->insert('zz_tokens', [
|
||||
'id_utente' => $user['id_utente'],
|
||||
'token' => $token,
|
||||
@ -38,6 +39,7 @@ switch ($resource) {
|
||||
// Operazione di logout
|
||||
case 'logout':
|
||||
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']));
|
||||
} else {
|
||||
$results = [
|
||||
|
@ -680,7 +680,7 @@ ALTER TABLE `zz_semaphores` ADD FOREIGN KEY (`id_utente`) REFERENCES `zz_users`(
|
||||
CREATE TABLE IF NOT EXISTS `zz_tokens` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`id_utente` int(11) NOT NULL,
|
||||
`token` varchar(255) NOT NULL UNIQUE,
|
||||
`token` varchar(255) NOT NULL,
|
||||
`descrizione` varchar(255),
|
||||
`enabled` boolean NOT NULL DEFAULT 1,
|
||||
PRIMARY KEY (`id`),
|
||||
|
Loading…
Reference in New Issue
Block a user