добавляю все изменения проекта на текущий момент
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Dto\ApiResponseDto;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
class ApiResponder{
|
||||
public $dto;
|
||||
|
||||
|
||||
public function __construct(
|
||||
)
|
||||
{}
|
||||
|
||||
public function success(): JsonResponse
|
||||
{
|
||||
return $this->buildResponse();
|
||||
}
|
||||
|
||||
public function error()
|
||||
{
|
||||
return $this->buildResponse();
|
||||
}
|
||||
|
||||
public function setDto(ApiResponseDto $dto)
|
||||
{
|
||||
$this->dto = $dto;
|
||||
}
|
||||
|
||||
// public function fromDTO(ApiResponseDto $dto)
|
||||
// {
|
||||
// return $dto;
|
||||
// }
|
||||
|
||||
#Гаврилов
|
||||
//СБОР СТАТИСТИКИ ПО ВЫЗЫВАЕМЫМ API ЕНДПОИНТАМ. ВНЕСТИ В TODO ПРОЕКТА
|
||||
private function setStatistics()
|
||||
{
|
||||
}
|
||||
|
||||
#Гаврилов
|
||||
//ДОБАВЬ ЛОГИРОВАНИЕ ОШИБОК В TRY CATCH В .LOG ФАЙЛ
|
||||
|
||||
private function buildResponse(): JsonResponse
|
||||
{
|
||||
//echo '<pre>'; var_dump((array)$this->dto); echo'</pre>';
|
||||
//return (array) $this->dto;
|
||||
return response()->json((array) $this->dto);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\MagicApps;
|
||||
use App\Facades\UserContext;
|
||||
|
||||
class AuthorizationService
|
||||
{
|
||||
private $appWithRoles;
|
||||
|
||||
|
||||
/**
|
||||
* Получаем приложения вместе с ролями
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getUserAppPermissions(): array
|
||||
{
|
||||
$this->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();
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/**Сервис для определения модуля
|
||||
@author dgavrilov
|
||||
*/
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
class ModuleService{
|
||||
/**
|
||||
* Получаем имя модуля из роута (так как в нем обязательно указывается префикс)
|
||||
*
|
||||
* @return string | null
|
||||
*/
|
||||
public function getModuleName(): string | null
|
||||
{
|
||||
$route = request()->route();
|
||||
$routePrefix = null;
|
||||
if ($route && $route->getPrefix()) {
|
||||
$routePrefix = explode('/', $route->getPrefix())[1];
|
||||
}
|
||||
|
||||
return $routePrefix;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Основываясь на имени модуля из роута получаем имя роута на русском (свойство name_ru), которое обязательное прописывается в конфиге модуля
|
||||
*
|
||||
* @return string | null
|
||||
*/
|
||||
public function getRuModuleName(): string | null
|
||||
{
|
||||
if ($module = $this->getModuleName()) {
|
||||
return config("$module.name_ru", null);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
/**
|
||||
* Базовый класс для работы с Redis в контексте модульной структуры платформы
|
||||
*/
|
||||
abstract class RedisBaseService
|
||||
{
|
||||
/**
|
||||
* @var string базовое подключение к Redis. Руками не прописывается, устанавливается в конструкторе дочернего сервиса через недоступный из фасада метод protected connection(). Сделано это, чтобы разработчик не указывал вручную подключение каждый раз b при этом любой дочерний сервис был обязан прописывать подключение
|
||||
*/
|
||||
protected string $connection;
|
||||
/**
|
||||
* @var int базовый ttl для данных с ограниченным сроком жизни
|
||||
*/
|
||||
public int $ttl = 600;
|
||||
/**
|
||||
* @var string имя модуля/приложения откуда отправляются данные. Передается в инициилизирующем методе module(). Значение '' означает, что данные отправляются из корня проекта, не из модуля
|
||||
*/
|
||||
public string $moduleName;
|
||||
|
||||
|
||||
/**
|
||||
* Метод установки подключения к Redis. В какую БД кладем данные
|
||||
*
|
||||
* @param string $connection имя подключения
|
||||
* @return void
|
||||
*/
|
||||
abstract protected function connection(string $connection): void;
|
||||
|
||||
|
||||
/**
|
||||
* Инициилизирующий метод фасада, принимающий аргумент в виде названия модуля, откуда планируется отправить данные.
|
||||
*
|
||||
* @param string $moduleName имя модуля, откуда передаются данные. Аргумент можно не передавать, если данные передаются из корня ларавель
|
||||
* @return self
|
||||
*/
|
||||
public function module(string $moduleName = ''): self
|
||||
{
|
||||
$this->moduleName = $moduleName;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Меняем ttl данных
|
||||
*
|
||||
* @param int $ttl время жизни записи с данными
|
||||
* @return self
|
||||
*/
|
||||
public function ttl(int $ttl): self
|
||||
{
|
||||
$this->ttl = $ttl;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Возвращает часть префикса ключа redis для хранения информации, отправленной из модуля
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getModuleRedisPrefix(): string
|
||||
{
|
||||
return "_" . $this->moduleName . ":";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Реализация размещения данных в Redis
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
abstract public function put(): void;
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use Illuminate\Support\Facades\Redis;
|
||||
use App\Facades\UserContext;
|
||||
use Exception;
|
||||
|
||||
class RedisNotificationService extends RedisBaseService
|
||||
{
|
||||
protected string $connection = 'notifications';
|
||||
/**
|
||||
* @var array тексты уведомлений
|
||||
*/
|
||||
public array $notificationTexts = [];
|
||||
/**
|
||||
* @var array тексты нотификаций
|
||||
*/
|
||||
public array $notificationTypes = [];
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->connection('notifications');
|
||||
}
|
||||
|
||||
|
||||
protected function connection($connection): void
|
||||
{
|
||||
$this->connection = $connection;
|
||||
//Предполагается, что время жизни должно быть небольшое, так уведомления размещаются перед самим редиректом для их демонстрации пользователю как можно скорее
|
||||
$this->ttl = 180;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Метод возвращает id юзера, который является обязательной частью ключа в БД redis с нотификациями
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function identifyUser(): int
|
||||
{
|
||||
$userId = UserContext::getUserId();
|
||||
|
||||
return $userId;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Устанавливаем текст уведомлений для отправки в Redis
|
||||
*
|
||||
* @param array $notificationTexts массив текстов уведомлений
|
||||
* @return self
|
||||
*/
|
||||
public function notifications(array $notificationTexts): self
|
||||
{
|
||||
$this->notificationTexts = $notificationTexts;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Устанавливаем типы для передаваемых Redis уведомлений
|
||||
*
|
||||
* @param array $notificationTypes типы уведомлений
|
||||
* @return self
|
||||
*/
|
||||
public function types(array $notificationTypes): self
|
||||
{
|
||||
//Если при передаче типов уведомлений не указаны тексты уведомлений, либо если количество текстов уведомлений не равно количеству типов уведомлений, возвращаем ошибку
|
||||
if (empty($this->notificationTexts)) {
|
||||
throw new Exception('Не переданы тексты уведомлений');
|
||||
}
|
||||
if (count($this->notificationTexts) !== count($notificationTypes)) {
|
||||
throw new Exception('Количество переданных типов должно совпадать с количеством текстов уведомлений');
|
||||
}
|
||||
if ($incorrectTypes = array_diff($notificationTypes, config('app.FRONT_notification_types'))) {
|
||||
throw new Exception('Переданные типы уведомлений ' . implode(', ', $incorrectTypes) . ' не существуют');
|
||||
}
|
||||
$this->notificationTypes = $notificationTypes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function put(): void
|
||||
{
|
||||
$notificationsRedis = [];
|
||||
if (empty($this->notificationTexts) || empty($this->notificationTypes)) {
|
||||
throw new Exception('Отсутствуют обязательные параметры для отправки в Redis');
|
||||
} else {
|
||||
foreach ($this->notificationTexts as $key => $text) {
|
||||
$notificationsRedis[] = ['text' => $text, 'type' => $this->notificationTypes[$key]];
|
||||
}
|
||||
}
|
||||
Redis::connection($this->connection)->setex($this->getModuleRedisPrefix() . "notifications:user:" . $this->identifyUser(), $this->ttl, json_encode($notificationsRedis));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Сервис работы с данными юзера (установка/получение логина, групп, подмена значений в случае работы на тестовой среде)
|
||||
*/
|
||||
class UserService
|
||||
{
|
||||
/**
|
||||
* @var string пользовательский логин
|
||||
*/
|
||||
public string $userLogin;
|
||||
/**
|
||||
* @var array пользовательские группы AD
|
||||
*/
|
||||
public array $userADGroups;
|
||||
/**
|
||||
* @var array почтовые рассылки куда входит пользователь
|
||||
*/
|
||||
public array $userEmails;
|
||||
/**
|
||||
* @var boolean является ли пользователь админом приложения Magic
|
||||
*/
|
||||
public bool $isAdmin;
|
||||
/**
|
||||
* @var array доступы пользователя к приложениям
|
||||
*/
|
||||
public array $userAppPermissions;
|
||||
/**
|
||||
* @var int идентификатор пользователя из таблицы users
|
||||
*/
|
||||
public int $userId;
|
||||
|
||||
/**
|
||||
* Установка пользовательского логина
|
||||
*
|
||||
* @param string $login логин для подмены превоначального значения, взятого из сессии
|
||||
* @return void
|
||||
*/
|
||||
public function setUserLogin(string $login): void
|
||||
{
|
||||
$this->userLogin = $login;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Установка пользовательского логина
|
||||
*
|
||||
* @param array $appRoles доступы пользователя к приложениям Magic
|
||||
* @return void
|
||||
*/
|
||||
public function setUserAppPermissions(array $appRoles): void
|
||||
{
|
||||
$this->userAppPermissions = $appRoles;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Установка пользовательского идентификатора из таблицы users
|
||||
*
|
||||
* @param int $userId идентификатор пользователя
|
||||
* @return void
|
||||
*/
|
||||
public function setUserId(int $userId): void
|
||||
{
|
||||
$this->userId = $userId;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Установка групп AD пользователя
|
||||
*
|
||||
* @param array $userGroups все группы из AD где состоит пользователь (emails, AD и т.д.)
|
||||
* @return void
|
||||
*/
|
||||
public function setUserADGroups(array $userGroups): void
|
||||
{
|
||||
$this->userADGroups = array_filter($userGroups, function($el){return substr($el, 0, 1) !== '#';});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Установка почтовых рассылок куда входит пользователь
|
||||
*
|
||||
* @param array $userGroups все групы пользователя AD, в которых он состоит (почтовые ящики, AD и т.д.)
|
||||
* @return void
|
||||
*/
|
||||
public function setUserEmails(array $userGroups): void
|
||||
{
|
||||
$this->userEmails = array_filter($userGroups, function($el){return substr($el, 0, 1) === '#';});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Устанавливаем флаг является ли пользователь админом приложения Magic
|
||||
*
|
||||
* @param boolean $flag
|
||||
* @return void
|
||||
*/
|
||||
public function setIsAdminFlag(bool $flag): void
|
||||
{
|
||||
$this->isAdmin = $flag;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Добавление группы AD в массив групп пользователя
|
||||
*
|
||||
* @param string $group группа для добавления в массив установленных при аутентификации групп AD пользователя
|
||||
* @return void
|
||||
*/
|
||||
public function addUserADGroup(string $group): void
|
||||
{
|
||||
$this->userADGroups[] = $group;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Добавление email в массив емейлов пользователя
|
||||
*
|
||||
* @param string $email почтовая рассылка для добавления в массив установленных при аутентификации почтовых ящиков пользователя
|
||||
* @return void
|
||||
*/
|
||||
public function addUserEmail(string $email): void
|
||||
{
|
||||
$this->userEmails[] = $email;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Возвращаем доступы пользователя к приложениям Magic
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getUserAppPermissions(): array
|
||||
{
|
||||
return $this->userAppPermissions;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Получаем пользовательский логин
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserLogin(): string
|
||||
{
|
||||
return $this->userLogin;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Получаем пользовательский логин
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getUserId(): int
|
||||
{
|
||||
return $this->userId;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Получаем пользовательский логин
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getUserADGroups(): array
|
||||
{
|
||||
return $this->userADGroups;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Получаем email рассылки куда он входит
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getUserEmails(): array
|
||||
{
|
||||
return $this->userEmails;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Получаем значение флага является ли пользователь админом приложения Magic
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function getIsAdminFlag(): bool
|
||||
{
|
||||
return $this->isAdmin;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user