From 73b2cb3fa8d1164a4b14ca021c2da59cd544b700 Mon Sep 17 00:00:00 2001 From: Vincent BRIDIER Date: Fri, 23 Aug 2024 08:22:48 +0200 Subject: [PATCH] Replace BO Auth by SAML --- .env.example | 36 +- app/Console/Commands/UserCreate.php | 31 +- app/Http/Kernel.php | 6 + .../Requests/Bo/Users/StoreUserRequest.php | 10 - .../Requests/Bo/Users/UpdateUserRequest.php | 17 +- app/Models/User.php | 21 - app/Policies/Rules/UserStaticRules.php | 10 +- app/Providers/EventServiceProvider.php | 52 ++ composer.json | 5 +- composer.lock | 515 +++++++++++++++--- config/saml2.php | 397 ++++++++++++++ ...2024_08_22_150017_alter_users_for_saml.php | 32 ++ manifest.yaml | 108 ++-- resources/views/bo/auth/login.blade.php | 56 +- resources/views/bo/layouts/head.blade.php | 4 +- resources/views/bo/pages/dashboard.blade.php | 21 +- .../views/bo/pages/login-error.blade.php | 11 + resources/views/bo/pages/users/form.blade.php | 35 +- resources/views/fo/layouts/head.blade.php | 2 +- .../views/modules/script-constants.blade.php | 2 +- resources/views/vendor/errors/403.blade.php | 1 - routes/web-bo.php | 4 + 22 files changed, 1064 insertions(+), 312 deletions(-) create mode 100644 config/saml2.php create mode 100644 database/migrations/2024_08_22_150017_alter_users_for_saml.php create mode 100644 resources/views/bo/pages/login-error.blade.php diff --git a/.env.example b/.env.example index 3f9ba6b0..2b1558ee 100644 --- a/.env.example +++ b/.env.example @@ -3,7 +3,6 @@ APP_ENV=local APP_KEY= APP_DEBUG=true APP_URL=http://localhost -ASSET_URL=http://localhost LOG_CHANNEL=stack LOG_DEPRECATIONS_CHANNEL=null @@ -38,28 +37,23 @@ MAIL_ENCRYPTION=null MAIL_FROM_ADDRESS="hello@example.com" MAIL_FROM_NAME="${APP_NAME}" -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false - -PUSHER_APP_ID= -PUSHER_APP_KEY= -PUSHER_APP_SECRET= -PUSHER_HOST= -PUSHER_PORT=443 -PUSHER_SCHEME=https -PUSHER_APP_CLUSTER=mt1 - -VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}" -VITE_PUSHER_HOST="${PUSHER_HOST}" -VITE_PUSHER_PORT="${PUSHER_PORT}" -VITE_PUSHER_SCHEME="${PUSHER_SCHEME}" -VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" - # SENTRY SENTRY_LARAVEL_DSN= # MATOMO MATOMO_SITE_ID= + +# ADMIN SECURE +# - API ENDPOINT (Optional) +LDC_WEB_API_ENDPOINT="https://ldc-web.ldc.fr/api/ldc-networks" +# - API KEY +LDC_WEB_API_KEY="" +# - LIST SEPARATED WITH ',' (Optional) +LDC_WEB_CIDR_MANUAL_ALLOWED_LIST="" + +# SAML +SAML2_DEFAULT_TENANT_UUID= +SAML2_SP_CERT_x509= +SAML2_SP_CERT_PRIVATEKEY= +SAML2_CONTACT_TECHNICAL_EMAIL= +SAML2_CONTACT_SUPPORT_EMAIL= diff --git a/app/Console/Commands/UserCreate.php b/app/Console/Commands/UserCreate.php index cedc7733..3dee9e0e 100644 --- a/app/Console/Commands/UserCreate.php +++ b/app/Console/Commands/UserCreate.php @@ -47,13 +47,6 @@ class UserCreate extends Command */ protected $email; - /** - * The password of the new user. - * - * @var string|null - */ - protected $password; - /** * The role of the new user. * @@ -77,9 +70,6 @@ class UserCreate extends Command $this->email = null; $this->addEmail(); - $this->password = null; - $this->addPassword(); - $this->role = null; $this->addRole(); @@ -87,7 +77,6 @@ class UserCreate extends Command 'first_name' => $this->first_name, 'last_name' => $this->last_name, 'email' => $this->email, - 'password' => $this->password, 'role' => $this->role, 'published' => true, 'published_at' => Carbon::now(), @@ -174,22 +163,6 @@ class UserCreate extends Command }; //end while } - /** - * Add a password to the user. - * - * @return void - */ - private function addPassword(): void - { - while ( - ($this->password = $this->secret( - (!\is_null($this->password) ? 'Failed to confirm, ' : '') . 'Type the wanted user password' - )) !== $this->secret('Confirm the password') - ) { - continue; - }; //end while - } - /** * Add a role to the user. * @@ -199,7 +172,7 @@ class UserCreate extends Command { while (is_null($this->role)) { try { - $tmp = $this->choice( + $tmp = $this->choice( 'Select his role', [ Str::ucFirst(RoleEnum::conceptor->label()), @@ -207,8 +180,6 @@ class UserCreate extends Command Str::ucFirst(RoleEnum::visitor->label()) ], Str::ucFirst(RoleEnum::visitor->label()), - $maxAttempts = null, - $allowMultipleSelections = false ); if ($tmp === Str::ucFirst(RoleEnum::conceptor->label())) { $tmp = RoleEnum::conceptor; diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index a5df8875..5860fd5a 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -40,6 +40,12 @@ class Kernel extends HttpKernel \App\Http\Middleware\SecureHeaders::class ], + 'saml' => [ + \App\Http\Middleware\EncryptCookies::class, + \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, + \Illuminate\Session\Middleware\StartSession::class, + ], + 'api' => [ \Illuminate\Routing\Middleware\ThrottleRequests::class . ':api', \Illuminate\Routing\Middleware\SubstituteBindings::class, diff --git a/app/Http/Requests/Bo/Users/StoreUserRequest.php b/app/Http/Requests/Bo/Users/StoreUserRequest.php index 0a9b3235..043e6c70 100644 --- a/app/Http/Requests/Bo/Users/StoreUserRequest.php +++ b/app/Http/Requests/Bo/Users/StoreUserRequest.php @@ -7,7 +7,6 @@ use App\Models\User; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Gate; use Illuminate\Validation\Rules\Enum; -use Illuminate\Validation\Rules\Password; class StoreUserRequest extends FormRequest { @@ -44,14 +43,6 @@ class StoreUserRequest extends FormRequest 'first_name' => 'required|string|min:3|max:255', 'last_name' => 'required|string|min:3|max:255', 'email' => 'required|email:rfc,strict,dns,spoof,filter|unique:users,email', - 'password' => [ - 'required', 'required_with:password_confirmation', 'confirmed', 'max:255', Password::min(8) - ->letters() - ->mixedCase() - ->numbers() - ->symbols() - ->uncompromised() - ], 'role' => ['required', new Enum(RoleEnum::class)], 'published' => 'required|boolean', ]; @@ -68,7 +59,6 @@ class StoreUserRequest extends FormRequest 'first_name' => trans('validation.attributes.first_name'), 'last_name' => trans('validation.attributes.last_name'), 'email' => trans('validation.attributes.email'), - 'password' => trans('validation.attributes.password'), 'role' => trans('validation.attributes.role'), 'published' => trans('validation.custom.publication') ]; diff --git a/app/Http/Requests/Bo/Users/UpdateUserRequest.php b/app/Http/Requests/Bo/Users/UpdateUserRequest.php index 6c587c91..c9de3428 100644 --- a/app/Http/Requests/Bo/Users/UpdateUserRequest.php +++ b/app/Http/Requests/Bo/Users/UpdateUserRequest.php @@ -4,7 +4,6 @@ namespace App\Http\Requests\Bo\Users; use Illuminate\Support\Facades\Gate; use Illuminate\Validation\Rule; -use Illuminate\Validation\Rules\Password; class UpdateUserRequest extends StoreUserRequest { @@ -26,11 +25,7 @@ class UpdateUserRequest extends StoreUserRequest protected function prepareForValidation(): void { $this->merge([ - 'published' => $this->boolean('published'), - 'password' => $this->input('password') ?? - \optional($this->route('user'))->password, - 'password_confirmation' => $this->input('password_confirmation') ?? - \optional($this->route('user'))->password + 'published' => $this->boolean('published') ]); } @@ -46,15 +41,7 @@ class UpdateUserRequest extends StoreUserRequest 'required', 'email:rfc,strict,dns,spoof,filter', Rule::unique('users', 'email')->ignore(\optional($this->route('user'))->getRouteKey()) - ], - 'password' => [ - 'required', 'required_with:password_confirmation', 'confirmed', 'max:255', Password::min(8) - ->letters() - ->mixedCase() - ->numbers() - ->symbols() - ->uncompromised() - ], + ] ]); } } diff --git a/app/Models/User.php b/app/Models/User.php index 12d79ac3..343a9b27 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -8,13 +8,11 @@ use Illuminate\Auth\Access\AuthorizationException; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; -use Illuminate\Support\Facades\Hash; /** * @property string $first_name Firstname. * @property string $last_name Lastname. * @property string $email Email. - * @property string $password Password. * @property \App\Enums\Users\RoleEnum $role Role. * @property bool $published Published status. * @property \Illuminate\Support\Carbon $published_at Publication status update date. @@ -38,7 +36,6 @@ class User extends Authenticatable 'first_name', 'last_name', 'email', - 'password', 'role', 'published', 'published_at', @@ -50,7 +47,6 @@ class User extends Authenticatable * @var array */ protected $hidden = [ - 'password', 'remember_token', ]; @@ -74,7 +70,6 @@ class User extends Authenticatable protected static function booted(): void { static::creating(function (self $model) { - self::updatePassword($model); // * Prevent user elevation privileges throw_if( auth('backend')->user() and auth('backend')->user()->role->value() > $model->role->value(), @@ -82,7 +77,6 @@ class User extends Authenticatable ); }); static::updating(function (self $model) { - self::updatePassword($model); if (optional(auth('backend')->user())->getKey() === $model->getKey()) { \validator( ['published' => $model->published], @@ -98,21 +92,6 @@ class User extends Authenticatable }); } - // * METHODS - - /** - * Update password. - * - * @param self $model - * @return void - */ - private static function updatePassword(self $model): void - { - if (Hash::needsRehash($model->password)) { - $model->password = Hash::make($model->password); - } - } - // * RELATIONS /** diff --git a/app/Policies/Rules/UserStaticRules.php b/app/Policies/Rules/UserStaticRules.php index c527f44c..2f4a3b95 100644 --- a/app/Policies/Rules/UserStaticRules.php +++ b/app/Policies/Rules/UserStaticRules.php @@ -35,13 +35,17 @@ abstract class UserStaticRules /** * At least a minimum role * - * @param \App\Models\User $user - * @param \App\Enums\Users\RoleEnum $minRole + * @param \App\Models\User $user + * @param \App\Enums\Users\RoleEnum|null $minRole * @return boolean */ - public static function atLeastRole(User $user, RoleEnum $minRole): bool + public static function atLeastRole(User $user, RoleEnum|null $minRole): bool { // phpcs:enable + // Condition for creation case when user model is null + if (!$minRole) { + return true; + } return $user->role->value() <= $minRole->value(); } } diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index 6e0c3969..35745bf8 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -5,6 +5,13 @@ namespace App\Providers; use Illuminate\Auth\Events\Registered; use Illuminate\Auth\Listeners\SendEmailVerificationNotification; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; +use Illuminate\Support\Facades\Event; +use App\Models\User; +use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Cache; +use Illuminate\Support\Facades\Session; +use Slides\Saml2\Events\SignedIn; +use Slides\Saml2\Events\SignedOut; class EventServiceProvider extends ServiceProvider { @@ -28,4 +35,49 @@ class EventServiceProvider extends ServiceProvider { return false; } + + /** + * Register any events for your application. + * + * @return void + */ + public function boot() + { + Event::listen('Slides\Saml2\Events\SignedIn', function (SignedIn $event) { + + $messageId = $event->getAuth()->getLastMessageId(); + + $fromCache = Cache::get(config('cache.prefix') . "_saml_message_id_" . $messageId); + if ($fromCache) { + logger()->error( + 'SAML MESSAGE ID HANDLER', + ['error' => 'Message ID : ' . $messageId . " replayed !"] + ); + abort(403); + } else { + Cache::put(config('cache.prefix') . "_saml_message_id_" . $messageId, $messageId, 28800); + // Cache for 8h. + } + + $user = $event->getSaml2User(); + $email = $user->getNameId(); + + $lUser = User::where('email', '=', $email)->first(); + + if (!$lUser) { + abort(403); + } + + Auth::guard('backend')->login($lUser); + session(['sessionIndex' => $user->getSessionIndex()]); + $lUser->last_connection = now(); + $lUser->saveQuietly(); + }); + + //phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found + Event::listen('Slides\Saml2\Events\SignedOut', function (SignedOut $event) { + Auth::guard('backend')->logout(); + Session::save(); + }); + } } diff --git a/composer.json b/composer.json index 30415928..95c52642 100644 --- a/composer.json +++ b/composer.json @@ -5,12 +5,14 @@ "description": "Nature d'éleveurs website", "require": { "php": "^8.3", + "24slides/laravel-saml2": "^2.4", "diglactic/laravel-breadcrumbs": "^8.0", "doctrine/dbal": "^3.8", "guzzlehttp/guzzle": "^7.2", "laravel/framework": "^10.0", "laravel/tinker": "^2.8", "laravel/ui": "^4.2", + "ldc/web-admin-secure-laravel": "^2.0", "mews/purifier": "^3.4", "sentry/sentry-laravel": "*", "uwil/k8s-laravel": "^1.2" @@ -25,8 +27,7 @@ "nunomaduro/collision": "^7.0", "phpunit/phpunit": "^10.0", "slevomat/coding-standard": "^8.10", - "spatie/laravel-ignition": "^2.0", - "thedoctor0/laravel-factory-generator": "^1.2" + "spatie/laravel-ignition": "^2.0" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index a52029cd..26ac7bbc 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,83 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "0c405e5e857d060da1fe4ec06d7c6b58", + "content-hash": "5148466f07f0bb59987530415d755a5e", "packages": [ + { + "name": "24slides/laravel-saml2", + "version": "2.4.0", + "source": { + "type": "git", + "url": "https://github.com/24Slides/laravel-saml2.git", + "reference": "85dadba29a54f624c29d06b9a2ba0f00186cf665" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/24Slides/laravel-saml2/zipball/85dadba29a54f624c29d06b9a2ba0f00186cf665", + "reference": "85dadba29a54f624c29d06b9a2ba0f00186cf665", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "illuminate/console": "~5.5|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", + "illuminate/database": "~5.5|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", + "illuminate/support": "~5.4|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", + "onelogin/php-saml": "^3.0|^4.0", + "php": ">=7.1", + "ramsey/uuid": "^3.8|^4.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.9", + "phpunit/phpunit": "^7.5|^9.0", + "squizlabs/php_codesniffer": "^2.3" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "Saml2": "Slides\\Saml2\\Facades\\Auth" + }, + "providers": [ + "Slides\\Saml2\\ServiceProvider" + ] + }, + "branch-aliases": { + "dev-master": "2.0.8-dev" + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Slides\\Saml2\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Artem Brezhnev", + "email": "brezzhnev@gmail.com" + } + ], + "description": "SAML2 Service Provider integration to your Laravel 5.4+ application, based on OneLogin toolkit", + "homepage": "https://github.com/24slides/laravel-saml2", + "keywords": [ + "SAML2", + "SSO", + "laravel", + "onelogin", + "saml" + ], + "support": { + "issues": "https://github.com/24Slides/laravel-saml2/issues", + "source": "https://github.com/24Slides/laravel-saml2/tree/2.4.0" + }, + "time": "2024-04-13T12:57:36+00:00" + }, { "name": "brick/math", "version": "0.12.1", @@ -854,6 +929,102 @@ ], "time": "2023-08-10T19:36:49+00:00" }, + { + "name": "dxw/cidr", + "version": "v3.2.0", + "source": { + "type": "git", + "url": "https://github.com/dxw/cidr.git", + "reference": "b07dd398f5a93441f57a687982bc7d0ffb96729a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dxw/cidr/zipball/b07dd398f5a93441f57a687982bc7d0ffb96729a", + "reference": "b07dd398f5a93441f57a687982bc7d0ffb96729a", + "shasum": "" + }, + "require": { + "dxw/result": "^1.0", + "php": "^7.4||^8.1", + "phpseclib/phpseclib": "^2.0" + }, + "require-dev": { + "dxw/php-cs-fixer-config": "^2.0", + "kahlan/kahlan": "^5.2", + "vimeo/psalm": "^5.14" + }, + "type": "library", + "autoload": { + "psr-4": { + "Dxw\\CIDR\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "dxw", + "email": "team@govpress.com", + "homepage": "https://www.dxw.com" + } + ], + "description": "IP address matching with CIDR ranges", + "homepage": "https://github.com/dxw/cidr", + "support": { + "issues": "https://github.com/dxw/cidr/issues", + "source": "https://github.com/dxw/cidr/tree/v3.2.0" + }, + "time": "2023-08-14T10:14:13+00:00" + }, + { + "name": "dxw/result", + "version": "v1.0.6", + "source": { + "type": "git", + "url": "https://github.com/dxw/result.git", + "reference": "d554bb10f0cf74056ccd26526688e194652eef79" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dxw/result/zipball/d554bb10f0cf74056ccd26526688e194652eef79", + "reference": "d554bb10f0cf74056ccd26526688e194652eef79", + "shasum": "" + }, + "require": { + "php": "^7.4||^8.1" + }, + "require-dev": { + "dxw/php-cs-fixer-config": "^2.1", + "kahlan/kahlan": "^5.2", + "vimeo/psalm": "^4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Dxw\\Result\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mallory Adams", + "email": "mallory@dxw.com", + "homepage": "https://www.dxw.com/" + } + ], + "description": "Result values", + "homepage": "https://github.com/dxw/result", + "support": { + "issues": "https://github.com/dxw/result/issues", + "source": "https://github.com/dxw/result/tree/v1.0.6" + }, + "time": "2023-07-19T11:14:28+00:00" + }, { "name": "egulias/email-validator", "version": "4.0.2", @@ -2093,6 +2264,71 @@ }, "time": "2024-05-08T18:07:10+00:00" }, + { + "name": "ldc/web-admin-secure-laravel", + "version": "2.0.0", + "source": { + "type": "git", + "url": "git@lab.s-web.fr:ldc-web/projets/ldc-web-admin-secure-laravel.git", + "reference": "5f0c6b136fd967102bafeefa3048ffd47dbbc9be" + }, + "dist": { + "type": "zip", + "url": "https://lab.s-web.fr/api/v4/projects/20/packages/composer/archives/ldc/web-admin-secure-laravel.zip?sha=5f0c6b136fd967102bafeefa3048ffd47dbbc9be", + "reference": "5f0c6b136fd967102bafeefa3048ffd47dbbc9be", + "shasum": "" + }, + "require": { + "dxw/cidr": "^3.1", + "illuminate/support": "~10", + "laravel/framework": "~10", + "php": ">=8.2" + }, + "require-dev": { + "orchestra/testbench": "^8", + "phpunit/php-code-coverage": "^9", + "phpunit/phpunit": "^9", + "slevomat/coding-standard": "^7", + "squizlabs/php_codesniffer": "^3" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "LDC\\WebAdminSecureLaravel\\AdminSecureServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "LDC\\WebAdminSecureLaravel\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "LDC\\WebAdminSecureLaravel\\Tests\\": "tests" + } + }, + "scripts": { + "test": [ + "vendor/bin/phpunit" + ], + "post-autoload-dump": [ + "@php ./vendor/bin/testbench package:discover --ansi" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Vincent BRIDIER", + "email": "vincent.bridier@ldc.fr", + "homepage": "https://www.ldc.fr" + } + ], + "description": "Restrict access to LDC Network" + }, { "name": "league/commonmark", "version": "2.5.3", @@ -3125,6 +3361,70 @@ ], "time": "2023-11-13T09:31:12+00:00" }, + { + "name": "onelogin/php-saml", + "version": "4.2.0", + "source": { + "type": "git", + "url": "https://github.com/SAML-Toolkits/php-saml.git", + "reference": "d3b5172f137db2f412239432d77253ceaaa1e939" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/SAML-Toolkits/php-saml/zipball/d3b5172f137db2f412239432d77253ceaaa1e939", + "reference": "d3b5172f137db2f412239432d77253ceaaa1e939", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "robrichards/xmlseclibs": "^3.1" + }, + "require-dev": { + "pdepend/pdepend": "^2.8.0", + "php-coveralls/php-coveralls": "^2.0", + "phploc/phploc": "^4.0 || ^5.0 || ^6.0 || ^7.0", + "phpunit/phpunit": "^9.5", + "sebastian/phpcpd": "^4.0 || ^5.0 || ^6.0 ", + "squizlabs/php_codesniffer": "^3.5.8" + }, + "suggest": { + "ext-curl": "Install curl lib to be able to use the IdPMetadataParser for parsing remote XMLs", + "ext-dom": "Install xml lib", + "ext-openssl": "Install openssl lib in order to handle with x509 certs (require to support sign and encryption)", + "ext-zlib": "Install zlib" + }, + "type": "library", + "autoload": { + "psr-4": { + "OneLogin\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHP SAML Toolkit", + "homepage": "https://github.com/SAML-Toolkits/php-saml", + "keywords": [ + "Federation", + "SAML2", + "SSO", + "identity", + "saml" + ], + "support": { + "email": "sixto.martin.garcia@gmail.com", + "issues": "https://github.com/onelogin/SAML-Toolkits/issues", + "source": "https://github.com/onelogin/SAML-Toolkits/" + }, + "funding": [ + { + "url": "https://github.com/SAML-Toolkits", + "type": "github" + } + ], + "time": "2024-05-30T15:10:40+00:00" + }, { "name": "phpoption/phpoption", "version": "1.9.3", @@ -3200,6 +3500,116 @@ ], "time": "2024-07-20T21:41:07+00:00" }, + { + "name": "phpseclib/phpseclib", + "version": "2.0.47", + "source": { + "type": "git", + "url": "https://github.com/phpseclib/phpseclib.git", + "reference": "b7d7d90ee7df7f33a664b4aea32d50a305d35adb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/b7d7d90ee7df7f33a664b4aea32d50a305d35adb", + "reference": "b7d7d90ee7df7f33a664b4aea32d50a305d35adb", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phing/phing": "~2.7", + "phpunit/phpunit": "^4.8.35|^5.7|^6.0|^9.4", + "squizlabs/php_codesniffer": "~2.0" + }, + "suggest": { + "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.", + "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.", + "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", + "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations.", + "ext-xml": "Install the XML extension to load XML formatted public keys." + }, + "type": "library", + "autoload": { + "files": [ + "phpseclib/bootstrap.php" + ], + "psr-4": { + "phpseclib\\": "phpseclib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jim Wigginton", + "email": "terrafrost@php.net", + "role": "Lead Developer" + }, + { + "name": "Patrick Monnerat", + "email": "pm@datasphere.ch", + "role": "Developer" + }, + { + "name": "Andreas Fischer", + "email": "bantu@phpbb.com", + "role": "Developer" + }, + { + "name": "Hans-Jürgen Petrich", + "email": "petrich@tronic-media.com", + "role": "Developer" + }, + { + "name": "Graham Campbell", + "email": "graham@alt-three.com", + "role": "Developer" + } + ], + "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.", + "homepage": "http://phpseclib.sourceforge.net", + "keywords": [ + "BigInteger", + "aes", + "asn.1", + "asn1", + "blowfish", + "crypto", + "cryptography", + "encryption", + "rsa", + "security", + "sftp", + "signature", + "signing", + "ssh", + "twofish", + "x.509", + "x509" + ], + "support": { + "issues": "https://github.com/phpseclib/phpseclib/issues", + "source": "https://github.com/phpseclib/phpseclib/tree/2.0.47" + }, + "funding": [ + { + "url": "https://github.com/terrafrost", + "type": "github" + }, + { + "url": "https://www.patreon.com/phpseclib", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib", + "type": "tidelift" + } + ], + "time": "2024-02-26T04:55:38+00:00" + }, { "name": "psr/cache", "version": "3.0.0", @@ -3965,6 +4375,48 @@ ], "time": "2024-04-27T21:32:50+00:00" }, + { + "name": "robrichards/xmlseclibs", + "version": "3.1.1", + "source": { + "type": "git", + "url": "https://github.com/robrichards/xmlseclibs.git", + "reference": "f8f19e58f26cdb42c54b214ff8a820760292f8df" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/robrichards/xmlseclibs/zipball/f8f19e58f26cdb42c54b214ff8a820760292f8df", + "reference": "f8f19e58f26cdb42c54b214ff8a820760292f8df", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "php": ">= 5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "RobRichards\\XMLSecLibs\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "A PHP library for XML Security", + "homepage": "https://github.com/robrichards/xmlseclibs", + "keywords": [ + "security", + "signature", + "xml", + "xmldsig" + ], + "support": { + "issues": "https://github.com/robrichards/xmlseclibs/issues", + "source": "https://github.com/robrichards/xmlseclibs/tree/3.1.1" + }, + "time": "2020-09-05T13:00:25+00:00" + }, { "name": "sentry/sentry", "version": "4.9.0", @@ -10808,67 +11260,6 @@ ], "time": "2024-05-31T14:57:53+00:00" }, - { - "name": "thedoctor0/laravel-factory-generator", - "version": "1.4.3", - "source": { - "type": "git", - "url": "https://github.com/TheDoctor0/laravel-factory-generator.git", - "reference": "fed9260ab27522e3630bc379a14786b1880fa76d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/TheDoctor0/laravel-factory-generator/zipball/fed9260ab27522e3630bc379a14786b1880fa76d", - "reference": "fed9260ab27522e3630bc379a14786b1880fa76d", - "shasum": "" - }, - "require": { - "illuminate/console": "^10.0|^11.0", - "illuminate/filesystem": "^10.0|^11.0", - "illuminate/support": "^10.0|^11.0", - "php": "^8.1" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "TheDoctor0\\LaravelFactoryGenerator\\FactoryGeneratorServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "TheDoctor0\\LaravelFactoryGenerator\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Automatically generate Laravel factories for your models.", - "keywords": [ - "factories", - "factory", - "generator", - "laravel", - "tests" - ], - "support": { - "issues": "https://github.com/TheDoctor0/laravel-factory-generator/issues", - "source": "https://github.com/TheDoctor0/laravel-factory-generator/tree/1.4.3" - }, - "funding": [ - { - "url": "https://www.paypal.me/thedoctor0", - "type": "custom" - }, - { - "url": "https://github.com/thedoctor0", - "type": "github" - } - ], - "time": "2024-05-14T06:51:07+00:00" - }, { "name": "theseer/tokenizer", "version": "1.2.3", diff --git a/config/saml2.php b/config/saml2.php new file mode 100644 index 00000000..7687a41e --- /dev/null +++ b/config/saml2.php @@ -0,0 +1,397 @@ + \Slides\Saml2\Models\Tenant::class, + + /* + |-------------------------------------------------------------------------- + | Use built-in routes + |-------------------------------------------------------------------------- + | + | If "useRoutes" set to true, the package defines five new routes: + | + | Method | URI | Name + | -------|---------------------------------|------------------ + | POST | {routesPrefix}/{uuid}/acs | saml.acs + | GET | {routesPrefix}/{uuid}/login | saml.login + | GET | {routesPrefix}/{uuid}/logout | saml.logout + | GET | {routesPrefix}/{uuid}/metadata | saml.metadata + | GET | {routesPrefix}/{uuid}/sls | saml.sls + | + */ + + 'useRoutes' => true, + + /* + |-------------------------------------------------------------------------- + | Built-in routes prefix + |-------------------------------------------------------------------------- + | + | Here you may define the prefix for built-in routes. + | + */ + + 'routesPrefix' => '/saml2', + + /* + |-------------------------------------------------------------------------- + | Middle groups to use for the SAML routes + |-------------------------------------------------------------------------- + | + | Note, Laravel 5.2 requires a group which includes StartSession + | + */ + + 'routesMiddleware' => ['saml'], + + /* + |-------------------------------------------------------------------------- + | Signature validation + |-------------------------------------------------------------------------- + | + | Set to true if you want to use parameters from $_SERVER to validate the signature. + | + */ + + 'retrieveParametersFromServer' => false, + + /* + |-------------------------------------------------------------------------- + | Login redirection URL. + |-------------------------------------------------------------------------- + | + | The redirection URL after successful login. + | + */ + + 'loginRoute' => '/bo', + + /* + |-------------------------------------------------------------------------- + | Logout redirection URL. + |-------------------------------------------------------------------------- + | + | The redirection URL after successful logout. + | + */ + + 'logoutRoute' => '/bo', + + + /* + |-------------------------------------------------------------------------- + | Login error redirection URL. + |-------------------------------------------------------------------------- + | + | The redirection URL after login failing. + | + */ + + 'errorRoute' => '/bo/login-error', + + /* + |-------------------------------------------------------------------------- + | Strict mode. + |-------------------------------------------------------------------------- + | + | If 'strict' is True, then the PHP Toolkit will reject unsigned + | or unencrypted messages if it expects them signed or encrypted + | Also will reject the messages if not strictly follow the SAML + | standard: Destination, NameId, Conditions... are validated too. + | + */ + + 'strict' => true, + + /* + |-------------------------------------------------------------------------- + | Debug mode. + |-------------------------------------------------------------------------- + | + | When enabled, errors must be printed. + | + */ + + 'debug' => env('SAML2_DEBUG', env('APP_DEBUG', false)), + + /* + |-------------------------------------------------------------------------- + | Whether to use `X-Forwarded-*` headers to determine port/domain/protocol. + |-------------------------------------------------------------------------- + | + | If 'proxyVars' is True, then the Saml lib will trust proxy headers + | e.g X-Forwarded-Proto / HTTP_X_FORWARDED_PROTO. This is useful if + | your application is running behind a load balancer which terminates SSL. + | + */ + + 'proxyVars' => true, + + /* + |-------------------------------------------------------------------------- + | Service Provider configuration. + |-------------------------------------------------------------------------- + | + | General setting of the service provider. + | + */ + + 'sp' => [ + + /* + |-------------------------------------------------------------------------- + | NameID format. + |-------------------------------------------------------------------------- + | + | Specifies constraints on the name identifier to be used to + | represent the requested subject. + | + */ + + 'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress', + + /* + |-------------------------------------------------------------------------- + | SP Certificates. + |-------------------------------------------------------------------------- + | + | Usually x509cert and privateKey of the SP are provided by files placed at + | the certs folder. But we can also provide them with the following parameters. + | + */ + + 'x509cert' => env('SAML2_SP_CERT_x509', ''), + 'privateKey' => env('SAML2_SP_CERT_PRIVATEKEY', ''), + + /* + |-------------------------------------------------------------------------- + | Identifier (URI) of the SP entity. + |-------------------------------------------------------------------------- + | + | Leave blank to use the 'saml.metadata' route. + | + */ + + 'entityId' => env('SAML2_SP_ENTITYID', ''), + + /* + |-------------------------------------------------------------------------- + | The Assertion Consumer Service (ACS) URL. + |-------------------------------------------------------------------------- + | + | URL Location where the from the IdP will be returned, using HTTP-POST binding. + | Leave blank to use the 'saml.acs' route. + | + */ + + 'assertionConsumerService' => [ + 'url' => '', + ], + + /* + |-------------------------------------------------------------------------- + | The Single Logout Service URL. + |-------------------------------------------------------------------------- + | + | Specifies info about where and how the message MUST be + | returned to the requester, in this case our SP. + | + | URL Location where the from the IdP will be returned, using HTTP-Redirect binding. + | Leave blank to use the 'saml.sls' route. + | + */ + + 'singleLogoutService' => [ + 'url' => '' + ], + ], + + /* + |-------------------------------------------------------------------------- + | OneLogin security settings. + |-------------------------------------------------------------------------- + | + | + | + */ + + 'security' => [ + + 'signatureAlgorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256', + 'digestAlgorithm' => 'http://www.w3.org/2001/04/xmlenc#sha256', + + /* + |-------------------------------------------------------------------------- + | NameId encryption + |-------------------------------------------------------------------------- + | + | Indicates that the nameID of the sent by this SP + | will be encrypted. + | + */ + + 'nameIdEncrypted' => true, + + /* + |-------------------------------------------------------------------------- + | AuthnRequest signage + |-------------------------------------------------------------------------- + | + | Indicates whether the messages sent by + | this SP will be signed. The Metadata of the SP will offer this info + | + */ + + 'authnRequestsSigned' => true, + + /* + |-------------------------------------------------------------------------- + | Logout request signage + |-------------------------------------------------------------------------- + | + | Indicates whether the messages sent by this SP + | will be signed. + | + */ + + 'logoutRequestSigned' => true, + + /* + |-------------------------------------------------------------------------- + | Logout response signage + |-------------------------------------------------------------------------- + | + | Indicates whether the messages sent by this SP + | will be signed. + | + */ + + 'logoutResponseSigned' => true, + + /* + |-------------------------------------------------------------------------- + | Whether need to sign metadata. + |-------------------------------------------------------------------------- + | + | The possible values: + | - false + | - true (use certs) + | - array: + | ``` + | [ + | 'keyFileName' => 'metadata.key', + | 'certFileName' => 'metadata.crt' + | ] + | ``` + | + */ + + 'signMetadata' => true, + + /* + |-------------------------------------------------------------------------- + | Requirement to sign messages. + |-------------------------------------------------------------------------- + | + | Indicates a requirement for the , and + | elements received by this SP to be signed. + | + */ + + 'wantMessagesSigned' => true, + + /* + |-------------------------------------------------------------------------- + | Requirement to sign assertion elements. + |-------------------------------------------------------------------------- + | + | Indicates a requirement for the elements received by + | this SP to be signed. + | + */ + + 'wantAssertionsSigned' => true, + + /* + |-------------------------------------------------------------------------- + | Requirement to encrypt NameID. + |-------------------------------------------------------------------------- + | + | Indicates a requirement for the NameID received by this SP to be encrypted. + | + */ + + 'wantNameIdEncrypted' => false, + + /* + |-------------------------------------------------------------------------- + | Authentication context. + |-------------------------------------------------------------------------- + | + | Set to false and no AuthContext will be sent in the AuthNRequest, + | + | Set true or don't present this parameter and you will get an + | AuthContext 'exact' 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport' + | + | Set an array with the possible auth context values: + | ['urn:oasis:names:tc:SAML:2.0:ac:classes:Password', 'urn:oasis:names:tc:SAML:2.0:ac:classes:X509'] + | + */ + + 'requestedAuthnContext' => true, + ], + + /* + |-------------------------------------------------------------------------- + | Contact information. + |-------------------------------------------------------------------------- + | + | It is recommended to supply a technical and support contacts. + | + */ + + 'contactPerson' => [ + 'technical' => [ + 'givenName' => env('SAML2_CONTACT_TECHNICAL_NAME', env('APP_NAME', 'Technical')), + 'emailAddress' => env('SAML2_CONTACT_TECHNICAL_EMAIL', 'no@reply.com') + ], + 'support' => [ + 'givenName' => env('SAML2_CONTACT_SUPPORT_NAME', env('APP_NAME', 'Support')), + 'emailAddress' => env('SAML2_CONTACT_SUPPORT_EMAIL', 'no@reply.com') + ], + ], + + /* + |-------------------------------------------------------------------------- + | Organization information. + |-------------------------------------------------------------------------- + | + | The info in en_US lang is recommended, add more if required. + | + */ + + 'organization' => [ + 'en-US' => [ + 'name' => env('SAML2_ORGANIZATION_NAME', env('APP_NAME', 'Name')), + 'displayname' => env('SAML2_ORGANIZATION_NAME', env('APP_NAME', 'Name')), + 'url' => env('SAML2_ORGANIZATION_URL', env('APP_URL', 'http://url')) + ], + ], + + /** + * Default tenant UUID + */ + + 'default_tenant_uuid' => env('SAML2_DEFAULT_TENANT_UUID', null) + +]; diff --git a/database/migrations/2024_08_22_150017_alter_users_for_saml.php b/database/migrations/2024_08_22_150017_alter_users_for_saml.php new file mode 100644 index 00000000..68a2b3a7 --- /dev/null +++ b/database/migrations/2024_08_22_150017_alter_users_for_saml.php @@ -0,0 +1,32 @@ +dropColumn('email_verified_at'); + $table->dropColumn('password'); + $table->date('last_connection')->nullable()->after('role'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->timestamp('email_verified_at')->nullable()->after('email'); + $table->string('password')->after('email_verified_at'); + $table->dropColumn('last_connection'); + }); + } +}; diff --git a/manifest.yaml b/manifest.yaml index 418c4146..6a75c4c5 100644 --- a/manifest.yaml +++ b/manifest.yaml @@ -1,4 +1,3 @@ ---- apiVersion: v1 kind: ConfigMap metadata: @@ -28,6 +27,11 @@ data: GOOGLE_ANALYTICS_ID: "${APP_GOOGLE_ANALYTICS_ID}" MATOMO_SITE_ID: "${APP_MATOMO_SITE_ID}" SENTRY_LARAVEL_DSN: "${APP_SENTRY_LARAVEL_DSN}" + SAML2_SP_CERT_x509: "${APP_SAML2_SP_CERT_x509}" + SAML2_SP_CERT_PRIVATEKEY: "${APP_SAML2_SP_CERT_PRIVATEKEY}" + SAML2_CONTACT_TECHNICAL_EMAIL: "${APP_SAML2_CONTACT_TECHNICAL_EMAIL}" + SAML2_CONTACT_SUPPORT_EMAIL: "${APP_SAML2_CONTACT_SUPPORT_EMAIL}" + SAML2_DEFAULT_TENANT_UUID: "${APP_SAML2_DEFAULT_TENANT_UUID}" --- apiVersion: v1 @@ -37,7 +41,7 @@ metadata: spec: storageClassName: "csi-cinder-classic" accessModes: - - ReadWriteOnce + - ReadWriteOnce resources: requests: storage: $APP_PVC_SIZE @@ -58,25 +62,25 @@ spec: app: ${CI_PROJECT_PATH_SLUG}-app spec: containers: - - name: ${CI_PROJECT_PATH_SLUG}-container - image: $IMAGE_TAG - envFrom: - - configMapRef: - name: ${CI_PROJECT_PATH_SLUG}-config-map - volumeMounts: - - name: storage - mountPath: /app/srcs/storage + - name: ${CI_PROJECT_PATH_SLUG}-container + image: $IMAGE_TAG + envFrom: + - configMapRef: + name: ${CI_PROJECT_PATH_SLUG}-config-map + volumeMounts: + - name: storage + mountPath: /app/srcs/storage imagePullSecrets: - - name: docker-registry-credentials + - name: docker-registry-credentials securityContext: runAsUser: 33 runAsGroup: 33 fsGroup: 33 fsGroupChangePolicy: "OnRootMismatch" volumes: - - name: storage - persistentVolumeClaim: - claimName: ${CI_PROJECT_PATH_SLUG}-pvc-storage + - name: storage + persistentVolumeClaim: + claimName: ${CI_PROJECT_PATH_SLUG}-pvc-storage --- apiVersion: v1 @@ -87,8 +91,8 @@ spec: selector: app: ${CI_PROJECT_PATH_SLUG}-app ports: - - port: 80 - targetPort: 443 + - port: 80 + targetPort: 443 --- apiVersion: traefik.io/v1alpha1 @@ -97,16 +101,16 @@ metadata: name: ${CI_PROJECT_PATH_SLUG}-ingress-route spec: entryPoints: - - web - - websecure + - web + - websecure routes: - - match: Host(`${APP_DOMAIN}`) || Host(`www.${APP_DOMAIN}`) - kind: Rule - services: - - name: ${CI_PROJECT_PATH_SLUG}-service - port: 80 - middlewares: - - name: redirect-no-www-to-www + - match: Host(`${APP_DOMAIN}`) || Host(`www.${APP_DOMAIN}`) + kind: Rule + services: + - name: ${CI_PROJECT_PATH_SLUG}-service + port: 80 + middlewares: + - name: redirect-no-www-to-www tls: secretName: ${CRT_TLS_NAME} @@ -124,35 +128,35 @@ spec: affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - - labelSelector: - matchExpressions: - - key: app - operator: In - values: - - ${CI_PROJECT_PATH_SLUG}-app - topologyKey: "kubernetes.io/hostname" - namespaces: [$KUBE_NAMESPACE] + - labelSelector: + matchExpressions: + - key: app + operator: In + values: + - ${CI_PROJECT_PATH_SLUG}-app + topologyKey: "kubernetes.io/hostname" + namespaces: [$KUBE_NAMESPACE] containers: - - name: ${CI_PROJECT_PATH_SLUG}-scheduled - image: $IMAGE_TAG - imagePullPolicy: IfNotPresent - command: - - "php" - args: - - "artisan" - - "schedule:run" - envFrom: - - configMapRef: - name: ${CI_PROJECT_PATH_SLUG}-config-map - volumeMounts: - - name: storage - mountPath: /app/srcs/storage - imagePullSecrets: - - name: docker-registry-credentials - volumes: + - name: ${CI_PROJECT_PATH_SLUG}-scheduled + image: $IMAGE_TAG + imagePullPolicy: IfNotPresent + command: + - "php" + args: + - "artisan" + - "schedule:run" + envFrom: + - configMapRef: + name: ${CI_PROJECT_PATH_SLUG}-config-map + volumeMounts: - name: storage - persistentVolumeClaim: - claimName: ${CI_PROJECT_PATH_SLUG}-pvc-storage + mountPath: /app/srcs/storage + imagePullSecrets: + - name: docker-registry-credentials + volumes: + - name: storage + persistentVolumeClaim: + claimName: ${CI_PROJECT_PATH_SLUG}-pvc-storage securityContext: runAsUser: 33 runAsGroup: 33 diff --git a/resources/views/bo/auth/login.blade.php b/resources/views/bo/auth/login.blade.php index 17314429..cc3b0221 100644 --- a/resources/views/bo/auth/login.blade.php +++ b/resources/views/bo/auth/login.blade.php @@ -8,57 +8,11 @@
{{ __('Connexion') }}
-
-
- @csrf -
- -
- - @error('email') - - {{ $message }} - - @enderror -
-
-
- -
- - @error('password') - - {{ $message }} - - @enderror -
-
-
-
-
- - -
-
-
-
-
- - @if (Route::has('bo.password.request')) - - {{ __('Mot de passe oublié ?') }} - - @endif -
-
-
+
diff --git a/resources/views/bo/layouts/head.blade.php b/resources/views/bo/layouts/head.blade.php index c9eb5565..26a67422 100644 --- a/resources/views/bo/layouts/head.blade.php +++ b/resources/views/bo/layouts/head.blade.php @@ -23,7 +23,7 @@ {{-- Others --}} {{-- blade-formatter-disable-next-line --}} -{{ config('app.name') }}@hasSection('title') - @yield('title')@endif +@hasSection('title')@yield('title') - @endif{{ config('app.name') }} {{-- blade-formatter-disable --}} @hasSection('canonical') @@ -40,7 +40,7 @@ @stack('styles') @if (config('app.debug')) - @endif diff --git a/resources/views/bo/pages/dashboard.blade.php b/resources/views/bo/pages/dashboard.blade.php index 0a40ec3b..0216767f 100644 --- a/resources/views/bo/pages/dashboard.blade.php +++ b/resources/views/bo/pages/dashboard.blade.php @@ -1,30 +1,37 @@ @extends('bo.layout') -@section('title', __('Accueil')) -@section('description', __('Description site')) +@section('title', __('Bo')) +@section('description', __("Interface d'administration")) @section('breadcrumb', 'no') @section('content')
-
+

{{ __('Dashboard') }}

-
- {{ __('Bonjour :first_name :last_name !', [ +
+ + {{ __('Bonjour :first_name :last_name !', [ 'first_name' => auth('backend')->user()->first_name, 'last_name' => auth('backend')->user()->last_name, ]) }} +
-

+

{{ __('Bienvenue dans le back-office, où vous pouvez gérer votre application web.') }}

-

+

+ + {{ __('Pour accéder à vos statistiques') }} : + https://report.uwil.fr
{{ __('Pour tout problème ou évolution souhaitée, veuillez nous contacter via notre outil : ') }} https://support.uwil.fr/. +

diff --git a/resources/views/bo/pages/login-error.blade.php b/resources/views/bo/pages/login-error.blade.php new file mode 100644 index 00000000..478f049c --- /dev/null +++ b/resources/views/bo/pages/login-error.blade.php @@ -0,0 +1,11 @@ +@extends('vendor.errors.illustrated-layout') + +@section('title', __('Une erreur est survenue lors de la connexion.')) +@section('message', __('Une erreur est survenue lors de la connexion.')) +@section('submessage', __('Veuillez contacter le support.')) + +@section('button', true) + +@section('image') + +@endsection diff --git a/resources/views/bo/pages/users/form.blade.php b/resources/views/bo/pages/users/form.blade.php index 9651b06a..7d498510 100644 --- a/resources/views/bo/pages/users/form.blade.php +++ b/resources/views/bo/pages/users/form.blade.php @@ -90,39 +90,6 @@
- {{-- PASSWORD --}} -
-
- {{ __('Mot de passe') }} -
-
- @include('bo.partials.inputs.varchar-password', [ - 'id' => 'userPassword', - 'label' => __('Mot de passe de l\':model', ['model' => __('models.classes.user')]), - 'name' => 'password', - 'hasWordCounter' => true, - 'required' => !$userModel->exists, - 'model' => null, - 'helper' => __( - 'Doît respecter certaines contraintes (8 caractères minimum, lettres, chiffres, caractères spéciaux).'), - ]) -
-
- @include('bo.partials.inputs.varchar-password', [ - 'id' => 'userPassword_confirmation', - 'label' => __('Confirmation du mot de passe de l\':model', [ - 'model' => __('models.classes.user'), - ]), - 'name' => 'password_confirmation', - 'hasWordCounter' => true, - 'required' => !$userModel->exists, - 'model' => null, - 'helper' => __('Doît correspondre au mot de passe saisi précédemment.'), - ]) -
-
-
-
{{-- STATUS --}} @can('changePublished', $userModel)
@@ -141,6 +108,8 @@
+ @else + @endcan

{{ __('* Champs obligatoires') }}

diff --git a/resources/views/fo/layouts/head.blade.php b/resources/views/fo/layouts/head.blade.php index 8fc84d72..614796bc 100644 --- a/resources/views/fo/layouts/head.blade.php +++ b/resources/views/fo/layouts/head.blade.php @@ -48,7 +48,7 @@ {{-- DEBUG --}} @if (config('app.debug')) - @endif diff --git a/resources/views/modules/script-constants.blade.php b/resources/views/modules/script-constants.blade.php index 1b031561..ce47547b 100644 --- a/resources/views/modules/script-constants.blade.php +++ b/resources/views/modules/script-constants.blade.php @@ -1,4 +1,4 @@ -