Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
215c8d0fbb |
@@ -112,6 +112,124 @@ class limited_backoffice_service
|
|||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array<string, array{group:string,capability:string}>
|
||||||
|
*/
|
||||||
|
private const ROLE_PERMISSION_CAPABILITIES = [
|
||||||
|
'user' => [
|
||||||
|
'group' => 'account',
|
||||||
|
'capability' => 'sign_in',
|
||||||
|
],
|
||||||
|
'permissions_list_own' => [
|
||||||
|
'group' => 'account',
|
||||||
|
'capability' => 'view_own_permissions',
|
||||||
|
],
|
||||||
|
'list_orders' => [
|
||||||
|
'group' => 'orders',
|
||||||
|
'capability' => 'view_orders',
|
||||||
|
],
|
||||||
|
'add_order' => [
|
||||||
|
'group' => 'orders',
|
||||||
|
'capability' => 'create_orders',
|
||||||
|
],
|
||||||
|
'edit_order' => [
|
||||||
|
'group' => 'orders',
|
||||||
|
'capability' => 'edit_orders',
|
||||||
|
],
|
||||||
|
'delete_order' => [
|
||||||
|
'group' => 'orders',
|
||||||
|
'capability' => 'delete_orders',
|
||||||
|
],
|
||||||
|
'list_order_items' => [
|
||||||
|
'group' => 'orders',
|
||||||
|
'capability' => 'view_order_items',
|
||||||
|
],
|
||||||
|
'add_order_items' => [
|
||||||
|
'group' => 'orders',
|
||||||
|
'capability' => 'create_order_items',
|
||||||
|
],
|
||||||
|
'edit_order_items' => [
|
||||||
|
'group' => 'orders',
|
||||||
|
'capability' => 'update_order_lines',
|
||||||
|
],
|
||||||
|
'delete_order_items' => [
|
||||||
|
'group' => 'orders',
|
||||||
|
'capability' => 'remove_order_lines',
|
||||||
|
],
|
||||||
|
'charge_order' => [
|
||||||
|
'group' => 'orders',
|
||||||
|
'capability' => 'charge_orders',
|
||||||
|
],
|
||||||
|
'list_bookings' => [
|
||||||
|
'group' => 'bookings',
|
||||||
|
'capability' => 'view_department_bookings',
|
||||||
|
],
|
||||||
|
'list_own_bookings' => [
|
||||||
|
'group' => 'bookings',
|
||||||
|
'capability' => 'view_own_bookings',
|
||||||
|
],
|
||||||
|
'edit_bookings' => [
|
||||||
|
'group' => 'bookings',
|
||||||
|
'capability' => 'update_bookings',
|
||||||
|
],
|
||||||
|
'add_booking' => [
|
||||||
|
'group' => 'bookings',
|
||||||
|
'capability' => 'create_bookings',
|
||||||
|
],
|
||||||
|
'complete_bookings' => [
|
||||||
|
'group' => 'bookings',
|
||||||
|
'capability' => 'mark_bookings_complete',
|
||||||
|
],
|
||||||
|
'resend_booking_confirmations' => [
|
||||||
|
'group' => 'bookings',
|
||||||
|
'capability' => 'send_booking_confirmations',
|
||||||
|
],
|
||||||
|
'department_timebookings_entries_get' => [
|
||||||
|
'group' => 'time_bookings',
|
||||||
|
'capability' => 'view_time_booking_entries',
|
||||||
|
],
|
||||||
|
'department_timebookings_entries_post' => [
|
||||||
|
'group' => 'time_bookings',
|
||||||
|
'capability' => 'create_time_booking_entries',
|
||||||
|
],
|
||||||
|
'department_timebookings_entries_put' => [
|
||||||
|
'group' => 'time_bookings',
|
||||||
|
'capability' => 'edit_time_booking_entries',
|
||||||
|
],
|
||||||
|
'statistics_orders_new' => [
|
||||||
|
'group' => 'reports',
|
||||||
|
'capability' => 'view_order_statistics',
|
||||||
|
],
|
||||||
|
'statistics_bookings_new' => [
|
||||||
|
'group' => 'reports',
|
||||||
|
'capability' => 'view_booking_statistics',
|
||||||
|
],
|
||||||
|
self::PERMISSION_ACCESS => [
|
||||||
|
'group' => 'limited_backoffice',
|
||||||
|
'capability' => 'open_limited_backoffice',
|
||||||
|
],
|
||||||
|
self::PERMISSION_MANAGE_PRICES => [
|
||||||
|
'group' => 'limited_backoffice',
|
||||||
|
'capability' => 'manage_department_prices',
|
||||||
|
],
|
||||||
|
self::PERMISSION_MANAGE_EMPLOYEES => [
|
||||||
|
'group' => 'limited_backoffice',
|
||||||
|
'capability' => 'manage_employee_access',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array<int, string>
|
||||||
|
*/
|
||||||
|
private const ROLE_PERMISSION_GROUP_ORDER = [
|
||||||
|
'account',
|
||||||
|
'orders',
|
||||||
|
'bookings',
|
||||||
|
'time_bookings',
|
||||||
|
'reports',
|
||||||
|
'limited_backoffice',
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array<string, bool>
|
* @var array<string, bool>
|
||||||
*/
|
*/
|
||||||
@@ -123,7 +241,7 @@ class limited_backoffice_service
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array<int, array{key:string,label:string,description:string}>
|
* @return array<int, array{key:string,label:string,description:string,permission_groups:array<int,array{key:string,capabilities:array<int,string>}>}>
|
||||||
*/
|
*/
|
||||||
public function rolePresets(): array
|
public function rolePresets(): array
|
||||||
{
|
{
|
||||||
@@ -133,11 +251,45 @@ class limited_backoffice_service
|
|||||||
'key' => $key,
|
'key' => $key,
|
||||||
'label' => $preset['label'],
|
'label' => $preset['label'],
|
||||||
'description' => $preset['description'],
|
'description' => $preset['description'],
|
||||||
|
'permission_groups' => $this->rolePermissionGroups($preset['permissions']),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
return $roles;
|
return $roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<int, string> $permissions
|
||||||
|
* @return array<int, array{key:string,capabilities:array<int,string>}>
|
||||||
|
*/
|
||||||
|
private function rolePermissionGroups(array $permissions): array
|
||||||
|
{
|
||||||
|
$groups = [];
|
||||||
|
foreach ($permissions as $permission) {
|
||||||
|
$capability = self::ROLE_PERMISSION_CAPABILITIES[$permission] ?? null;
|
||||||
|
if ($capability === null) {
|
||||||
|
throw new \RuntimeException('Missing limited backoffice role capability for permission: ' . $permission);
|
||||||
|
}
|
||||||
|
|
||||||
|
$group = $capability['group'];
|
||||||
|
$groups[$group] ??= [];
|
||||||
|
$groups[$group][] = $capability['capability'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$payload = [];
|
||||||
|
foreach (self::ROLE_PERMISSION_GROUP_ORDER as $group) {
|
||||||
|
if (!isset($groups[$group])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$payload[] = [
|
||||||
|
'key' => $group,
|
||||||
|
'capabilities' => array_values(array_unique($groups[$group])),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $payload;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array<int, int>
|
* @return array<int, int>
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -285,7 +285,54 @@ it('creates updates lists and deactivates scoped employees without exposing raw
|
|||||||
->assertSuccess();
|
->assertSuccess();
|
||||||
|
|
||||||
expect(array_column($roles->data(), 'key'))->toBe(['viewer', 'cashier', 'booking_coordinator', 'operations_lead', 'department_admin']);
|
expect(array_column($roles->data(), 'key'))->toBe(['viewer', 'cashier', 'booking_coordinator', 'operations_lead', 'department_admin']);
|
||||||
|
$rolesByKey = array_column($roles->data(), null, 'key');
|
||||||
|
expect($rolesByKey['viewer']['permission_groups'] ?? null)->toBe([
|
||||||
|
[
|
||||||
|
'key' => 'account',
|
||||||
|
'capabilities' => ['sign_in', 'view_own_permissions'],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
$departmentAdminGroups = array_column($rolesByKey['department_admin']['permission_groups'] ?? [], 'capabilities', 'key');
|
||||||
|
expect($departmentAdminGroups['limited_backoffice'] ?? null)->toBe([
|
||||||
|
'open_limited_backoffice',
|
||||||
|
'manage_department_prices',
|
||||||
|
'manage_employee_access',
|
||||||
|
]);
|
||||||
expect($roles->body)->not->toContain('department_access_');
|
expect($roles->body)->not->toContain('department_access_');
|
||||||
|
$rolePayload = $roles->data();
|
||||||
|
$rolePayloadStrings = [];
|
||||||
|
array_walk_recursive($rolePayload, static function ($value) use (&$rolePayloadStrings): void {
|
||||||
|
if (is_string($value)) {
|
||||||
|
$rolePayloadStrings[] = $value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
foreach ([
|
||||||
|
'list_orders',
|
||||||
|
'add_order',
|
||||||
|
'edit_order',
|
||||||
|
'delete_order',
|
||||||
|
'list_order_items',
|
||||||
|
'add_order_items',
|
||||||
|
'edit_order_items',
|
||||||
|
'delete_order_items',
|
||||||
|
'charge_order',
|
||||||
|
'list_bookings',
|
||||||
|
'list_own_bookings',
|
||||||
|
'edit_bookings',
|
||||||
|
'add_booking',
|
||||||
|
'complete_bookings',
|
||||||
|
'resend_booking_confirmations',
|
||||||
|
'department_timebookings_entries_get',
|
||||||
|
'department_timebookings_entries_post',
|
||||||
|
'department_timebookings_entries_put',
|
||||||
|
'statistics_orders_new',
|
||||||
|
'statistics_bookings_new',
|
||||||
|
'limited_backoffice_access',
|
||||||
|
'limited_backoffice_prices_manage',
|
||||||
|
'limited_backoffice_employees_manage',
|
||||||
|
] as $rawPermission) {
|
||||||
|
expect($rolePayloadStrings)->not->toContain($rawPermission);
|
||||||
|
}
|
||||||
|
|
||||||
$created = api_client()->post('/limited-backoffice/employees', [
|
$created = api_client()->post('/limited-backoffice/employees', [
|
||||||
'display_name' => 'Limited Cashier',
|
'display_name' => 'Limited Cashier',
|
||||||
|
|||||||
Reference in New Issue
Block a user