bump: 📦 laravel 11 + sitemap + saml + robots.txt
This commit is contained in:
parent
cdf0a866dc
commit
36c877d6be
24 changed files with 1942 additions and 2096 deletions
|
|
@ -75,3 +75,9 @@ MAIL_CONTACT_OTHER="equipe.web@ldc.fr"
|
|||
GOOGLE_RECAPTCHA_PUBLIC=
|
||||
GOOGLE_RECAPTCHA_PRIVATE=
|
||||
GOOGLE_RECAPTCHA_VERSION=
|
||||
|
||||
|
||||
SAML2_DEFAULT_TENANT_UUID=
|
||||
SAML2_SP_CERT_x509=
|
||||
SAML2_SP_CERT_PRIVATEKEY=
|
||||
SAML2_CONTACT_TECHNICAL_EMAIL=
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -39,7 +39,11 @@ class Kernel extends HttpKernel
|
|||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
\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,
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
];
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
],
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@ use App\Traits\Models\ActivityLog;
|
|||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Str;
|
||||
use Spatie\Sitemap\Contracts\Sitemapable;
|
||||
use Spatie\Sitemap\Tags\Url;
|
||||
use Uwil\SitemapGenerator\Lib\SitemapHelper;
|
||||
|
||||
/**
|
||||
* @property string $seo_title SEO title.
|
||||
|
|
@ -32,7 +35,7 @@ use Illuminate\Support\Str;
|
|||
*
|
||||
* @property-read \App\Models\ActivityLog $activityLogs Activities logs One-to-many relationship.
|
||||
*/
|
||||
class News extends Model
|
||||
class News extends Model implements Sitemapable
|
||||
{
|
||||
use ActivityLog;
|
||||
use HasFactory;
|
||||
|
|
@ -62,6 +65,20 @@ class News extends Model
|
|||
'unpublish_at',
|
||||
];
|
||||
|
||||
/**
|
||||
* toSitemapTag method
|
||||
*
|
||||
* @return Url|string|array
|
||||
*/
|
||||
public function toSitemapTag(): Url | string | array
|
||||
{
|
||||
$model = $this;
|
||||
$route = 'fo.news.show';
|
||||
$params = ['publishedNews' => $model];
|
||||
return SitemapHelper::generateUrl($route, $params, $model);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@ use App\Traits\Models\ActivityLog;
|
|||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Str;
|
||||
use Spatie\Sitemap\Contracts\Sitemapable;
|
||||
use Spatie\Sitemap\Tags\Url;
|
||||
use Uwil\SitemapGenerator\Lib\SitemapHelper;
|
||||
|
||||
/**
|
||||
* @property string $seo_title SEO title.
|
||||
|
|
@ -48,7 +51,7 @@ use Illuminate\Support\Str;
|
|||
* @property-read \App\Models\Logo $logos Logos Many-to-many relationship.
|
||||
* @property-read \App\Models\ActivityLog $activityLogs Activities logs One-to-many relationship.
|
||||
*/
|
||||
class Site extends Model
|
||||
class Site extends Model implements Sitemapable
|
||||
{
|
||||
use ActivityLog;
|
||||
use HasFactory;
|
||||
|
|
@ -203,4 +206,17 @@ class Site extends Model
|
|||
{
|
||||
return $this->belongsToMany(Logo::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* toSitemapTag method
|
||||
*
|
||||
* @return Url|string|array
|
||||
*/
|
||||
public function toSitemapTag(): Url | string | array
|
||||
{
|
||||
$model = $this;
|
||||
$route = 'fo.sites.show';
|
||||
$params = ['site' => $model];
|
||||
return SitemapHelper::generateUrl($route, $params, $model);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 \Illuminate\Support\Carbon $published Published status.
|
||||
* @property \Illuminate\Support\Carbon $published_at Publication status update date.
|
||||
|
|
@ -50,7 +48,6 @@ class User extends Authenticatable
|
|||
* @var array<int, string>
|
||||
*/
|
||||
protected $hidden = [
|
||||
'password',
|
||||
'remember_token',
|
||||
];
|
||||
|
||||
|
|
@ -61,7 +58,7 @@ class User extends Authenticatable
|
|||
*/
|
||||
protected $casts = [
|
||||
'role' => RoleEnum::class,
|
||||
'email_verified_at' => 'datetime',
|
||||
'last_connection' => 'date',
|
||||
'published' => 'boolean',
|
||||
'published_at' => 'datetime',
|
||||
];
|
||||
|
|
@ -74,7 +71,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 +78,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],
|
||||
|
|
@ -97,19 +92,4 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,12 @@ 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;
|
||||
|
||||
class EventServiceProvider extends ServiceProvider
|
||||
{
|
||||
|
|
@ -28,4 +34,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();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "uwil/laravel-base-project",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"type": "project",
|
||||
"description": "Laravel base project reference.",
|
||||
"support": {
|
||||
|
|
@ -12,30 +12,30 @@
|
|||
],
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^8.2",
|
||||
"php": "^8.3",
|
||||
"24slides/laravel-saml2": "^2.4",
|
||||
"axlon/laravel-postal-code-validation": "^3.5",
|
||||
"diglactic/laravel-breadcrumbs": "^8.0",
|
||||
"diglactic/laravel-breadcrumbs": "^9.0",
|
||||
"guzzlehttp/guzzle": "^7.2",
|
||||
"kwaadpepper/image-resizer": "^2.1",
|
||||
"laravel/framework": "^10.0",
|
||||
"kwaadpepper/image-resizer": "^3.1",
|
||||
"laravel/framework": "^11.0",
|
||||
"laravel/tinker": "^2.8",
|
||||
"laravel/ui": "^4.2",
|
||||
"ldc/sitemap-generator": "^2.0",
|
||||
"mews/purifier": "^3.4",
|
||||
"propaganistas/laravel-phone": "^5.1",
|
||||
"sentry/sentry-laravel": "*",
|
||||
"uwil/k8s-laravel": "^1.2"
|
||||
"uwil/k8s-laravel": "^1.2",
|
||||
"uwil/sitemap-generator": "^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"fakerphp/faker": "^1.9.1",
|
||||
"kitloong/laravel-migrations-generator": "^6.8",
|
||||
"krlove/eloquent-model-generator": "dev-l10-compatibility",
|
||||
"kitloong/laravel-migrations-generator": "^7.1",
|
||||
"larastan/larastan": "^2.9",
|
||||
"laravel-lang/common": "^4.0",
|
||||
"laravel/pint": "^1.0",
|
||||
"laravel/sail": "^1.18",
|
||||
"mockery/mockery": "^1.4.4",
|
||||
"nunomaduro/collision": "^7.0",
|
||||
"nunomaduro/collision": "^8.1",
|
||||
"phpunit/phpunit": "^10.0",
|
||||
"slevomat/coding-standard": "^8.10",
|
||||
"spatie/laravel-ignition": "^2.0",
|
||||
|
|
|
|||
3103
composer.lock
generated
3103
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -56,8 +56,6 @@ return [
|
|||
|
||||
'url' => env('APP_URL', 'http://localhost'),
|
||||
|
||||
'asset_url' => env('ASSET_URL'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Timezone
|
||||
|
|
|
|||
395
config/saml2.php
Normal file
395
config/saml2.php
Normal file
|
|
@ -0,0 +1,395 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Tenant Model
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This will allow you to override the tenant model with your own.
|
||||
|
|
||||
*/
|
||||
|
||||
'tenantModel' => \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 <Response> 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 <Logout Response> message MUST be
|
||||
| returned to the requester, in this case our SP.
|
||||
|
|
||||
| URL Location where the <Response> 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 <samlp:logoutRequest> sent by this SP
|
||||
| will be encrypted.
|
||||
|
|
||||
*/
|
||||
|
||||
'nameIdEncrypted' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| AuthnRequest signage
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Indicates whether the <samlp:AuthnRequest> 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 <samlp:logoutRequest> messages sent by this SP
|
||||
| will be signed.
|
||||
|
|
||||
*/
|
||||
|
||||
'logoutRequestSigned' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Logout response signage
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Indicates whether the <samlp:logoutResponse> 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 <samlp:Response>, <samlp:LogoutRequest> and
|
||||
| <samlp:LogoutResponse> elements received by this SP to be signed.
|
||||
|
|
||||
*/
|
||||
|
||||
'wantMessagesSigned' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Requirement to sign assertion elements.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Indicates a requirement for the <saml:Assertion> 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)
|
||||
|
||||
];
|
||||
|
|
@ -1,72 +1,44 @@
|
|||
<?php
|
||||
|
||||
use Spatie\Sitemap\Tags\Url;
|
||||
|
||||
return [
|
||||
|
||||
/**
|
||||
* A list of url to ignore
|
||||
* These are hard coded
|
||||
* Each url does not have to be exhaustive
|
||||
* Single route names
|
||||
*
|
||||
* For example, if you want to ignore all routes
|
||||
* of the backoffice group
|
||||
* just add 'bo' into this table
|
||||
*
|
||||
* * Note that this can take route names (both partially or full)
|
||||
* * You can use a wild card just as for routeIs method
|
||||
*/
|
||||
'ignoreRoutes' => [
|
||||
'bo.*',
|
||||
'fo.frame',
|
||||
'cspReportUri',
|
||||
'singlePages' => [
|
||||
'fo.home.show',
|
||||
'fo.unveil.show',
|
||||
'fo.commit.show',
|
||||
'fo.listen.show',
|
||||
'fo.news.index',
|
||||
'fo.hire.show',
|
||||
'fo.produce.show',
|
||||
'fo.legals',
|
||||
'fo.confidentiality',
|
||||
],
|
||||
|
||||
/**
|
||||
* This should be filled using the command `php artisan sitemap:install-completer`
|
||||
* Model namespaces with filters
|
||||
*
|
||||
* 'completeWith' => [CLASS, 'METHOD'],
|
||||
* eg : 'completeWith' => [CompleteSitemapWith::class, 'append'],
|
||||
*
|
||||
* This should point to a static method which will be called with the folowing parameter
|
||||
* (LDC\SitemapGenerator\Lib\Sitemap $sitemap)
|
||||
*
|
||||
* You may now use $sitemap->addLinks('route.myRouteName', string[] $links)
|
||||
*/
|
||||
'completeWith' => null,
|
||||
'cruds' => [
|
||||
[
|
||||
'model' => 'App\Models\News',
|
||||
'filters' => [
|
||||
[
|
||||
'published',
|
||||
'=',
|
||||
true
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
'model' => 'App\Models\Site',
|
||||
'filters' => []
|
||||
],
|
||||
|
||||
/**
|
||||
* The default route frequency to use with sitemap generator
|
||||
*/
|
||||
'routeDefaultFrequency' => Url::CHANGE_FREQUENCY_DAILY,
|
||||
|
||||
/**
|
||||
* The default route priority to use with sitemap generator
|
||||
*
|
||||
* priority should be a number between 0 and 1
|
||||
* https://www.sitemaps.org/protocol.html
|
||||
*/
|
||||
'routeDefaultPriority' => 0.5,
|
||||
|
||||
/**
|
||||
* Frequencies for routes
|
||||
* use the full or partial route name as index
|
||||
* and a frequency within \Spatie\Sitemap\Tags\Url constants
|
||||
*
|
||||
* eg: 'engagments.*' => \Spatie\Sitemap\Tags\Url::CHANGE_FREQUENCY_HOURLY
|
||||
*/
|
||||
'routeFrequencies' => [],
|
||||
|
||||
/**
|
||||
* Priorities for routes
|
||||
* use the full or partial route name as index
|
||||
* and a priority in 1.0, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, and 0.0.
|
||||
*
|
||||
* 1.0 is the Highest
|
||||
*
|
||||
* eg: 'engagments.*' => 1.0
|
||||
*/
|
||||
'routePriorities' => [],
|
||||
],
|
||||
|
||||
/**
|
||||
* Enable or disable schedule for the job
|
||||
|
|
@ -86,20 +58,4 @@ return [
|
|||
* Default is every day at 15:45
|
||||
*/
|
||||
'cron' => '45 15 * * *',
|
||||
|
||||
/**
|
||||
* The sitemap generator can execute JavaScript on each page so it will
|
||||
* discover links that are generated by your JS scripts. This feature
|
||||
* is powered by headless Chrome.
|
||||
*
|
||||
* ! This needs pupetter installed with npm : npm i puppeteer (not to put in dev dependencies)
|
||||
*/
|
||||
'executeJavascript' => false,
|
||||
|
||||
/**
|
||||
* Output xml file, consider this shall be public/sitemap.xml
|
||||
*
|
||||
* Use this for deployement convenience for example.
|
||||
*/
|
||||
'output' => \storage_path('app/public/sitemap.xml')
|
||||
];
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropColumn('email_verified_at');
|
||||
$table->dropColumn('password');
|
||||
$table->date('last_connection')->nullable()->after('role');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
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');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -30,6 +30,10 @@ data:
|
|||
GOOGLE_RECAPTCHA_VERSION: "${APP_GOOGLE_RECAPTCHA_VERSION}"
|
||||
SENTRY_LARAVEL_DSN: "${APP_SENTRY_LARAVEL_DSN}"
|
||||
MATOMO_SITE_ID: "${APP_MATOMO_SITE_ID}"
|
||||
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}"
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
|
|
|
|||
|
|
@ -1,3 +1,13 @@
|
|||
User-agent: *
|
||||
Disallow: /bo
|
||||
|
||||
User-agent: GPTBot
|
||||
Disallow: /
|
||||
|
||||
User-agent: Amazonbot
|
||||
Disallow: /
|
||||
|
||||
User-agent: ClaudeBot
|
||||
Disallow: /
|
||||
|
||||
Sitemap: https://www.volena.fr/sitemap.xml
|
||||
|
|
|
|||
|
|
@ -9,60 +9,17 @@
|
|||
<div class="card">
|
||||
<div class="card-header">{{ __('Connexion') }}</div>
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ route('bo.login') }}">
|
||||
@csrf
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-4 col-form-label text-md-end" for="email">{{ __('Adresse Email') }}</label>
|
||||
<div class="col-md-6">
|
||||
<input class="form-control @error('email') is-invalid @enderror" id="email" name="email"
|
||||
type="email" value="{{ old('email') }}" autocomplete="email" autofocus required>
|
||||
@error('email')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col text-center">
|
||||
<a class="btn btn-primary" href="{{ route('saml.login', ['uuid' => config('saml2.default_tenant_uuid')]) }}">
|
||||
<span>{{ __('Connexion avec UWIL Support') }}</span>
|
||||
<i class="fa-solid fa-arrow-right-from-bracket"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-4 col-form-label text-md-end" for="password">{{ __('Mot de passe') }}</label>
|
||||
<div class="col-md-6">
|
||||
<input class="form-control @error('password') is-invalid @enderror" id="password" name="password"
|
||||
type="password" autocomplete="current-password" required>
|
||||
@error('password')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6 offset-md-4">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" id="remember" name="remember" type="checkbox"
|
||||
{{ old('remember') ? 'checked' : '' }}>
|
||||
<label class="form-check-label user-select-none" for="remember">
|
||||
{{ __('Se souvenir de moi') }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-0">
|
||||
<div class="col-md-8 offset-md-4">
|
||||
<button class="btn btn-primary" type="submit">
|
||||
<span>{{ __('Connexion') }}</span>
|
||||
<i class="fa-solid fa-arrow-right-from-bracket"></i>
|
||||
</button>
|
||||
@if (Route::has('bo.password.request'))
|
||||
<a class="btn btn-link" href="{{ route('bo.password.request') }}">
|
||||
{{ __('Mot de passe oublié ?') }}
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
@endsection
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
@stack('styles')
|
||||
|
||||
@if (config('app.debug'))
|
||||
<script nonce="{{ $nonce }}">
|
||||
<script nonce="{{ $nonce ?? '' }}">
|
||||
window.vueDebug = true;
|
||||
</script>
|
||||
@endif
|
||||
|
|
|
|||
|
|
@ -22,6 +22,13 @@
|
|||
{{ __('Bienvenue dans le back-office, où vous pouvez gérer votre application web.') }}
|
||||
</p>
|
||||
<p class="card-text">
|
||||
{{ __('Pour accéder à vos statistiques') }} :
|
||||
<a class="btn btn-primary btn-sm" data-bs-toggle="tooltip" href="https://report.uwil.fr"
|
||||
title="{{ __('Accéder à notre outil de ticketing') }}" target="blank">
|
||||
{{ __('UWIL Report') }}
|
||||
<i class="fa-solid fa-arrow-up-right-from-square ms-1"></i>
|
||||
</a>
|
||||
|
||||
{{ __('Pour tout problème ou évolution souhaitée, veuillez nous contacter via notre outil : ') }}
|
||||
<a data-bs-toggle="tooltip" href="https://support.uwil.fr/" title="{{ __('Accéder à notre outil de ticketing') }}"
|
||||
target="blank">https://support.uwil.fr/</a>.
|
||||
|
|
|
|||
22
resources/views/bo/pages/login-error.blade.php
Normal file
22
resources/views/bo/pages/login-error.blade.php
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
@extends('fo.layout')
|
||||
|
||||
@section('title', __('Une erreur est survenue lors de la connexion.'))
|
||||
@section('description', __('Il semble qu\'il y ait des erreurs pour répondre à votre demande.'))
|
||||
@section('breadcrumb', 'no')
|
||||
@section('bodyClass', 'bg-white-wood')
|
||||
|
||||
@section('content')
|
||||
<div class="container my-5 py-5">
|
||||
<div class="row">
|
||||
<div class="col text-center">
|
||||
<h1>{{ str(__('Une erreur est survenue lors de la connexion.'))->upper() }}</h1>
|
||||
<h4 class="h4 my-4">
|
||||
{{ __('Veuillez contacter le support.') }}
|
||||
</h4>
|
||||
<a class="btn btn-secondary" href="{{ route('fo.home.show') }}" title="{{ __('Accéder à la page d\'accueil') }}">
|
||||
{{ str(__('retour à la page d\'accueil'))->upper() }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
|
@ -89,39 +89,6 @@
|
|||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
{{-- PASSWORD --}}
|
||||
<div class="col-12 mb-3">
|
||||
<fieldset class="h-100 border p-3">
|
||||
<legend>{{ __('Mot de passe') }}</legend>
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-6 mb-3">
|
||||
@include('bo.partials.inputs.varchar-password', [
|
||||
'id' => 'userPassword',
|
||||
'label' => __('Mot de passe de l\':model', ['model' => trans_choice('models.classes.user', 1)]),
|
||||
'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).'),
|
||||
])
|
||||
</div>
|
||||
<div class="col-12 col-md-6 mb-3">
|
||||
@include('bo.partials.inputs.varchar-password', [
|
||||
'id' => 'userPassword_confirmation',
|
||||
'label' => __('Confirmation du mot de passe de l\':model', [
|
||||
'model' => trans_choice('models.classes.user', 1),
|
||||
]),
|
||||
'name' => 'password_confirmation',
|
||||
'hasWordCounter' => true,
|
||||
'required' => !$userModel->exists,
|
||||
'model' => null,
|
||||
'helper' => __('Doît correspondre au mot de passe saisi précédemment.'),
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
{{-- STATUS --}}
|
||||
@can('changePublished', $userModel)
|
||||
<div class="col-12 col-md-6 mb-3">
|
||||
|
|
@ -145,20 +112,3 @@
|
|||
<p><b>{{ __('validation.custom.required_fields') }}</b></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script nonce="{{ $nonce }}">
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
// If we edit the password, the confirmation is required.
|
||||
const passwordInput = document.getElementById('userPassword');
|
||||
const confirmPasswordInput = document.getElementById('userPassword_confirmation');
|
||||
passwordInput.addEventListener('input', () => {
|
||||
if (passwordInput.value !== '') {
|
||||
confirmPasswordInput.required = true;
|
||||
} else {
|
||||
confirmPasswordInput.required = false;
|
||||
}
|
||||
})
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
@push('scripts')
|
||||
<script nonce="{{ $nonce }}">
|
||||
<script nonce="{{ $nonce ?? '' }}">
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const submit = document.getElementById('formSubmit')
|
||||
submitClone = document.getElementById('formSubmitClone');
|
||||
|
|
|
|||
|
|
@ -35,16 +35,22 @@ Route::prefix('bo')
|
|||
]
|
||||
);
|
||||
});
|
||||
Route::get('/login-error', function () {
|
||||
return view('bo.pages.login-error');
|
||||
});
|
||||
|
||||
Route::middleware('auth:backend')->group(function () {
|
||||
Route::get('/', [DashboardController::class, 'index'])->name('dashboard');
|
||||
|
||||
// * USERS.
|
||||
Route::resource('users', UserController::class)->except('show');
|
||||
Route::patch('/users/{user}/change-published', [
|
||||
UserController::class, 'changePublished'
|
||||
UserController::class,
|
||||
'changePublished'
|
||||
])->name('users.change-published');
|
||||
Route::get('/users/{user}/duplicate', [
|
||||
UserController::class, 'duplicate'
|
||||
UserController::class,
|
||||
'duplicate'
|
||||
])->name('users.duplicate');
|
||||
|
||||
// * STATIC PAGES.
|
||||
|
|
@ -63,13 +69,16 @@ Route::prefix('bo')
|
|||
->withoutMiddleware('htmlsanitize')
|
||||
->middleware('htmlsanitize:content,introduction');
|
||||
Route::patch('/news/{news}/change-published', [
|
||||
NewsController::class, 'changePublished'
|
||||
NewsController::class,
|
||||
'changePublished'
|
||||
])->name('news.change-published');
|
||||
Route::patch('/news/{news}/change-order/{direction}', [
|
||||
NewsController::class, 'changeOrder'
|
||||
NewsController::class,
|
||||
'changeOrder'
|
||||
])->where('direction', 'up|down')->name('news.change-order');
|
||||
Route::get('/news/{news}/duplicate', [
|
||||
NewsController::class, 'duplicate'
|
||||
NewsController::class,
|
||||
'duplicate'
|
||||
])->name('news.duplicate');
|
||||
|
||||
// * SITES.
|
||||
|
|
@ -77,29 +86,34 @@ Route::prefix('bo')
|
|||
->withoutMiddleware('htmlsanitize')
|
||||
->middleware('htmlsanitize:director_speach,employee_speach,highlights,content');
|
||||
Route::patch('/sites/{site}/change-order/{direction}', [
|
||||
SiteController::class, 'changeOrder'
|
||||
SiteController::class,
|
||||
'changeOrder'
|
||||
])->where('direction', 'up|down')->name('sites.change-order');
|
||||
Route::get('/sites/{site}/duplicate', [
|
||||
SiteController::class, 'duplicate'
|
||||
SiteController::class,
|
||||
'duplicate'
|
||||
])->name('sites.duplicate');
|
||||
|
||||
// * LOGOS.
|
||||
Route::resource('logos', LogoController::class)->except('show');
|
||||
Route::get('/logos/{logo}/duplicate', [
|
||||
LogoController::class, 'duplicate'
|
||||
LogoController::class,
|
||||
'duplicate'
|
||||
])->name('logos.duplicate');
|
||||
|
||||
// * HISTORICAL MILESTONES.
|
||||
Route::resource('historicalmilestones', HistoricalMilestoneController::class)->except('show')
|
||||
->parameters(['historicalmilestones' => 'historical_milestone']);
|
||||
Route::get('/historicalmilestones/{historical_milestone}/duplicate', [
|
||||
HistoricalMilestoneController::class, 'duplicate'
|
||||
HistoricalMilestoneController::class,
|
||||
'duplicate'
|
||||
])->name('historicalmilestones.duplicate');
|
||||
|
||||
// * SLIDES.
|
||||
Route::resource('slides', SlideController::class)->except('show');
|
||||
Route::get('/slides/{slide}/duplicate', [
|
||||
SlideController::class, 'duplicate'
|
||||
SlideController::class,
|
||||
'duplicate'
|
||||
])->name('slides.duplicate');
|
||||
|
||||
// * STRIPS.
|
||||
|
|
@ -107,10 +121,12 @@ Route::prefix('bo')
|
|||
->withoutMiddleware('htmlsanitize')
|
||||
->middleware('htmlsanitize:text');
|
||||
Route::patch('/strips/{strip}/change-published', [
|
||||
StripController::class, 'changePublished'
|
||||
StripController::class,
|
||||
'changePublished'
|
||||
])->name('strips.change-published');
|
||||
Route::get('/strips/{strip}/duplicate', [
|
||||
StripController::class, 'duplicate'
|
||||
StripController::class,
|
||||
'duplicate'
|
||||
])->name('strips.duplicate');
|
||||
|
||||
// * SECTIONS.
|
||||
|
|
@ -128,7 +144,8 @@ Route::prefix('bo')
|
|||
Route::resource('jobvideos', JobVideoController::class)->except('show')
|
||||
->parameters(['jobvideos' => 'job_video']);
|
||||
Route::get('/jobvideos/{job_video}/duplicate', [
|
||||
JobVideoController::class, 'duplicate'
|
||||
JobVideoController::class,
|
||||
'duplicate'
|
||||
])->name('jobvideos.duplicate');
|
||||
|
||||
// * TESTIMONIALS.
|
||||
|
|
@ -136,7 +153,8 @@ Route::prefix('bo')
|
|||
->withoutMiddleware('htmlsanitize')
|
||||
->middleware('htmlsanitize:content');
|
||||
Route::get('/testimonials/{testimonial}/duplicate', [
|
||||
TestimonialController::class, 'duplicate'
|
||||
TestimonialController::class,
|
||||
'duplicate'
|
||||
])->name('testimonials.duplicate');
|
||||
|
||||
Route::middleware('can:isConceptor')->group(function () {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue