| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | <?php | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-18 00:56:55 +08:00
										 |  |  | namespace BookStack\Access; | 
					
						
							| 
									
										
										
										
											2019-08-07 18:07:21 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-18 00:56:55 +08:00
										 |  |  | use BookStack\Users\Models\Role; | 
					
						
							|  |  |  | use BookStack\Users\Models\User; | 
					
						
							| 
									
										
										
										
											2020-08-04 21:55:01 +08:00
										 |  |  | use Illuminate\Support\Collection; | 
					
						
							| 
									
										
										
										
											2019-08-07 18:07:21 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-07 06:05:26 +08:00
										 |  |  | class GroupSyncService | 
					
						
							| 
									
										
										
										
											2019-08-07 18:07:21 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Check a role against an array of group names to see if it matches. | 
					
						
							|  |  |  |      * Checked against role 'external_auth_id' if set otherwise the name of the role. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2019-11-16 23:24:09 +08:00
										 |  |  |     protected function roleMatchesGroupNames(Role $role, array $groupNames): bool | 
					
						
							| 
									
										
										
										
											2019-08-07 18:07:21 +08:00
										 |  |  |     { | 
					
						
							|  |  |  |         if ($role->external_auth_id) { | 
					
						
							| 
									
										
										
										
											2019-11-16 23:24:09 +08:00
										 |  |  |             return $this->externalIdMatchesGroupNames($role->external_auth_id, $groupNames); | 
					
						
							| 
									
										
										
										
											2019-08-07 18:07:21 +08:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $roleName = str_replace(' ', '-', trim(strtolower($role->display_name))); | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-07 18:07:21 +08:00
										 |  |  |         return in_array($roleName, $groupNames); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-16 23:24:09 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Check if the given external auth ID string matches one of the given group names. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     protected function externalIdMatchesGroupNames(string $externalId, array $groupNames): bool | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-05-05 04:03:13 +08:00
										 |  |  |         foreach ($this->parseRoleExternalAuthId($externalId) as $externalAuthId) { | 
					
						
							|  |  |  |             if (in_array($externalAuthId, $groupNames)) { | 
					
						
							| 
									
										
										
										
											2019-11-16 23:24:09 +08:00
										 |  |  |                 return true; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-05 04:03:13 +08:00
										 |  |  |     protected function parseRoleExternalAuthId(string $externalId): array | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-06-27 21:17:42 +08:00
										 |  |  |         $inputIds = preg_split('/(?<!\\\),/', strtolower($externalId)); | 
					
						
							| 
									
										
										
										
											2022-05-05 04:03:13 +08:00
										 |  |  |         $cleanIds = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach ($inputIds as $inputId) { | 
					
						
							|  |  |  |             $cleanIds[] = str_replace('\,', ',', trim($inputId)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $cleanIds; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-07 18:07:21 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Match an array of group names to BookStack system roles. | 
					
						
							|  |  |  |      * Formats group names to be lower-case and hyphenated. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2020-08-04 21:55:01 +08:00
										 |  |  |     protected function matchGroupsToSystemsRoles(array $groupNames): Collection | 
					
						
							| 
									
										
										
										
											2019-08-07 18:07:21 +08:00
										 |  |  |     { | 
					
						
							|  |  |  |         foreach ($groupNames as $i => $groupName) { | 
					
						
							|  |  |  |             $groupNames[$i] = str_replace(' ', '-', trim(strtolower($groupName))); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-04 21:55:01 +08:00
										 |  |  |         $roles = Role::query()->get(['id', 'external_auth_id', 'display_name']); | 
					
						
							| 
									
										
										
										
											2019-08-07 18:07:21 +08:00
										 |  |  |         $matchedRoles = $roles->filter(function (Role $role) use ($groupNames) { | 
					
						
							|  |  |  |             return $this->roleMatchesGroupNames($role, $groupNames); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $matchedRoles->pluck('id'); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |      * Sync the groups to the user roles for the current user. | 
					
						
							| 
									
										
										
										
											2019-08-07 18:07:21 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-10-07 06:05:26 +08:00
										 |  |  |     public function syncUserWithFoundGroups(User $user, array $userGroups, bool $detachExisting): void | 
					
						
							| 
									
										
										
										
											2019-08-07 18:07:21 +08:00
										 |  |  |     { | 
					
						
							|  |  |  |         // Get the ids for the roles from the names
 | 
					
						
							| 
									
										
										
										
											2019-08-07 21:31:10 +08:00
										 |  |  |         $groupsAsRoles = $this->matchGroupsToSystemsRoles($userGroups); | 
					
						
							| 
									
										
										
										
											2019-08-07 18:07:21 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // Sync groups
 | 
					
						
							| 
									
										
										
										
											2021-10-07 06:05:26 +08:00
										 |  |  |         if ($detachExisting) { | 
					
						
							| 
									
										
										
										
											2019-08-07 21:31:10 +08:00
										 |  |  |             $user->roles()->sync($groupsAsRoles); | 
					
						
							| 
									
										
										
										
											2020-02-03 01:31:00 +08:00
										 |  |  |             $user->attachDefaultRole(); | 
					
						
							| 
									
										
										
										
											2019-08-07 18:07:21 +08:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2019-08-07 21:31:10 +08:00
										 |  |  |             $user->roles()->syncWithoutDetaching($groupsAsRoles); | 
					
						
							| 
									
										
										
										
											2019-08-07 18:07:21 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-10-16 23:01:59 +08:00
										 |  |  | } |