diff --git a/services/nginx/app/modules/subusers/classes/subuser_user_grant.php b/services/nginx/app/modules/subusers/classes/subuser_user_grant.php new file mode 100644 index 00000000..c1231de2 --- /dev/null +++ b/services/nginx/app/modules/subusers/classes/subuser_user_grant.php @@ -0,0 +1,59 @@ +subuser_id = $subuser_id; + $this->customer_number = $customer_number; + // Get the grants and enable the permission nodes based on the grants + $this->loadGrants(); + } + + public function loadGrants(): void + { + $subuser_grants_o = new subuser_grants_o(); + $subuser_grants = $subuser_grants_o->getGrantsForSubuserAndCustomer($this->subuser_id, $this->customer_number); + // Loop through the permissions and enable the corresponding permission nodes + foreach ($subuser_grants as $permission) { + $this->enablePermissionNode($permission); + } + } + + private function enablePermissionNode(string $permission): void + { + // Get all properties extending the subusers_permission_nodes class + $reflection = new \ReflectionClass($this); + $properties = $reflection->getProperties(); + foreach ($properties as $property) { + $propertyType = $property->getType(); + if ($propertyType && is_a($propertyType->getName(), subusers_permission_nodes::class, true)) { + $permissionNodes = $property->getValue($this); + if (is_array($permissionNodes)) { + foreach ($permissionNodes as $node) { + if ($node->nodeKey->name === $permission) { + $node->value = true; + return; + } + } + } + } + } + } +} \ No newline at end of file diff --git a/services/nginx/app/modules/subusers/classes/subusers_permission_node.php b/services/nginx/app/modules/subusers/classes/subusers_permission_node.php new file mode 100644 index 00000000..5521a77a --- /dev/null +++ b/services/nginx/app/modules/subusers/classes/subusers_permission_node.php @@ -0,0 +1,53 @@ +nodeKey = $nodeKey; + $this->name = $name; + $this->description = $description; + $this->type = $type; + $this->value = $value; + } +} \ No newline at end of file diff --git a/services/nginx/app/modules/subusers/classes/subusers_permission_nodes.php b/services/nginx/app/modules/subusers/classes/subusers_permission_nodes.php new file mode 100644 index 00000000..fe0a2613 --- /dev/null +++ b/services/nginx/app/modules/subusers/classes/subusers_permission_nodes.php @@ -0,0 +1,11 @@ +subuserId = $subuserId; + return $subuser; + } + + /** + * Get a subuser by their username. + * @param string $username + * @return subusers_user + * @throws Exception If there was an error getting the subuser by username or if the subuser does not exist + */ + public static function byUsername(string $username): subusers_user + { + return self::bySubuserId((new subusers_o())->getSubuserByUsername($username)->id); + } + + /** + * Get a subuser by their session token. + * @param string $token + * @return subusers_user|null + * @throws Exception If there was an error getting the subuser by session token + */ + public static function bySessionToken(string $token): ?subusers_user + { + $subusers_o = new subusers_o(); + $subusers_o->getSubuserBySessionToken($token); + return self::bySubuserId($subusers_o->id); + } +} \ No newline at end of file diff --git a/services/nginx/app/modules/subusers/helpers/subusers_permission_node_key.php b/services/nginx/app/modules/subusers/helpers/subusers_permission_node_key.php new file mode 100644 index 00000000..26d672fc --- /dev/null +++ b/services/nginx/app/modules/subusers/helpers/subusers_permission_node_key.php @@ -0,0 +1,61 @@ + subusers_permission_node_key::VEHICLES_LIST, + 'VEHCILES_EDIT' => subusers_permission_node_key::VEHICLES_EDIT, + 'VEHCILES_DELETE' => subusers_permission_node_key::VEHICLES_DELETE, + 'VEHCILES_ADD' => subusers_permission_node_key::VEHICLES_ADD, + /** Self-Serve */ + 'SELFSERVE_ADD' => subusers_permission_node_key::SELFSERVE_ADD, + /** Bookings */ + 'BOOKINGS_LIST' => subusers_permission_node_key::BOOKINGS_LIST, + 'BOOKINGS_EDIT' => subusers_permission_node_key::BOOKINGS_EDIT, + 'BOOKINGS_DELETE' => subusers_permission_node_key::BOOKINGS_DELETE, + 'BOOKINGS_ADD' => subusers_permission_node_key::BOOKINGS_ADD, + /** Orders */ + 'ORDERS_LIST' => subusers_permission_node_key::ORDERS_LIST, + 'ORDERS_EDIT' => subusers_permission_node_key::ORDERS_EDIT, + /** Subusers */ + 'SUBUSERS_LIST' => subusers_permission_node_key::SUBUSERS_LIST, + 'SUBUSERS_EDIT' => subusers_permission_node_key::SUBUSERS_EDIT, + 'SUBUSERS_DELETE' => subusers_permission_node_key::SUBUSERS_DELETE, + 'SUBUSERS_ADD' => subusers_permission_node_key::SUBUSERS_ADD, + default => null, + }; + } + + public function equals(subusers_permission_node_key $param): bool + { + return $this === $param; + } + +} diff --git a/services/nginx/app/modules/subusers/helpers/subusers_permission_type.php b/services/nginx/app/modules/subusers/helpers/subusers_permission_type.php new file mode 100644 index 00000000..51ea25d5 --- /dev/null +++ b/services/nginx/app/modules/subusers/helpers/subusers_permission_type.php @@ -0,0 +1,28 @@ + subusers_permission_type::ADD, + 'EDIT' => subusers_permission_type::EDIT, + 'DELETE' => subusers_permission_type::DELETE, + 'VIEW' => subusers_permission_type::VIEW, + default => null, + }; + } + + public function equals(subusers_permission_type $param): bool + { + return $this === $param; + } + +} diff --git a/services/nginx/app/modules/subusers/interfaces/subusers_permission_node_i.php b/services/nginx/app/modules/subusers/interfaces/subusers_permission_node_i.php new file mode 100644 index 00000000..58520d9f --- /dev/null +++ b/services/nginx/app/modules/subusers/interfaces/subusers_permission_node_i.php @@ -0,0 +1,7 @@ +addNode(subusers_permission_node_key::BOOKINGS_LIST, 'List Bookings', 'Allows the user to view the list of bookings', subusers_permission_type::VIEW, false); + $this->addNode(subusers_permission_node_key::BOOKINGS_EDIT, 'Edit Bookings', 'Allows the user to edit existing bookings', subusers_permission_type::EDIT, false); + $this->addNode(subusers_permission_node_key::BOOKINGS_DELETE, 'Delete Bookings', 'Allows the user to delete existing bookings', subusers_permission_type::DELETE, false); + $this->addNode(subusers_permission_node_key::BOOKINGS_ADD, 'Add Bookings', 'Allows the user to add new bookings', subusers_permission_type::ADD, false); + } +} \ No newline at end of file diff --git a/services/nginx/app/modules/subusers/permissions/subusers_permission_nodes_orders.php b/services/nginx/app/modules/subusers/permissions/subusers_permission_nodes_orders.php new file mode 100644 index 00000000..f7dd417a --- /dev/null +++ b/services/nginx/app/modules/subusers/permissions/subusers_permission_nodes_orders.php @@ -0,0 +1,21 @@ +addNode(subusers_permission_node_key::ORDERS_LIST, 'View Orders', 'Allows the user to view the list of orders and order details', subusers_permission_type::VIEW, false); + $this->addNode(subusers_permission_node_key::ORDERS_EDIT, 'Edit Orders', 'Allows the user to edit existing orders', subusers_permission_type::EDIT, false); + } +} \ No newline at end of file diff --git a/services/nginx/app/modules/subusers/permissions/subusers_permission_nodes_selfserve.php b/services/nginx/app/modules/subusers/permissions/subusers_permission_nodes_selfserve.php new file mode 100644 index 00000000..8a8fe2cc --- /dev/null +++ b/services/nginx/app/modules/subusers/permissions/subusers_permission_nodes_selfserve.php @@ -0,0 +1,20 @@ +addNode(subusers_permission_node_key::SELFSERVE_ADD, 'Self Serve Add', 'Add self serve', subusers_permission_type::ADD, false); + } +} \ No newline at end of file diff --git a/services/nginx/app/modules/subusers/permissions/subusers_permission_nodes_subusers.php b/services/nginx/app/modules/subusers/permissions/subusers_permission_nodes_subusers.php new file mode 100644 index 00000000..5a945005 --- /dev/null +++ b/services/nginx/app/modules/subusers/permissions/subusers_permission_nodes_subusers.php @@ -0,0 +1,23 @@ +addNode(subusers_permission_node_key::SUBUSERS_LIST, 'List Subusers', 'Allows the user to view the list of subusers', subusers_permission_type::VIEW, false); + $this->addNode(subusers_permission_node_key::SUBUSERS_EDIT, 'Edit Subusers', 'Allows the user to edit existing subusers', subusers_permission_type::EDIT, false); + $this->addNode(subusers_permission_node_key::SUBUSERS_DELETE, 'Delete Subusers', 'Allows the user to delete existing subusers', subusers_permission_type::DELETE, false); + $this->addNode(subusers_permission_node_key::SUBUSERS_ADD, 'Add Subusers', 'Allows the user to add new subusers', subusers_permission_type::ADD, false); + } +} \ No newline at end of file diff --git a/services/nginx/app/modules/subusers/permissions/subusers_permission_nodes_vehicles.php b/services/nginx/app/modules/subusers/permissions/subusers_permission_nodes_vehicles.php new file mode 100644 index 00000000..6bc72117 --- /dev/null +++ b/services/nginx/app/modules/subusers/permissions/subusers_permission_nodes_vehicles.php @@ -0,0 +1,23 @@ +addNode(subusers_permission_node_key::VEHICLES_LIST, 'Vehicles List', 'View vehicles list', subusers_permission_type::VIEW, false); + $this->addNode(subusers_permission_node_key::VEHICLES_EDIT, 'Vehicles Edit', 'Edit vehicles', subusers_permission_type::EDIT, false); + $this->addNode(subusers_permission_node_key::VEHICLES_DELETE, 'Vehicles Delete', 'Delete vehicles', subusers_permission_type::DELETE, false); + $this->addNode(subusers_permission_node_key::VEHICLES_ADD, 'Vehicles Add', 'Add vehicles', subusers_permission_type::ADD, false); + } +} \ No newline at end of file diff --git a/services/nginx/app/modules/subusers/traits/subuser_user_grant_t.php b/services/nginx/app/modules/subusers/traits/subuser_user_grant_t.php new file mode 100644 index 00000000..5da6b993 --- /dev/null +++ b/services/nginx/app/modules/subusers/traits/subuser_user_grant_t.php @@ -0,0 +1,8 @@ +group_name = $group_name; + $this->description = $description; + } + /** + * @var subusers_permission_node[] + */ + public array $nodes = []; + + /** + * @param subusers_permission_node_key $nodeKey + * @param string $name + * @param string $description + * @param subusers_permission_type $type + * @param bool $value + * @return void + */ + public function addNode(subusers_permission_node_key $nodeKey, string $name, string $description, subusers_permission_type $type, bool $value): void + { + $this->nodes[$nodeKey->name] = new subusers_permission_node($nodeKey, $name, $description, $type, $value); + } + + public function getNode(subusers_permission_node_key $nodeKey): ?subusers_permission_node + { + return $this->nodes[$nodeKey->name] ?? null; + } + + public function getNodeByKey(string $nodeKey): ?subusers_permission_node + { + return $this->nodes[$nodeKey] ?? null; + } + + public function getNodeByName(string $nodeKey): ?subusers_permission_node + { + return $this->nodes[$nodeKey] ?? null; + } +} + diff --git a/services/nginx/app/modules/subusers/traits/subusers_user_permissions_t.php b/services/nginx/app/modules/subusers/traits/subusers_user_permissions_t.php new file mode 100644 index 00000000..0074fd1a --- /dev/null +++ b/services/nginx/app/modules/subusers/traits/subusers_user_permissions_t.php @@ -0,0 +1,39 @@ +getObjectProperties(); return $this; } + + public function getGrantsForSubuserAndCustomer(int $subuser_id, int $customer_number): array + { + $grants = self::getFieldsWhere([ + 'billing_customer_number' => $customer_number, + 'subuser' => $subuser_id, + 'enabled' => 1, + 'deleted_at' => null, + ], ['permissions']); + // Extract permissions from the grants + $permissions = []; + foreach ($grants as $grant) { + $grant_permissions = json_decode($grant['permissions'], true); + if (is_array($grant_permissions)) { + $permissions = array_merge($permissions, $grant_permissions); + } + } + return $permissions; + } } \ No newline at end of file diff --git a/services/nginx/app/objects/subusers_o.php b/services/nginx/app/objects/subusers_o.php index ec7d6ae8..6e410ef4 100644 --- a/services/nginx/app/objects/subusers_o.php +++ b/services/nginx/app/objects/subusers_o.php @@ -230,4 +230,22 @@ class subusers_o extends db $this->setCachedExpiration('session_token:' . $session_token, 7 * 24 * 60 * 60, 'subuser_sessions'); // Set the session to expire after 7 days return $session_token; } + + /** + * @param string $token The session token + * @return subusers_o|null The subuser object or null if the token is invalid or expired + * @throws Exception + */ + public function getSubuserBySessionToken(string $token): ?subusers_o + { + $cache_key = 'session_token:' . $token; + $cache_object_id = 'subuser_sessions'; + $subuser_id = $this->getCached($cache_key, $cache_object_id); + if ($subuser_id === null) { + return null; + } + $subuser = (new subusers_o())->select((int)$subuser_id); + $subuser->getObjectProperties(); + return $subuser; + } } \ No newline at end of file diff --git a/services/nginx/app/routes/subuserGrantsRoute.php b/services/nginx/app/routes/subuserGrantsRoute.php new file mode 100644 index 00000000..d634dee1 --- /dev/null +++ b/services/nginx/app/routes/subuserGrantsRoute.php @@ -0,0 +1,24 @@ +