Files
api/services/nginx/app/routes/bookingsRoute.php
T
Jepp9350 491f268108 Add role and permission management with enhanced access control
This update introduces functionalities for managing roles, permissions, and access control across departments. Key additions include methods for filtering, restricting, and handling user permissions, as well as new APIs for assigning/removing permissions to/from roles. Access to resources like orders, bookings, and plate scans is now securely tied to department-specific permissions.
2025-02-27 17:54:18 +01:00

361 lines
16 KiB
PHP

<?php
namespace routes;
use classes\authentication;
use classes\response;
use classes\wash_certificate_store;
use objects\bookings_o;
use objects\departments_o;
use objects\logs_o;
use traits\route_t;
class bookingsRoute
{
use route_t;
public function run(): void
{
/** All bookings */
$this->get('/bookings', function () {
// Require the user to be logged in
global
/** @var response $response */
$EMAIL_WASH_CERTIFICATE_TOKEN,
$response;
$this->requirePermission('list_bookings');
// Get the user object
$user = (new authentication())->get_user();
// Check if the request was successful
if ($user) {
// Log the incident
(new logs_o())->add('bookings', 'global', 1, $user->id, 'LIST_BOOKINGS', 'Successfully listed bookings');
// If the user has the permission to issue wash certificates, add the wash certificate key to the response
if ($user->hasPermission('issue_wash_certificates')) {
$response->add_meta('wash_certificate_token', $EMAIL_WASH_CERTIFICATE_TOKEN);
}
$bookings_o = new bookings_o();
// Return the list of bookings
$response->success(
$bookings_o->parseBookings($bookings_o->listObjectsWithPaginationIfSet(
function ($booking) {
$booking['department'] = (int)$booking['department'];
return $booking;
},
$bookings_o->forceRestrictFilters(
[
'department' => $user->getGroup()->getDepartments(),
]
)
))
);
} else {
// Log the incident
(new logs_o())->add('bookings', 'global', 1, 0, 'LIST_BOOKINGS', 'No user found, or invalid session');
// Return an error
$response->error('Invalid session', 400);
}
},
[
'list_bookings' => 'List all bookings',
'issue_wash_certificates' => 'When set, the response will include the wash certificate token for sending wash certificates'
]
);
/** Own bookings */
$this->get('/user/bookings', function () {
// Require the user to be logged in
global /** @var response $response */
$response;
$this->requirePermission('list_own_bookings');
// Get the user object
$user = (new authentication())->get_user();
// Check if the request was successful
if ($user) {
// Log the incident
(new logs_o())->add('bookings', 'global', 1, $user->id, 'LIST_OWN_BOOKINGS', 'Successfully listed own bookings');
// Return the list of departments
$bookings_o = new bookings_o();
$response->success(
$bookings_o->parseBookings($bookings_o->getCustomerBookingsPaginated(
$user->customer_number->value(),
($this->fromRequest('page') ?? 1),
($this->fromRequest('limit') ?? 10),
['id' => 'DESC'],
$this->fromRequest('search') === null ? '' : $this->fromRequest('search'),
$this->fromRequest('filters') === null ? [] :
$response->parseFilters($this->fromRequest('filters')) ?? []
))
);
} else {
// Log the incident
(new logs_o())->add('bookings', 'global', 1, 0, 'LIST_OWN_BOOKINGS', 'No user found, or invalid session');
// Return an error
$response->error('Invalid session', 400);
}
},
[
'list_own_bookings' => 'List all bookings for the logged in user'
]
);
// Synchronize booking from the external system
$this->post('/admin/bookings/sync', function () {
// Require the user to be logged in
global $response;
if ($this->fromRequest('auth_key') !== 'earm8BX4MFTgS6JCNQdqW5EzHUutv2Vx')
$this->requirePermission('sync_bookings');
// Check if the request was successful
$booking = [
'id' => $this->fromRequest('id'),
'customer_number' => $this->fromRequest('customer_number'),
'wash_type' => $this->fromRequest('wash_type'),
'contact_email' => $this->fromRequest('contact_email'),
'reference_number' => $this->fromRequest('reference_number'),
'regNrTraekker' => $this->fromRequest('regNrTraekker'),
'regNrTrailer' => $this->fromRequest('regNrTrailer'),
'washCertificateEmail' => $this->fromRequest('washCertificateEmail'),
'date' => $this->fromRequest('date'),
'department' => $this->fromRequest('department'),
'pickup_bool' => $this->fromRequest('pickup_bool'),
'notes' => $this->fromRequest('notes'),
'washCertificateStatus' => $this->fromRequest('washCertificateStatus'),
'washCertificateUrl' => $this->fromRequest('washCertificateUrl'),
'status' => $this->fromRequest('status'),
];
// Log the incident
(new logs_o())->add('bookings', 'global', 1, 0, 'SYNC_BOOKINGS', 'Successfully synced bookings');
// Add the booking, if it doesn't exist, update it if it does
(new bookings_o())->addOrUpdate(
(int)$booking['id'],
(int)$booking['customer_number'],
(string)$booking['wash_type'],
(string)$booking['contact_email'],
(string)$booking['reference_number'],
(string)$booking['regNrTraekker'],
(string)$booking['regNrTrailer'],
(string)$booking['washCertificateEmail'],
(string)$booking['date'],
(string)$booking['department'],
(string)$booking['pickup_bool'],
(string)$booking['notes'],
(string)$booking['washCertificateStatus'],
(string)$booking['washCertificateUrl'],
(string)$booking['status']
);
$response->success(
['message' => 'Successfully synced booking']
);
},
[
'sync_bookings' => 'Sync bookings from the external system NOTE: This permission is only required if the auth_key is not set'
]
);
// Get a departments unfulfilled bookings (count) for the day
$this->get('/admin/bookings/department/count', function () {
// Require the user to be logged in
global /** @var response $response */
$response;
$this->requirePermission('list_department_bookings_count');
// Get the user object
$user = (new authentication())->get_user();
// Check if the request was successful
if ($user) {
// Check if the department_id is set
if ($this->fromRequest('department_id') === null) {
$response->error('Department ID is required', 400);
}
// Check if the department id is a valid number
if (!is_numeric($this->fromRequest('department_id'))) {
$response->error('Department ID must be a number', 400);
}
// Check if the result is cached, if so, we don't need to query the database
if (redis->get_department_booking_count((int)$this->fromRequest('department_id'))) {
$response->add_meta('cached', true);
$response->success(
redis->get_department_booking_count((int)$this->fromRequest('department_id'))
);
}
// Check if the department exists
if (!(new departments_o())->selectId((int)$this->fromRequest('department_id'))->exists()) {
$response->error('Department not found', 404);
}
// Log the incident
(new logs_o())->add('bookings', 'global', 1, $user->id, 'LIST_DEPARTMENT_BOOKINGS_COUNT', 'Successfully listed department bookings');
// Return the list of departments
$response->success(
(new bookings_o())->getDepartmentBookingsUnfulfilledCount((int)$this->fromRequest('department_id'))
);
} else {
// Log the incident
(new logs_o())->add('bookings', 'global', 1, 0, 'LIST_DEPARTMENT_BOOKINGS_COUNT', 'No user found, or invalid session');
// Return an error
$response->error('Invalid session', 400);
}
},
[
'list_department_bookings_count' => 'List the unfulfilled bookings count for a department'
]
);
$this->post('/user/bookings/washcertificate/download', function () {
// Require the user to be logged in
global /** @var response $response */
$response;
$this->requirePermission('download_own_wash_certificate');
// Get the user object
$user = (new authentication())->get_user();
// Check if the request was successful
if (!$user->exists()) {
$response->error('User not found', 400);
}
// Check if the required fields are set
$id = $response->getRequestParameter('id');
// Make sure the id is a number
if (!is_numeric($id)) {
$response->error('id parameter must be a number got: ' . $id, 400);
}
// Make sure the user is allowed to download the wash certificate
if (!$user->hasAccessToBooking($id)) {
$response->error('You are not allowed to download this wash certificate', 400);
}
// Create the connection
$wash_certificate_store = new wash_certificate_store();
// Check if the wash certificate exists.
if (!$wash_certificate_store->washCertificateExists($id)) {
$response->error('The wash certificate does not exist. id: ' . $id, 404);
}
// Generate the download link
$response->success(
["link" => $wash_certificate_store->getWashCertificateDownload($id)]
);
},
[
'download_own_wash_certificate' => 'Download the wash certificate for a booking'
]
);
$this->post('/admin/bookings/delete', function () {
// Require the user to be logged in
global /** @var response $response */
$response;
$this->requirePermission('delete_booking');
// Get the user object
$user = (new authentication())->get_user();
// Check if the request was successful
if (!$user->exists()) {
$response->error('User not found', 400);
}
// Check if the required fields are set
$id = $response->getRequestParameter('id');
// Make sure the id is a number
if (!is_numeric($id)) {
$response->error('id parameter must be a number got: ' . $id, 400);
}
// Make sure the user is allowed to delete the booking
if (!$user->hasAccessToBooking($id)) {
$response->error('You are not allowed to delete this booking', 400);
}
// Delete the booking
(new bookings_o())->delete($id);
// Return success
$response->success(
["message" => "Booking deleted"]
);
},
[
'delete_booking' => 'Delete a booking'
]
);
$this->post('/superuser/bookings/sync/all', function () {
// Require the user to be logged in
global /** @var response $response */
$response;
$this->requirePermission('sync_all_bookings');
// Get the user object
$user = (new authentication())->get_user();
// Check if the request was successful
if (!$user->exists()) {
$response->error('User not found', 400);
}
// Log the incident
(new logs_o())->add('bookings', 'global', 1, $user->id, 'SYNC_ALL_BOOKINGS', 'Successfully synced all bookings');
// Sync all bookings
(new bookings_o())->syncBookings();
// Return success
$response->success(
["message" => "All bookings synced"]
);
},
[
'sync_all_bookings' => 'Sync all bookings from the external system'
]
);
$this->post('/admin/bookings/completeWashWithoutWashCertificate', function () {
// Require the user to be logged in
global /** @var response $response */
$response;
$this->requirePermission('complete_wash_without_wash_certificate');
// Get the user object
$user = (new authentication())->get_user();
// Check if the request was successful
if (!$user->exists()) {
$response->error('User not found', 400);
}
// Check if the required fields are set
$id = $response->getRequestParameter('id');
// Make sure the id is a number
if (!is_numeric($id)) {
$response->error('id parameter must be a number got: ' . $id, 400);
}
// Make sure the user is allowed to complete the wash without a wash certificate
if (!$user->hasAccessToBooking($id)) {
$response->error('You are not allowed to complete this wash without a wash certificate', 400);
}
// Complete the wash without a wash certificate
(new bookings_o())->completeWashWithoutWashCertificate($id);
// Return success
$response->success(
["message" => "Wash completed without wash certificate"]
);
},
[
'complete_wash_without_wash_certificate' => 'Complete a wash without a wash certificate'
]
);
$this->post('/user/bookings/delete', function () {
// Require the user to be logged in
global /** @var response $response */
$response;
$this->requirePermission('delete_own_booking');
// Get the user object
$user = (new authentication())->get_user();
// Check if the request was successful
if (!$user->exists()) {
$response->error('User not found', 400);
}
// Check if the required fields are set
$id = $response->getRequestParameter('id');
// Make sure the id is a number
if (!is_numeric($id)) {
$response->error('id parameter must be a number got: ' . $id, 400);
}
// Make sure the user is allowed to delete the booking
if (!$user->hasAccessToBooking($id)) {
$response->error('You are not allowed to delete this booking', 400);
}
// Delete the booking
(new bookings_o())->delete($id);
// Return success
$response->success(
["message" => "Booking deleted"]
);
},
[
'delete_own_booking' => 'Delete the users own booking'
]
);
}
}