From b5db913c249d59455fd307b1f1b93b1213bb5362 Mon Sep 17 00:00:00 2001 From: Leonid Nikitin Date: Tue, 5 Dec 2023 00:53:04 +0600 Subject: [PATCH] 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. --- .env.example | 4 ++++ app/Helpers/Helpers.php | 15 +++++++++++++++ app/Providers/AppServiceProvider.php | 6 ++++++ app/Services/Private/ProfileService.php | 9 +++++++++ app/Services/Private/UserService.php | 13 +++++++++++++ config/app.php | 12 ++++++++++++ lang/en.json | 3 ++- lang/ru.json | 3 ++- resources/views/private/layout/app.blade.php | 2 +- resources/views/public/login.blade.php | 5 +++-- 10 files changed, 67 insertions(+), 5 deletions(-) diff --git a/.env.example b/.env.example index 34962e9..b4cc4a0 100644 --- a/.env.example +++ b/.env.example @@ -4,6 +4,10 @@ APP_KEY= APP_DEBUG=true APP_URL=http://localhost +APP_DEMO_MODE=false +APP_DEMO_EMAIL= +APP_DEMO_PASSWORD= + APP_DEFAULT_USER_TIMEZONE=UTC # Valid languages: ru | en APP_DEFAULT_LOCALE=ru diff --git a/app/Helpers/Helpers.php b/app/Helpers/Helpers.php index fd28ac2..6f70ee6 100644 --- a/app/Helpers/Helpers.php +++ b/app/Helpers/Helpers.php @@ -2,6 +2,7 @@ namespace App\Helpers; +use App\Models\User; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Collection; @@ -21,4 +22,18 @@ final readonly class Helpers public static function getUserTimeZone() { return auth()->user()?->timezone ?? config('app.user_timezone'); } + + public static function isDemoMode(): bool + { + return config('app.demo_mode', false); + } + + public static function isDemoModeAndUserDenyUpdate(User $user): bool + { + if (self::isDemoMode() !== true) { + return false; + } + + return $user->email === config('app.demo_email'); + } } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 4ad927e..cf4eb71 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -11,6 +11,7 @@ use App\Captcha\Images\Head; use App\Captcha\Images\ImageManager; use App\Captcha\Images\Lines; use App\Contracts\CryptographyContract; +use App\Helpers\Helpers; use App\Services\Api\V1\CaptchaGenerateService; use App\Services\CaptchaToken\CaptchaTokenHandler; use App\Services\CryptographyString; @@ -20,6 +21,7 @@ use App\Services\Search\CreateSearchInstanceCommand; use App\Services\Search\Search; use Illuminate\Contracts\Foundation\Application; use Illuminate\Pagination\Paginator; +use Illuminate\Support\Facades\Blade; use Illuminate\Support\ServiceProvider; use Illuminate\Validation\Rules\Password; @@ -64,6 +66,10 @@ final class AppServiceProvider extends ServiceProvider */ public function boot(): void { + Blade::if('demo', function () { + return Helpers::isDemoMode(); + }); + Password::defaults(function () { $rule = Password::min(8); diff --git a/app/Services/Private/ProfileService.php b/app/Services/Private/ProfileService.php index b1248f4..4860e81 100644 --- a/app/Services/Private/ProfileService.php +++ b/app/Services/Private/ProfileService.php @@ -5,6 +5,7 @@ namespace App\Services\Private; use App\Dto\Request\Private\Profile\Update; use App\Dto\Request\Private\Profile\UpdateSettings; use App\Dto\Request\Private\User\UpdatePassword; +use App\Helpers\Helpers; use App\Models\User; use App\ServiceResults\ServiceResultError; use App\ServiceResults\ServiceResultSuccess; @@ -19,6 +20,10 @@ final class ProfileService extends Service public function update(Update $update, User $user): ServiceResultError | ServiceResultSuccess { + if (Helpers::isDemoModeAndUserDenyUpdate($user)) { + return $this->errValidate(__('Demo Mode')); + } + try { $data = [ 'name' => $update->getName() @@ -33,6 +38,10 @@ final class ProfileService extends Service public function updatePassword(UpdatePassword $update, User $user): ServiceResultError | ServiceResultSuccess { + if (Helpers::isDemoModeAndUserDenyUpdate($user)) { + return $this->errValidate(__('Demo Mode')); + } + try { $this->userCommandHandler->handleUpdatePassword($user, $update->getPassword()); } catch (\Throwable $e) { diff --git a/app/Services/Private/UserService.php b/app/Services/Private/UserService.php index f79a17e..d7d9c9b 100644 --- a/app/Services/Private/UserService.php +++ b/app/Services/Private/UserService.php @@ -5,6 +5,7 @@ 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; @@ -120,6 +121,10 @@ final class UserService extends Service 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')]), @@ -156,6 +161,10 @@ final class UserService extends Service 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) { @@ -178,6 +187,10 @@ final class UserService extends Service 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); diff --git a/config/app.php b/config/app.php index cf96293..9fd6d96 100644 --- a/config/app.php +++ b/config/app.php @@ -30,6 +30,18 @@ return [ 'env' => env('APP_ENV', 'production'), + /* + |-------------------------------------------------------------------------- + | Application Demo Mode + |-------------------------------------------------------------------------- + | + | Enables or disables Demo mode. + | When Demo mode is enabled, it disables the ability to change user. + */ + 'demo_mode' => (bool) env('APP_DEMO_MODE', false), + 'demo_email' => env('APP_DEMO_EMAIL', false), + 'demo_password' => env('APP_DEMO_PASSWORD', false), + /* |-------------------------------------------------------------------------- | Application Debug Mode diff --git a/lang/en.json b/lang/en.json index 12af7a9..b1013aa 100644 --- a/lang/en.json +++ b/lang/en.json @@ -72,5 +72,6 @@ "Captcha User Agent does not match": "The CAPTCHA verification state has been rejected because the User Agent does not match. Please check and ensure that you are using the same User Agent.", "The time for captcha verification has passed": "The time for captcha verification has passed.", "Captcha does not pass verification": "Captcha does not pass verification.", - "Add code to the site": "Add code to the site" + "Add code to the site": "Add code to the site", + "Demo Mode": "!!! Demo Mode !!!" } diff --git a/lang/ru.json b/lang/ru.json index c1fc059..04d4e89 100644 --- a/lang/ru.json +++ b/lang/ru.json @@ -72,5 +72,6 @@ "Captcha User Agent does not match": "Отклонено состояние проверки CAPTCHA, так как User Agent не совпадает. Пожалуйста, проверьте и убедитесь, что вы используете тот же User Agent.", "The time for captcha verification has passed": "Время верификации капчи прошло.", "Captcha does not pass verification": "Капча не проходит проверку.", - "Add code to the site": "Добавьте код на сайт" + "Add code to the site": "Добавьте код на сайт", + "Demo Mode": "!!! Включён демо режим !!!" } diff --git a/resources/views/private/layout/app.blade.php b/resources/views/private/layout/app.blade.php index 53a050b..e486185 100644 --- a/resources/views/private/layout/app.blade.php +++ b/resources/views/private/layout/app.blade.php @@ -56,7 +56,7 @@
- + @demo

{{ __('Demo Mode') }}

@endif