Skip to content

Commit 6037b90

Browse files
author
Marco Cesarato
committed
chore: update core
- Add new filter with examples - Add check if primary key already exists on insert and add hooks to bypass failed error - Add counter to every request to check if at least one is executed - Improve logger date with microtime - Improve code quality - Fix some issues and old methods calling - BREAKING CHANGES: `custom_api_call` renamed to `endpoint` and `public_endpoint`
1 parent 5a769fa commit 6037b90

File tree

10 files changed

+419
-105
lines changed

10 files changed

+419
-105
lines changed

includes/classes/API.php

Lines changed: 162 additions & 40 deletions
Large diffs are not rendered by default.

includes/classes/Auth.php

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
class Auth
1717
{
1818
/**
19-
* @var string token storage table name
19+
* Tokens storage table.
20+
*
21+
* @var string
2022
*/
2123
public static $api_table = 'api_auth';
2224

@@ -40,11 +42,24 @@ class Auth
4042
* @var Request
4143
*/
4244
public static $settings;
43-
44-
public $user = [];
45+
/**
46+
* User data.
47+
*
48+
* @var object
49+
*/
50+
public $user;
51+
/**
52+
* Account associated to the user.
53+
*
54+
* @var object
55+
*/
56+
public $account;
4557
public $user_id;
4658
public $is_admin = false;
4759
public $authenticated = false;
60+
/**
61+
* @var PDO
62+
*/
4863
private $db;
4964
private $table_free = [];
5065
private $table_readonly = [];
@@ -63,7 +78,7 @@ public function __construct()
6378
/**
6479
* Get user row.
6580
*
66-
* @return array
81+
* @return object
6782
*/
6883
public static function getUser()
6984
{
@@ -113,7 +128,7 @@ public function validate($query)
113128
$this->checkAPITable();
114129
}
115130

116-
if (!empty($this->query['check_counter']) && $this->validateToken($this->query['token']) && $this->is_admin) {
131+
if (!empty($this->query['check_counter']) && $this->validateToken($this->query['token']) && $this->isAdmin()) {
117132
$this->checkCounter();
118133
} elseif (!empty($this->query['check_token']) && $this->validateToken($this->query['check_token'])) {
119134
$this->checkToken();
@@ -165,7 +180,7 @@ public function validate($query)
165180
if ($user_row[$users_columns['password']] == $password) {
166181
$token = $this->generateToken($user_row[$users_columns['id']], $user_row[$users_columns['username']]);
167182
$this->user_id = $user_row[$users_columns['id']];
168-
$this->is_admin = !empty($users_columns['admin']) ? $user_row[key(reset($users_columns['admin']))] : false;
183+
$this->setIsAdmin(!empty($users_columns['admin']) ? $user_row[key(reset($users_columns['admin']))] : false);
169184
// Render
170185
$results = [
171186
(object)[
@@ -301,7 +316,7 @@ private function validateToken($token)
301316
$this->user = $user_row;
302317
$this->user_id = $user_row['id'];
303318
if (!empty($users_columns['admin'])) {
304-
$this->is_admin = (($user_row[key($users_columns['admin'])] == reset($users_columns['admin'])) ? true : false);
319+
$this->setIsAdmin(($user_row[key($users_columns['admin'])] == reset($users_columns['admin'])) ? true : false);
305320
}
306321
$this->authenticated = true;
307322

@@ -367,7 +382,7 @@ public function generateToken($user_id, $user_name)
367382
{
368383
$this->db = $this->getAPIDatabase();
369384
try {
370-
$token = md5(uniqid(rand(), true));
385+
$token = md5(uniqid(mt_rand(), true));
371386
$sth = $this->db->prepare('INSERT INTO ' . self::$api_table . ' (token,user_id,user_name,user_agent) VALUES (:token,:user_id,:user_name,:user_agent)');
372387
$sth->bindParam(':token', $token);
373388
$sth->bindParam(':user_name', $user_name);
@@ -398,7 +413,7 @@ public function permissionSQL($table, $permission)
398413
$sql = '';
399414

400415
// All allowed
401-
if ($this->is_admin == true) {
416+
if ($this->isAdmin()) {
402417
$sql = "'1' = '1'";
403418
}
404419

@@ -524,7 +539,43 @@ public function canDelete($table)
524539
*/
525540
private function needIncrementCounter()
526541
{
527-
return !(!empty($this->query['docs']) || !empty($this->query['check_token']) || !empty($this->query['check_counter']) || !empty($this->query['user_id']) && !empty($this->query['password']));
542+
return !(
543+
!empty($this->query['docs']) ||
544+
!empty($this->query['check_token']) ||
545+
!empty($this->query['check_counter']) ||
546+
(
547+
!empty($this->query['user_id']) &&
548+
!empty($this->query['password'])
549+
)
550+
);
551+
}
552+
553+
/**
554+
* @return bool
555+
*/
556+
public function isAuthenticated()
557+
{
558+
return !empty(self::getUser());
559+
}
560+
561+
/**
562+
* @return bool
563+
*/
564+
public function isAdmin()
565+
{
566+
return $this->is_admin === true;
567+
}
568+
569+
/**
570+
* @param bool $is_admin
571+
*
572+
* @return self
573+
*/
574+
public function setIsAdmin($is_admin)
575+
{
576+
$this->is_admin = $is_admin;
577+
578+
return $this;
528579
}
529580
}
530581

includes/classes/Logger.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class Logger
2020
protected $file;
2121
protected $params = [];
2222
protected $options = [
23-
'dateFormat' => 'd-M-Y H:i:s',
23+
'dateFormat' => 'd-M-Y H:i:s.u',
2424
'onlyMessage' => false,
2525
];
2626
protected $cache = '';
@@ -133,8 +133,12 @@ public function writeLog($message, $severity)
133133
$method = Request::method();
134134
// Grab the url path ( for troubleshooting )
135135
$path = $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
136+
136137
// Grab time - based on timezone in php.ini
137-
$time = date($this->params['dateFormat']);
138+
$t = microtime(true);
139+
$micro = sprintf('%06d', ($t - floor($t)) * 1000000);
140+
$d = new DateTime(date('Y-m-d H:i:s.' . $micro, $t));
141+
$time = $d->format($this->params['dateFormat']);
138142

139143
$ip = Request::getIPAddress();
140144

includes/classes/Request.php

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -70,17 +70,17 @@ public static function getParams($sanitize = true)
7070
// Auth
7171
if (!empty($params['auth'])) {
7272
if (empty($params['user_id'])) {
73-
$params['user_id'] = (!empty($_SERVER['HTTP_AUTH_ACCOUNT']) ? $_SERVER['HTTP_AUTH_ACCOUNT'] : uniqid(rand(), true));
73+
$params['user_id'] = (!empty($_SERVER['HTTP_AUTH_ACCOUNT']) ? $_SERVER['HTTP_AUTH_ACCOUNT'] : uniqid(mt_rand(), true));
7474
}
7575
if (empty($params['password'])) {
76-
$params['password'] = (!empty($_SERVER['HTTP_AUTH_PASSWORD']) ? $_SERVER['HTTP_AUTH_PASSWORD'] : uniqid(rand(), true));
76+
$params['password'] = (!empty($_SERVER['HTTP_AUTH_PASSWORD']) ? $_SERVER['HTTP_AUTH_PASSWORD'] : uniqid(mt_rand(), true));
7777
}
7878
unset($params['token']);
7979
}
8080

8181
// Check token
8282
if (!empty($params['check_auth']) && empty($params['check_token'])) {
83-
$params['check_token'] = (!empty($_SERVER['HTTP_ACCESS_TOKEN']) ? $_SERVER['HTTP_ACCESS_TOKEN'] : uniqid(rand(), true));
83+
$params['check_token'] = (!empty($_SERVER['HTTP_ACCESS_TOKEN']) ? $_SERVER['HTTP_ACCESS_TOKEN'] : uniqid(mt_rand(), true));
8484
unset($params['token']);
8585
}
8686

@@ -283,12 +283,12 @@ public static function getIPAddress()
283283
if (preg_match('/^::ffff:(\d+\.\d+\.\d+\.\d+)$/', $ip, $matches)) {
284284
$ip = $matches[1];
285285
}
286-
if ($ip == '::1') {
286+
if ($ip === '::1') {
287287
$ip = '127.0.0.1';
288288
}
289-
if ($ip == '127.0.0.1' || self::isPrivateIP($ip)) {
289+
if ($ip === '127.0.0.1' || self::isPrivateIP($ip)) {
290290
$ip = $_SERVER['REMOTE_ADDR'];
291-
if ($ip == '::1') {
291+
if ($ip === '::1') {
292292
$ip = '127.0.0.1';
293293
}
294294

@@ -449,7 +449,7 @@ public static function getAllIPAddress()
449449
if (preg_match('/^::ffff:(\d+\.\d+\.\d+\.\d+)$/', $ip, $matches)) {
450450
$ip = $matches[1];
451451
}
452-
if ($ip == '::1') {
452+
if ($ip === '::1') {
453453
$ips[] = '127.0.0.1';
454454
} elseif (self::validateIPAddress($ip)) {
455455
$ips[] = $ip;
@@ -471,13 +471,10 @@ public static function getAllIPAddress()
471471
* @param $params mixed data to sanitize
472472
*
473473
* @return $params sanitized data
474-
*
475-
* @author Marco Cesarato <cesarato.developer@gmail.com>
476474
*/
477475
private static function sanitizeParams($params)
478476
{
479477
foreach ($params as $key => $value) {
480-
$value = trim_all($value);
481478
$value = self::sanitizeRXSS($value);
482479
$value = self::sanitizeStriptags($value);
483480
$value = self::sanitizeHtmlentities($value);

includes/classes/Response.php

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,8 @@ class Response
1515
public static $instance;
1616
public $input;
1717

18-
public function __construct()
19-
{
20-
}
21-
2218
/**
23-
* Return success reponse.
19+
* Return success response.
2420
*
2521
* @return array
2622
*/
@@ -45,35 +41,52 @@ public static function created()
4541

4642
/**
4743
* Return failed response.
44+
*
45+
* @return array
4846
*/
4947
public static function failed()
5048
{
51-
self::error('Bad request', 400);
49+
$message = 'Bad request';
50+
$code = 400;
51+
52+
self::error($message, $code);
53+
54+
return ['response' => (object)['status' => $code, 'message' => $message]];
5255
}
5356

5457
/**
5558
* Return failed response.
5659
*
5760
* @param string $msg
61+
*
62+
* @return array
5863
*/
5964
public static function noPermissions($msg = '')
6065
{
61-
self::error('No permissions ' . $msg, 403);
66+
$message = 'No permissions ' . $msg;
67+
$code = 403;
68+
69+
self::error($message, $code);
70+
71+
return ['response' => (object)['status' => $code, 'message' => $message]];
6272
}
6373

6474
/**
6575
* Halt the program with an "Internal server error" and the specified message.
6676
*
6777
* @param string|object $error the error or a (PDO) exception object
6878
* @param int $code (optional) the error code with which to respond
69-
* @param bool $custom_call
79+
* @param bool $internal if true will fallback to the first endpoint available
80+
*
81+
* @return array
7082
*/
71-
public static function error($error, $code = 500, $custom_call = false)
83+
public static function error($error, $code = 500, $internal = false)
7284
{
7385
$hooks = Hooks::getInstance();
74-
if ($custom_call) {
75-
$hooks->do_action('custom_api_call');
86+
if ($internal) {
87+
$hooks->do_action('endpoint');
7688
}
89+
$hooks->do_action('public_endpoint');
7790
$hooks->do_action('on_error', $error, $code);
7891

7992
$api = API::getInstance();
@@ -83,15 +96,17 @@ public static function error($error, $code = 500, $custom_call = false)
8396
$results = [
8497
'response' => (object)['status' => 400, 'message' => $message],
8598
];
86-
$logger->error($code . ' - ' . $error);
99+
$logger->error('ERROR_' . $code . ': ' . $error);
87100
$api->render($results);
88101
}
89102
http_response_code($code);
90103
$error = trim($error);
91-
$logger->error($code . ' - ' . $error);
104+
$logger->error('ERROR_' . $code . ': ' . $error);
92105
$results = [
93106
'response' => (object)['status' => $code, 'message' => Request::sanitizeHtmlentities($error)],
94107
];
95108
$api->render($results);
109+
110+
return ['response' => (object)['status' => $code, 'message' => $error]];
96111
}
97112
}

includes/functions.php

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,9 @@ function array_to_object($array)
6262
function is_https()
6363
{
6464
if (isset($_SERVER['HTTP_HOST'])) {
65-
if (((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || $_SERVER['SERVER_PORT'] == 443)
66-
|| !empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' || !empty($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on') {
67-
return true;
68-
}
69-
70-
return false;
65+
return ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || $_SERVER['SERVER_PORT'] == 443) ||
66+
(!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') ||
67+
(!empty($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] === 'on');
7168
}
7269

7370
return false;
@@ -130,7 +127,9 @@ function trim_all($arr, $charlist = ' ')
130127
{
131128
if (is_string($arr)) {
132129
return trim($arr, $charlist);
133-
} elseif (is_array($arr)) {
130+
}
131+
132+
if (is_array($arr)) {
134133
foreach ($arr as $key => $value) {
135134
if (is_array($value)) {
136135
$result[$key] = trim_all($value, $charlist);
@@ -140,13 +139,13 @@ function trim_all($arr, $charlist = ' ')
140139
}
141140

142141
return $result;
143-
} else {
144-
return $arr;
145142
}
143+
144+
return $arr;
146145
}
147146

148147
/**
149-
* Recusively travserses through an array to propegate SimpleXML objects.
148+
* Recursively traverses through an array to propagate SimpleXML objects.
150149
*
151150
* @param array $array the array to parse
152151
* @param object $xml the Simple XML object (must be at least a single empty node)

plugins/actions.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@
88
use marcocesarato\DatabaseAPI\Response;
99

1010
/**
11-
* Custom API Call.
11+
* Endpoint.
1212
*
1313
* @param $query
1414
*/
15-
function action_custom_api_call($query)
15+
function action_endpoint($query)
1616
{
1717
$api = API::getInstance();
1818
$api->query['part_1'] = $api->query['db'];

plugins/custom/example.hooks.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@
1111
$hooks = Hooks::getInstance();
1212

1313
/**
14-
* Custom API Call.
14+
* Endpoint example.
1515
*
1616
* @return mixed or die (with mixed return just skip to next action until 404 error)
1717
*/
18-
function action_custom_api_call_example()
18+
function action_endpoint_example()
1919
{
2020
$user = Auth::getUser(); // User row
2121
$api = API::getInstance(); // PDO Object
@@ -35,4 +35,7 @@ function action_custom_api_call_example()
3535
}*/
3636
}
3737

38-
$hooks->add_action('custom_api_call', 'action_custom_api_call_example');
38+
// Private
39+
$hooks->add_action('endpoint', 'action_endpoint_example');
40+
// Public
41+
$hooks->add_action('public_endpoint', 'action_endpoint_example');

0 commit comments

Comments
 (0)