]> BookStack Code Mirror - bookstack/blob - app/Access/GroupSyncService.php
Lexical: Fixed code in lists, removed extra old alignment code
[bookstack] / app / Access / GroupSyncService.php
1 <?php
2
3 namespace BookStack\Access;
4
5 use BookStack\Users\Models\Role;
6 use BookStack\Users\Models\User;
7 use Illuminate\Support\Collection;
8
9 class GroupSyncService
10 {
11     /**
12      * Check a role against an array of group names to see if it matches.
13      * Checked against role 'external_auth_id' if set otherwise the name of the role.
14      */
15     protected function roleMatchesGroupNames(Role $role, array $groupNames): bool
16     {
17         if ($role->external_auth_id) {
18             return $this->externalIdMatchesGroupNames($role->external_auth_id, $groupNames);
19         }
20
21         $roleName = str_replace(' ', '-', trim(strtolower($role->display_name)));
22
23         return in_array($roleName, $groupNames);
24     }
25
26     /**
27      * Check if the given external auth ID string matches one of the given group names.
28      */
29     protected function externalIdMatchesGroupNames(string $externalId, array $groupNames): bool
30     {
31         foreach ($this->parseRoleExternalAuthId($externalId) as $externalAuthId) {
32             if (in_array($externalAuthId, $groupNames)) {
33                 return true;
34             }
35         }
36
37         return false;
38     }
39
40     protected function parseRoleExternalAuthId(string $externalId): array
41     {
42         $inputIds = preg_split('/(?<!\\\),/', strtolower($externalId));
43         $cleanIds = [];
44
45         foreach ($inputIds as $inputId) {
46             $cleanIds[] = str_replace('\,', ',', trim($inputId));
47         }
48
49         return $cleanIds;
50     }
51
52     /**
53      * Match an array of group names to BookStack system roles.
54      * Formats group names to be lower-case and hyphenated.
55      */
56     protected function matchGroupsToSystemsRoles(array $groupNames): Collection
57     {
58         foreach ($groupNames as $i => $groupName) {
59             $groupNames[$i] = str_replace(' ', '-', trim(strtolower($groupName)));
60         }
61
62         $roles = Role::query()->get(['id', 'external_auth_id', 'display_name']);
63         $matchedRoles = $roles->filter(function (Role $role) use ($groupNames) {
64             return $this->roleMatchesGroupNames($role, $groupNames);
65         });
66
67         return $matchedRoles->pluck('id');
68     }
69
70     /**
71      * Sync the groups to the user roles for the current user.
72      */
73     public function syncUserWithFoundGroups(User $user, array $userGroups, bool $detachExisting): void
74     {
75         // Get the ids for the roles from the names
76         $groupsAsRoles = $this->matchGroupsToSystemsRoles($userGroups);
77
78         // Sync groups
79         if ($detachExisting) {
80             $user->roles()->sync($groupsAsRoles);
81             $user->attachDefaultRole();
82         } else {
83             $user->roles()->syncWithoutDetaching($groupsAsRoles);
84         }
85     }
86 }