diff --git a/app/Providers/AuthorizationServiceProvider.php b/app/Providers/AuthorizationServiceProvider.php new file mode 100644 index 0000000..d833d37 --- /dev/null +++ b/app/Providers/AuthorizationServiceProvider.php @@ -0,0 +1,30 @@ +app->bind(AuthorizationService::class, function($app) { + return new AuthorizationService(); + }); + } + + /** + * Bootstrap services. + */ + public function boot(): void + { + // + } +} diff --git a/app/Services/AuthorizationService.php b/app/Services/AuthorizationService.php new file mode 100644 index 0000000..640a3c2 --- /dev/null +++ b/app/Services/AuthorizationService.php @@ -0,0 +1,86 @@ +appWithRoles = MagicApps::with('appRoles')->get()->toArray(); + //Итоговый массив с доступами пользователя к приложению и ролью + $userAppAccess = []; + foreach ($this->appWithRoles as $appData) { + //Определяем по какому массиву проверять доступ к приложению - почтовые рассылки или группы AD + if (empty($appData['access_groups_email'])) { + $appAccess = explode(';', $appData['access_groups_ad']); + $userAccessGroups = UserContext::getUserADGroups(); + } else { + $appAccess = explode(';', $appData['access_groups_email']); + $userAccessGroups = UserContext::getUserEmails(); + } + //Если пересечения групп доступа приложения и групп доступа пользователя отсутствуют, считаем, что доступа нет + if (empty(array_intersect($appAccess, $userAccessGroups))) { + continue; + } + //Если ролевая модель отсутствует для приложения как таковая, прописывам значение null + if (empty($appData['app_roles'])) { + $userAppAccess[$appData['app_name']] = null; + } else { + //Если ролевая модель существует, ставим значение false, которое будет заменено ролью пользователя. Сохранение false на выходе, в свою очередь, сигнализирует, что роль пользователя не определилась + $userAppAccess[$appData['app_name']] = false; + foreach ($appData['app_roles'] as $roleData) { + if($this->checkRoleAccess($appData['role_driver'], explode(';', $roleData['role_access']))) { + $userAppAccess[$appData['app_name']] = $roleData['app_role']; + //Все роли идут по приоритету важности, поэтому останавливаемся на самой важной и возвращаем ее, остальные роли не перебираем. Я пока не уверен как лучше организовать отображение функционала ролей в приложениях: весь нужный функционал "класть" в одну роль и отображать строго тот функционал, который относится к роли. Или распределять функционал между ролями и, если пользователь входит в несколько ролей, отображать весь функционал всех ролей, куда он может входить. В случае последнего варианта, нужно будет хранить все доступные роли пользователя, а не только самую важную по приортету. + //Также пока непонятно, реализовывать ли возможность переключаться между ролями на продакшн среде. Если реализовывать, так же придется хранить все роли, куда входит пользователь. Но в этом случае есть риски запутаться в логировании, например, если пользователь под ролью админ переключится на пользователя юзер и совершит от него действие + break; + } + } + } + } + return $userAppAccess; + } + + + /** + * Возвращаем результат проверки доступности роли + * + * @param string $roleAccessDriver название драйвера доступа роли + * @param array $roleData массив с перечисленными рассылками/логинами/группами, которым доступна роль + * @return bool + */ + public function checkRoleAccess(string $roleAccessDriver, array $roleData): bool + { + switch ($roleAccessDriver) { + case 'login': + return in_array(UserContext::getUserLogin(), $roleData); + break; + case 'email': + return !empty(array_intersect(UserContext::getUserEmails(), $roleData)); + break; + case 'ADgroup': + return !empty(array_intersect(UserContext::getUserADGroups(), $roleData)); + break; + } + } + + //УДАЛИТЬ + // public function getUserAppRoles(array $userGroups) + // { + // $userEmails = session()->get('_auth_groups'); + // $userLogin = session()->get('_auth_login'); + // $magicApps = $this->getAppRoles(); + // } + +}