service-captcha/app/Services/Private/UserService.php
Leonid Nikitin b5db913c24
Add demo mode restrictions to user operations.
Added functionalities to restrict certain user operations like update, password change, and deletion in demo mode. This is done to prevent demo users from modifying crucial data. Helper methods are created for standard re-usable checks. Also, Blade directive is added for frontend UI demo checks.
2023-12-05 00:53:04 +06:00

215 lines
7.1 KiB
PHP

<?php declare(strict_types=1);
namespace App\Services\Private;
use App\Dto\Builder\User as UserBuilderDto;
use App\Dto\Request\Private\User\StoreUpdate;
use App\Dto\Request\Private\User\UpdatePassword;
use App\Helpers\Helpers;
use App\Models\User;
use App\Dto\QuerySettingsDto;
use App\Repositories\RoleRepository;
use App\Repositories\UserRepository;
use App\ServiceResults\ServiceResultArray;
use App\ServiceResults\ServiceResultError;
use App\ServiceResults\ServiceResultSuccess;
use App\ServiceResults\StoreUpdateResult;
use App\Services\Service;
use App\Services\User\UserCommandHandler;
use Illuminate\Support\Facades\DB;
final class UserService extends Service
{
public function __construct(
private readonly UserRepository $userRepository,
private readonly UserCommandHandler $userCommandHandler,
private readonly RoleRepository $roleRepository
) { }
public function index(UserBuilderDto $userBuilderDto, QuerySettingsDto $querySettingsDto, User $user): ServiceResultError | ServiceResultArray
{
if ($user->cannot('viewAny', User::class)) {
return $this->errFobidden(__('Access is denied'));
}
$users = $this->userRepository->getUsers(
$userBuilderDto,
$querySettingsDto->getQueryWith()
)->pagination(
$querySettingsDto->getLimit(),
$querySettingsDto->getPage()
);
return $this->result([
'users' => $users,
]);
}
public function create(User $user): ServiceResultError | ServiceResultArray
{
if ($user->cannot('create', User::class)) {
return $this->errFobidden(__('Access is denied'));
}
return $this->result([
'user' => new User(),
'roles' => $this->roleRepository->getRolesForSelect(),
'userRoles' => [],
]);
}
public function edit(int $id, User $user): ServiceResultError | ServiceResultArray
{
$modelUser = $this->userRepository->getUserById($id);
if (is_null($modelUser)) {
return $this->errNotFound(__('Not Found'));
}
if ($user->cannot('view', $modelUser)) {
return $this->errFobidden(__('Access is denied'));
}
$userRoles = $modelUser->roles()->withTrashed()->pluck('id')->toArray();
return $this->result([
'user' => $modelUser,
'roles' => $this->roleRepository->getRolesForSelect($userRoles),
'userRoles' => $userRoles,
]);
}
public function store(StoreUpdate $data, User $user): ServiceResultError | StoreUpdateResult
{
if ($user->cannot('create', User::class)) {
return $this->errFobidden(__('Access is denied'));
}
if ($this->userRepository->isExistsEmail($data->getEmail())) {
return $this->errValidate(
__('validation.unique', ['attribute' => __('validation.attributes.email')]),
['code' => __('validation.unique', ['attribute' => __('validation.attributes.email')])]
);
}
try {
$modelUser = DB::transaction(function () use ($data) {
$dataUser = $this->getDataUser($data);
$modelUser = $this->userCommandHandler->handleStore($dataUser, $data->getPassword());
$this->userCommandHandler->handleConfirmationByEmail($modelUser);
$this->userCommandHandler->handleSyncRoles($modelUser, $data->getRoles());
return $modelUser;
});
} catch (\Throwable $e) {
report($e);
return $this->errService(__('Server Error'));
}
return $this->resultStoreUpdateModel($modelUser, __('The user was successfully created'));
}
public function update(int $id, StoreUpdate $data, User $user): ServiceResultError | StoreUpdateResult
{
$modelUser = $this->userRepository->getUserById($id);
if (is_null($modelUser)) {
return $this->errNotFound(__('Not Found'));
}
if ($user->cannot('update', $modelUser)) {
return $this->errFobidden(__('Access is denied'));
}
if (Helpers::isDemoModeAndUserDenyUpdate($modelUser)) {
return $this->errValidate(__('Demo Mode'));
}
if ($this->userRepository->isExistsEmail($data->getEmail(), $modelUser->id)) {
return $this->errValidate(
__('validation.unique', ['attribute' => __('validation.attributes.email')]),
['code' => __('validation.unique', ['attribute' => __('validation.attributes.email')])]
);
}
try {
$modelUser = DB::transaction(function () use ($data, $modelUser) {
$dataUser = $this->getDataUser($data);
$modelUser = $this->userCommandHandler->handleUpdate($modelUser, $dataUser);
$this->userCommandHandler->handleSyncRoles($modelUser, $data->getRoles());
return $modelUser;
});
} catch (\Throwable $e) {
report($e);
return $this->errService(__('Server Error'));
}
return $this->resultStoreUpdateModel($modelUser, __('The user was successfully updated'));
}
public function updatePassword(int $id, UpdatePassword $data, User $user): ServiceResultError | StoreUpdateResult
{
$modelUser = $this->userRepository->getUserById($id);
if (is_null($modelUser)) {
return $this->errNotFound(__('Not Found'));
}
if ($user->cannot('update', $modelUser)) {
return $this->errFobidden(__('Access is denied'));
}
if (Helpers::isDemoModeAndUserDenyUpdate($modelUser)) {
return $this->errValidate(__('Demo Mode'));
}
try {
$this->userCommandHandler->handleUpdatePassword($modelUser, $data->getPassword());
} catch (\Throwable $e) {
report($e->getMessage());
return $this->errService($e->getMessage());
}
return $this->resultStoreUpdateModel($modelUser, __('The password has been changed'));
}
public function destroy(int $id, User $user): ServiceResultError | ServiceResultSuccess
{
$modelUser = $this->userRepository->getUserById($id);
if (is_null($modelUser)) {
return $this->errNotFound(__('Not Found'));
}
if ($user->cannot('delete', $modelUser)) {
return $this->errFobidden(__('Access is denied'));
}
if (Helpers::isDemoModeAndUserDenyUpdate($modelUser)) {
return $this->errValidate(__('Demo Mode'));
}
try {
DB::transaction(function () use ($modelUser) {
$this->userCommandHandler->handleDestroy($modelUser);
});
} catch (\Throwable $e) {
report($e);
return $this->errService(__('Server Error'));
}
return $this->ok(__('The user has been deleted'));
}
private function getDataUser(StoreUpdate $data): array
{
return [
'is_active' => $data->isActive(),
'name' => $data->getName(),
'email' => $data->getEmail(),
];
}
}