Extend subuser permission system and refactor route permission handling

- Update `subusersRoute` to support subuser authentication and permission checks dynamically.
- Add new permission nodes (`SELFSERVE_LIST`, `SELFSERVE_EDIT`, `SELFSERVE_DELETE`) in `subusers_permission_node_key`.
- Fix typos in vehicle permission constants and ensure proper resolution.
- Enhance `vehiclesRoute` with effective customer context and scoped permission checks.
- Localize new permission nodes with descriptions in Danish.
This commit is contained in:
Jeppe Bundgaard
2026-02-12 16:26:29 +01:00
parent 19139b08cb
commit 6302fd25df
4 changed files with 46 additions and 10 deletions
@@ -11,6 +11,9 @@ enum subusers_permission_node_key
case VEHICLES_ADD;
/** Self-Serve */
case SELFSERVE_LIST;
case SELFSERVE_EDIT;
case SELFSERVE_DELETE;
case SELFSERVE_ADD;
/** Bookings */
case BOOKINGS_LIST;
@@ -30,11 +33,14 @@ enum subusers_permission_node_key
{
return match (strtoupper($param)) {
/** Vehicles */
'VEHCILES_LIST' => 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,
'VEHICLES_LIST' => subusers_permission_node_key::VEHICLES_LIST,
'VEHICLES_EDIT' => subusers_permission_node_key::VEHICLES_EDIT,
'VEHICLES_DELETE' => subusers_permission_node_key::VEHICLES_DELETE,
'VEHICLES_ADD' => subusers_permission_node_key::VEHICLES_ADD,
/** Self-Serve */
'SELFSERVE_LIST' => subusers_permission_node_key::SELFSERVE_LIST,
'SELFSERVE_EDIT' => subusers_permission_node_key::SELFSERVE_EDIT,
'SELFSERVE_DELETE' => subusers_permission_node_key::SELFSERVE_DELETE,
'SELFSERVE_ADD' => subusers_permission_node_key::SELFSERVE_ADD,
/** Bookings */
'BOOKINGS_LIST' => subusers_permission_node_key::BOOKINGS_LIST,
@@ -15,6 +15,9 @@ class subusers_permission_nodes_selfserve extends subusers_permission_nodes
'Tilladelser til selvbetjening',
);
$this->addNode(subusers_permission_node_key::SELFSERVE_ADD, 'Tilføj selvbetjening', 'Tilføj selvbetjening', subusers_permission_type::ADD, false);
$this->addNode(subusers_permission_node_key::SELFSERVE_LIST, 'Vis selvbetjening', 'Giver brugeren mulighed for at se selvbetjeningsrelaterede oplysninger', subusers_permission_type::VIEW, false);
$this->addNode(subusers_permission_node_key::SELFSERVE_EDIT, 'Rediger selvbetjening', 'Giver brugeren mulighed for at ændre selvbetjeningsrelaterede oplysninger', subusers_permission_type::EDIT, false);
$this->addNode(subusers_permission_node_key::SELFSERVE_DELETE, 'Slet selvbetjening', 'Giver brugeren mulighed for at slette selvbetjeningsrelaterede oplysninger', subusers_permission_type::DELETE, false);
$this->addNode(subusers_permission_node_key::SELFSERVE_ADD, 'Tilføj selvbetjening', 'Giver brugeren mulighed for at tilføje selvbetjeningsrelaterede oplysninger', subusers_permission_type::ADD, false);
}
}
+21 -5
View File
@@ -425,13 +425,29 @@ class subusersRoute
// =============================
$this->get('/subusers', function () {
global $response;
// Require authenticated user
$user = (new authentication())->get_user();
if ($user === false) {
// Require authenticated principal (user or subuser)
$auth = new authentication();
$user = $auth->get_user();
$subuser = $auth->get_subuser();
if ($user === false && $subuser === false) {
$response->error('Unauthorized', 401);
}
$customerNumber = (int)$user->customer_number->value();
if ($customerNumber === 0) {
// Link route permission to Subusers node so subusers can be constrained by grants.
// For classic users we keep current behavior (no extra user permission enforced here).
$permission_list = self::definePermission('list_own_subusers', subusers_permission_node_key::SUBUSERS_LIST);
if ($subuser !== false) {
// Only enforce for subuser principals; classic users are governed by existing user ACLs elsewhere.
self::requirePermission($permission_list);
}
// Determine effective customer number (user's customer number or subuser's target header)
if ($user !== false) {
$customerNumber = (int)$user->customer_number->value();
} else {
$customerNumber = (int)$auth->get_subuser_customer_number_target();
}
if (empty($customerNumber)) {
$response->error('Unauthorized', 401);
}
@@ -57,6 +57,17 @@ class vehiclesRoute
// Listing: restrict to effective customer when lacking the broader permission
$vehicles_o = new customer_vehicles_o();
$effectiveCustomer = self::resolveEffectiveCustomerNumber();
$permitted = self::allowOwnOrDepartmentAccess(
$permission_own,
$permission_other,
$effectiveCustomer,
null,
null,
'You do not have permission to view vehicles.'
);
if (!$permitted) {
$response->error('You do not have permission to view vehicles.');
}
$response->success(
$vehicles_o->listObjectsWithPaginationIfSet(
function ($vehicle) {