Implement route-level permission handling.
Added support for defining and registering permissions for API routes. Updated methods across the router and route traits to accommodate permission details, enabling better access control. Enhanced department license plate lookup with session validation and additional endpoints.
This commit is contained in:
@@ -17,9 +17,9 @@ class router
|
||||
$this->routeClasses = [];
|
||||
}
|
||||
|
||||
public function add($route, $method, $function): void
|
||||
public function add($route, $method, $function, array $permissions = []): void
|
||||
{
|
||||
$this->routes[] = ['route' => $route, 'method' => $method, 'function' => $function];
|
||||
$this->routes[] = ['route' => $route, 'method' => $method, 'function' => $function, 'permissions' => $permissions];
|
||||
}
|
||||
|
||||
public function auto_load_routes(string $path): void
|
||||
@@ -112,6 +112,15 @@ class router
|
||||
return count($this->routes);
|
||||
}
|
||||
|
||||
public function getPermissions(): array
|
||||
{
|
||||
$permissions = [];
|
||||
foreach ( $this->routes as $route ) {
|
||||
$permissions = array_merge($permissions, $route['permissions']);
|
||||
}
|
||||
return $permissions;
|
||||
}
|
||||
|
||||
public function getRoutes(): array
|
||||
{
|
||||
return $this->routes;
|
||||
|
||||
@@ -13,21 +13,74 @@ class vehiclePlateLookupRoute
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
$this->get('/department/license-plate/lookup', function () {
|
||||
$this->get(
|
||||
'/department/license-plate/lookup',
|
||||
function () {
|
||||
// Require the user to be logged in
|
||||
global $response;
|
||||
$this->requirePermission('department_license_plate_lookup');
|
||||
// Get the user object
|
||||
$user = (new authentication())->get_user();
|
||||
// Check if the request was successful
|
||||
if ($user) {
|
||||
// Make sure the vehicle plate is set
|
||||
if (!(string)$this->fromRequest('plate')) {
|
||||
$response->error('Plate parameter is required', 400);
|
||||
}
|
||||
// Return the vehicle order history
|
||||
$response->success(
|
||||
(new orders_o())->get_vehicle_order_history($this->fromRequest('plate'))
|
||||
);
|
||||
} else {
|
||||
// Log the incident
|
||||
(new logs_o())->add('orders', 'global', 1, 0, 'FETCH_VEHICLE_ORDER_HISTORY', 'No user found, or invalid session');
|
||||
// Return an error
|
||||
$response->error('Invalid session', 400);
|
||||
}
|
||||
},
|
||||
[
|
||||
'department_license_plate_lookup' => 'Department license plate lookup'
|
||||
]
|
||||
);
|
||||
|
||||
$this->get('/department/license-plate/customer-lookup', function () {
|
||||
// Require the user to be logged in
|
||||
global $response;
|
||||
$this->requirePermission('department_license_plate_lookup');
|
||||
self::requirePermission('department_license_plate_lookup');
|
||||
// Get the user object
|
||||
$user = (new authentication())->get_user();
|
||||
// Check if the request was successful
|
||||
if ($user) {
|
||||
// Make sure the vehicle plate is set
|
||||
if (!(string)$this->fromRequest('plate')) {
|
||||
$response->error('Plate parameter is required', 400);
|
||||
self::requireParameters(['plate', 'customer_number', 'column']);
|
||||
self::requireType((string)self::getParameter('plate'), 'string');
|
||||
self::requireType((int)self::getParameter('customer_number'), self::type_int());
|
||||
self::requireType((string)self::getParameter('column'), 'string');
|
||||
self::requireMinLength('customer_number', 1);
|
||||
self::requireMaxLength('customer_number', 10);
|
||||
self::requireMinLength('plate', 0);
|
||||
self::requireMaxLength('plate', 10);
|
||||
// Make sure the column is allowed
|
||||
$allowedColumns = ['reg_1', 'reg_2', 'reg_3'];
|
||||
if (!in_array((string)self::getParameter('column'), $allowedColumns)) {
|
||||
$response->error('Invalid column, allowed columns are: ' . implode(', ', $allowedColumns), 400);
|
||||
}
|
||||
// Return the vehicle order history
|
||||
$response->success(
|
||||
(new orders_o())->get_vehicle_order_history($this->fromRequest('plate'))
|
||||
(new orders_o())
|
||||
->setSearchableFields(['customer_id', (string)self::getParameter('column'), 'created_at'])
|
||||
->listObjectsWithPagination(
|
||||
1,
|
||||
10,
|
||||
(string)self::getParameter('plate'),
|
||||
['customer_id' => self::getParameter('customer_number')],
|
||||
['created_at' => 'DESC'],
|
||||
function ($order) {
|
||||
return [
|
||||
'registration_number' => $order[(string)self::getParameter('column')], // Get the registration number
|
||||
];
|
||||
}
|
||||
)
|
||||
);
|
||||
} else {
|
||||
// Log the incident
|
||||
|
||||
@@ -14,7 +14,7 @@ class workerRoute
|
||||
$this->get('/worker/status', function () {
|
||||
global /** @var router $router */
|
||||
$response, $router;
|
||||
$response->success(['message' => 'Worker is running', 'status' => 'OK', 'time' => date('Y-m-d H:i:s'), 'timezone' => date_default_timezone_get(), 'host' => gethostname(), 'version' => '1.0.1', 'routes' => $router->countRoutes()]);
|
||||
$response->success(['message' => 'Worker is running', 'status' => 'OK', 'time' => date('Y-m-d H:i:s'), 'timezone' => date_default_timezone_get(), 'host' => gethostname(), 'version' => '1.0.1', 'routes' => $router->countRoutes(), 'permissions' => $router->getPermissions()]);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ use objects\logs_o;
|
||||
|
||||
trait route_t
|
||||
{
|
||||
protected array $permissions = [];
|
||||
private string $route;
|
||||
|
||||
public function __construct()
|
||||
@@ -103,61 +104,92 @@ trait route_t
|
||||
/**
|
||||
* GET route
|
||||
* @param string $route Example: /home, /home/{id}
|
||||
* @param callable $callback
|
||||
* @param array $permissions
|
||||
* @return void
|
||||
*/
|
||||
public function get(string $route, callable $callback): void
|
||||
public function get(string $route, callable $callback, array $permissions = []): void
|
||||
{
|
||||
$this->registerRoute($route, 'GET', $callback);
|
||||
$this->registerRoute($route, 'GET', $callback, $permissions);
|
||||
}
|
||||
|
||||
private function registerRoute($route, $method, $callback): void
|
||||
private function registerRoute($route, $method, $callback, $permissions = []): void
|
||||
{
|
||||
global $router;
|
||||
$router->add($route, $method, $callback);
|
||||
$router->add($route, $method, $callback, self::registerPermissions($permissions, $route, $method));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register permissions for the route
|
||||
* @param array $permissions The permissions to register
|
||||
* @param null $endpoint
|
||||
* @param null $method
|
||||
* @return array
|
||||
*/
|
||||
public function registerPermissions(array $permissions, $endpoint = null, $method = null): array
|
||||
{
|
||||
foreach ( $permissions as $permission => $description ) {
|
||||
$this->registerPermission($permission, $description, $endpoint, $method);
|
||||
}
|
||||
return $this->permissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a permission
|
||||
* @param string $permission The permission to register (Example: 'modules_motorapi_lookup')
|
||||
* @param string $description The description of the permission (Example: 'Lookup license plate information')
|
||||
* @param null $endpoint The endpoint of the permission (Example: '/department/license-plate/lookup')
|
||||
* @param null $method The method of the permission (Example: 'GET')
|
||||
* @return void
|
||||
*/
|
||||
public function registerPermission(string $permission, string $description = 'No description provided.', $endpoint = null, $method = null): void
|
||||
{
|
||||
$this->permissions[$endpoint ?? $this->route][$method ?? 'UNKNOWN_METHOD'][$permission] = $description;
|
||||
}
|
||||
|
||||
/**
|
||||
* POST route
|
||||
* @param string $route Example: /home, /home/{id}
|
||||
*/
|
||||
public function post(string $route, callable $callback): void
|
||||
public function post(string $route, callable $callback, array $permissions = []): void
|
||||
{
|
||||
$this->registerRoute($route, 'POST', $callback);
|
||||
$this->registerRoute($route, 'POST', $callback, $permissions);
|
||||
}
|
||||
|
||||
/**
|
||||
* PUT route
|
||||
* @param string $route Example: /home, /home/{id}
|
||||
*/
|
||||
public function put(string $route, callable $callback): void
|
||||
public function put(string $route, callable $callback, array $permissions = []): void
|
||||
{
|
||||
$this->registerRoute($route, 'PUT', $callback);
|
||||
$this->registerRoute($route, 'PUT', $callback, $permissions);
|
||||
}
|
||||
|
||||
/**
|
||||
* DELETE route
|
||||
* @param string $route Example: /home, /home/{id}
|
||||
*/
|
||||
public function delete(string $route, callable $callback): void
|
||||
public function delete(string $route, callable $callback, array $permissions = []): void
|
||||
{
|
||||
$this->registerRoute($route, 'DELETE', $callback);
|
||||
$this->registerRoute($route, 'DELETE', $callback, $permissions);
|
||||
}
|
||||
|
||||
/**
|
||||
* OPTIONS route
|
||||
* @param string $route Example: /home, /home/{id}
|
||||
*/
|
||||
public function options(string $route, callable $callback): void
|
||||
public function options(string $route, callable $callback, array $permissions = []): void
|
||||
{
|
||||
$this->registerRoute($route, 'OPTIONS', $callback);
|
||||
$this->registerRoute($route, 'OPTIONS', $callback, $permissions);
|
||||
}
|
||||
|
||||
/**
|
||||
* PATCH route
|
||||
* @param string $route Example: /home, /home/{id}
|
||||
*/
|
||||
public function patch(string $route, callable $callback): void
|
||||
public function patch(string $route, callable $callback, array $permissions = []): void
|
||||
{
|
||||
$this->registerRoute($route, 'PATCH', $callback);
|
||||
$this->registerRoute($route, 'PATCH', $callback, $permissions);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user