Compare commits
112 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6315c452cb | ||
|
|
7b7b456ef2 | ||
|
|
8d3d646403 | ||
|
|
666d79b32f | ||
|
|
3ed4e6a99f | ||
|
|
80e21dabb7 | ||
|
|
f6b5dcb42c | ||
|
|
df39b81e40 | ||
|
|
e86852de81 | ||
|
|
d7c69379c1 | ||
|
|
9b2e54a6a3 | ||
|
|
9bf67ce627 | ||
|
|
83cd90096e | ||
|
|
4656dd598e | ||
|
|
6bca2d4a13 | ||
|
|
aefaf9a0b1 | ||
|
|
5f16591b85 | ||
|
|
aa7715c19c | ||
|
|
53fa87fa17 | ||
|
|
ecaff7a068 | ||
|
|
ab85b33052 | ||
|
|
cb8eae4a18 | ||
|
|
d13760ce4f | ||
|
|
e418f01712 | ||
|
|
5eb1df950a | ||
|
|
a56e9a3e63 | ||
|
|
3b6801dc35 | ||
|
|
84c28399ab | ||
|
|
1b0ec6a3d8 | ||
|
|
4338023e59 | ||
|
|
7b9e6cc094 | ||
|
|
0cbf60cf03 | ||
|
|
94156c7db0 | ||
|
|
59752b3b2e | ||
|
|
29108f8e28 | ||
|
|
bc96ef44b0 | ||
|
|
b4159f0c83 | ||
|
|
eed1ce86d5 | ||
|
|
6e3f65b9ea | ||
|
|
72c0652434 | ||
|
|
6f33b697e6 | ||
|
|
4e596fb2b9 | ||
|
|
3fef79fa72 | ||
|
|
45e298f2a9 | ||
|
|
ec39bb4f6f | ||
|
|
0b8b1bff0a | ||
|
|
b0508da89d | ||
|
|
fb94fcb1f6 | ||
|
|
8de072695b | ||
|
|
3db48686ee | ||
|
|
28625f2bf2 | ||
|
|
b658db5bf7 | ||
|
|
95d552c429 | ||
|
|
76b8b61288 | ||
|
|
e8871467c0 | ||
|
|
77ad125ad2 | ||
|
|
dcf995bdc6 | ||
|
|
29016ad3ba | ||
|
|
e1961fab93 | ||
|
|
fa7d44d03d | ||
|
|
4d363f8fac | ||
|
|
80a394691c | ||
|
|
1648636bfa | ||
|
|
159cbbebe7 | ||
|
|
a53cfc7d55 | ||
|
|
c498e298d8 | ||
|
|
e2d3d7ec28 | ||
|
|
bed9d9dde6 | ||
|
|
19f6454ea3 | ||
|
|
ffdd886ddc | ||
|
|
0d17174052 | ||
|
|
50a99c7344 | ||
|
|
41dba737cb | ||
|
|
ae4ab562dc | ||
|
|
a04a65c232 | ||
|
|
fd987180bb | ||
|
|
58d359155f | ||
|
|
1532e3a31d | ||
|
|
8e9f7f8419 | ||
|
|
d5c0c06294 | ||
|
|
0333649f48 | ||
|
|
6d482c4631 | ||
|
|
14b0382cdb | ||
|
|
54e501cd03 | ||
|
|
d162f87f3e | ||
|
|
1f1d691cbe | ||
|
|
be80ca6c6a | ||
|
|
bf365eadca | ||
|
|
28a8390c41 | ||
|
|
6ee0986b48 | ||
|
|
239307c1b1 | ||
|
|
81089b8e12 | ||
|
|
30ee51d9d1 | ||
|
|
398c762b33 | ||
|
|
a952ea6ac6 | ||
|
|
8318e83d0b | ||
|
|
25d9e1cac6 | ||
|
|
cffa0f34a8 | ||
|
|
9a8e0f8f9a | ||
|
|
5854fc274b | ||
|
|
608629307f | ||
|
|
b32f5161b3 | ||
|
|
f06e87daf5 | ||
|
|
13d998ac9c | ||
|
|
fed7a112c2 | ||
|
|
f34bb70504 | ||
|
|
53ccbb5af8 | ||
|
|
8949c3b427 | ||
|
|
1963b827d8 | ||
|
|
256a8b5542 | ||
|
|
6c63d52996 | ||
|
|
b557533b72 |
237 changed files with 10309 additions and 9335 deletions
43
.env.example
43
.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
|
||||
|
|
@ -23,12 +22,6 @@ QUEUE_CONNECTION=sync
|
|||
SESSION_DRIVER=file
|
||||
SESSION_LIFETIME=120
|
||||
|
||||
MEMCACHED_HOST=127.0.0.1
|
||||
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
MAIL_MAILER=smtp
|
||||
MAIL_HOST=mailpit
|
||||
MAIL_PORT=1025
|
||||
|
|
@ -37,26 +30,8 @@ MAIL_PASSWORD=null
|
|||
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}"
|
||||
MAIL_CONTACTFORM_RECEIVER=
|
||||
MAIL_CONTACTFORM_CUSTOMER_SERVICE_RECEIVER=
|
||||
|
||||
# Sentry
|
||||
SENTRY_LARAVEL_DSN=
|
||||
|
|
@ -69,3 +44,17 @@ MATOMO_SITE_ID=
|
|||
GOOGLE_RECAPTCHA_PUBLIC=
|
||||
GOOGLE_RECAPTCHA_PRIVATE=
|
||||
GOOGLE_RECAPTCHA_VERSION=
|
||||
|
||||
# UWIL ADMIN SECURE
|
||||
# - LIST SEPARATED WITH ',' (Required)
|
||||
UWIL_ADMIN_SECURE_CIDR_LIST=""
|
||||
# - LIST SEPARATED WITH ',' (Optional)
|
||||
UWIL_ADMIN_SECURE_CIDR_PROJECT_ALLOWED_LIST=""
|
||||
|
||||
|
||||
# SAML
|
||||
SAML2_DEFAULT_TENANT_UUID=
|
||||
SAML2_SP_CERT_x509=
|
||||
SAML2_SP_CERT_PRIVATEKEY=
|
||||
SAML2_CONTACT_TECHNICAL_EMAIL=
|
||||
SAML2_CONTACT_SUPPORT_EMAIL=
|
||||
|
|
|
|||
13
.gitignore
vendored
13
.gitignore
vendored
|
|
@ -23,3 +23,16 @@ Homestead.yaml
|
|||
npm-debug.log
|
||||
yarn-error.log
|
||||
.npmrc
|
||||
|
||||
# Ignore public favicon
|
||||
/public/android-chrome-192x192.png
|
||||
/public/android-chrome-512x512.png
|
||||
/public/apple-touch-icon.png
|
||||
/public/browserconfig.xml
|
||||
/public/browserconfig.xml
|
||||
/public/favicon-16x16.png
|
||||
/public/favicon-32x32.png
|
||||
/public/favicon.ico
|
||||
/public/mstile-150x150.png
|
||||
/public/safari-pinned-tab.svg
|
||||
/public/site.webmanifest
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ include:
|
|||
file: 'security/security.yml'
|
||||
- project: 'ldc-web/shared-ci'
|
||||
ref: 'main'
|
||||
file: 'build/build.yml'
|
||||
file: 'build/docker-multistage.yml'
|
||||
- project: 'ldc-web/shared-ci'
|
||||
ref: 'main'
|
||||
file: 'test/test.yml'
|
||||
|
|
|
|||
45
Dockerfile
Normal file
45
Dockerfile
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
FROM composer:2.8 AS vendor
|
||||
|
||||
ARG GITLAB_USER
|
||||
ARG GITLAB_PASSWORD
|
||||
|
||||
COPY database/ database/
|
||||
|
||||
COPY composer.json composer.json
|
||||
COPY composer.lock composer.lock
|
||||
|
||||
RUN composer config gitlab-token.lab.s-web.fr ${GITLAB_USER} ${GITLAB_PASSWORD}
|
||||
RUN composer install \
|
||||
--ignore-platform-reqs \
|
||||
--no-interaction \
|
||||
--no-plugins \
|
||||
--no-scripts \
|
||||
--no-dev \
|
||||
--prefer-dist
|
||||
|
||||
FROM node:20.18 AS frontend
|
||||
|
||||
ARG GITLAB_PASSWORD
|
||||
|
||||
RUN mkdir -p /app/public/build
|
||||
|
||||
COPY package*.json tsconfig.json vite.config.ts .eslintrc.json .stylelintrc.json /app/
|
||||
COPY resources/ /app/resources/
|
||||
WORKDIR /app
|
||||
RUN npm config set @ldc-web:registry https://lab.s-web.fr/api/v4/packages/npm/
|
||||
RUN npm config set -- '//lab.s-web.fr/api/v4/packages/npm/:_authToken' "${GITLAB_PASSWORD}"
|
||||
RUN npm ci && npm run prod
|
||||
|
||||
ARG PHP_8_5_TAG=latest
|
||||
FROM registry.s-web.fr/ldc-web/projets/ldc-web-images-docker/uwil-production-8.5:${PHP_8_5_TAG}
|
||||
|
||||
ARG USER=www-data
|
||||
|
||||
COPY --chown=${USER}:${USER} . /app/srcs
|
||||
COPY --chown=${USER}:${USER} ./resources/favicon /app/srcs/public
|
||||
COPY --from=vendor --chown=${USER}:${USER} /app/vendor/ /app/srcs/vendor/
|
||||
COPY --from=frontend --chown=${USER}:${USER} /app/public/build/ /app/srcs/public/build/
|
||||
|
||||
USER root
|
||||
RUN chmod -R 755 /app/srcs/storage
|
||||
USER ${USER}
|
||||
|
|
@ -1 +1,7 @@
|
|||
# Agis
|
||||
|
||||
## CRON
|
||||
Put every min in PROD :
|
||||
```
|
||||
php artisan schedule:run
|
||||
```
|
||||
|
|
@ -28,35 +28,28 @@ class UserCreate extends Command
|
|||
/**
|
||||
* The first name of the new user.
|
||||
*
|
||||
* @var string
|
||||
* @var string|null
|
||||
*/
|
||||
protected $first_name;
|
||||
|
||||
/**
|
||||
* The last name of the new user.
|
||||
*
|
||||
* @var string
|
||||
* @var string|null
|
||||
*/
|
||||
protected $last_name;
|
||||
|
||||
/**
|
||||
* The email of the new user.
|
||||
*
|
||||
* @var string
|
||||
* @var string|null
|
||||
*/
|
||||
protected $email;
|
||||
|
||||
/**
|
||||
* The password of the new user.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $password;
|
||||
|
||||
/**
|
||||
* The role of the new user.
|
||||
*
|
||||
* @var string
|
||||
* @var string|null
|
||||
*/
|
||||
protected $role;
|
||||
|
||||
|
|
@ -76,9 +69,6 @@ class UserCreate extends Command
|
|||
$this->email = null;
|
||||
$this->addEmail();
|
||||
|
||||
$this->password = null;
|
||||
$this->addPassword();
|
||||
|
||||
$this->role = null;
|
||||
$this->addRole();
|
||||
|
||||
|
|
@ -86,7 +76,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(),
|
||||
|
|
@ -173,22 +162,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.
|
||||
*
|
||||
|
|
@ -202,8 +175,6 @@ class UserCreate extends Command
|
|||
'Select his role',
|
||||
[RoleEnum::conceptor->label(), RoleEnum::admin->label(), RoleEnum::visitor->label()],
|
||||
RoleEnum::visitor->label(),
|
||||
$maxAttempts = null,
|
||||
$allowMultipleSelections = false
|
||||
);
|
||||
if ($tmp === RoleEnum::conceptor->label()) {
|
||||
$tmp = RoleEnum::conceptor;
|
||||
|
|
@ -219,7 +190,7 @@ class UserCreate extends Command
|
|||
$this->role = $tmp;
|
||||
} catch (ValidationException $e) {
|
||||
$this->error(sprintf(
|
||||
'Please choose from the selection',
|
||||
'Please choose from the selection %s',
|
||||
\implode(',', collect($e->errors())->flatten()->all())
|
||||
));
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ enum ActivityLogsEventEnum: int
|
|||
|
||||
/**
|
||||
* Optionnal labels definition
|
||||
*
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private const LABELS = [
|
||||
self::created->name => 'Création',
|
||||
|
|
|
|||
|
|
@ -13,9 +13,11 @@ enum CivilityEnum: int
|
|||
|
||||
/**
|
||||
* Optionnal labels definition
|
||||
*
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private const LABELS = [
|
||||
self::man->name => 'Homme',
|
||||
self::woman->name => 'Femme',
|
||||
self::man->name => 'Monsieur',
|
||||
self::woman->name => 'Madame',
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ enum ObjectEnum: int
|
|||
|
||||
/**
|
||||
* Optionnal labels definition
|
||||
*
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private const LABELS = [
|
||||
self::customerService->name => 'Service consommateurs',
|
||||
|
|
|
|||
|
|
@ -260,6 +260,8 @@ enum Country: int
|
|||
|
||||
/**
|
||||
* Optionnal labels definition
|
||||
*
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private const LABELS = [
|
||||
self::afghanistan->name => 'Afghanistan',
|
||||
|
|
|
|||
27
app/Enums/DesiredLocation.php
Normal file
27
app/Enums/DesiredLocation.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
use App\Traits\Enums\BaseEnum;
|
||||
|
||||
enum DesiredLocation: int
|
||||
{
|
||||
use BaseEnum;
|
||||
|
||||
case avignon = 1;
|
||||
case herbignac = 2;
|
||||
case tarare = 3;
|
||||
case none = 4;
|
||||
|
||||
/**
|
||||
* Optionnal labels definition.
|
||||
*
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private const LABELS = [
|
||||
self::avignon->name => 'Avignon',
|
||||
self::herbignac->name => 'Herbignac',
|
||||
self::tarare->name => 'Tarare',
|
||||
self::none->name => 'Indifférent',
|
||||
];
|
||||
}
|
||||
|
|
@ -16,6 +16,8 @@ enum CategoryEnum: int
|
|||
|
||||
/**
|
||||
* Optionnal labels definition.
|
||||
*
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private const LABELS = [
|
||||
self::enterprise->name => 'La vie d\'Entreprise',
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ enum CookingModeEnum: int
|
|||
|
||||
/**
|
||||
* Optionnal labels definition.
|
||||
*
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private const LABELS = [
|
||||
self::microwave->name => 'Micro-ondes',
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ enum BackgroundEnum: int
|
|||
|
||||
/**
|
||||
* Optionnal labels definition.
|
||||
*
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private const LABELS = [
|
||||
self::candlemas->name => 'Chandeleur',
|
||||
|
|
|
|||
|
|
@ -21,10 +21,12 @@ enum StaticPageType: int
|
|||
|
||||
/**
|
||||
* Optionnal labels definition.
|
||||
*
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private const LABELS = [
|
||||
self::contact->name => 'Contact',
|
||||
self::legals->name => 'Mentions légales',
|
||||
self::legals->name => 'Mentions légales et CGU',
|
||||
self::confidentiality->name => 'Confidentialité',
|
||||
self::home->name => 'Accueil',
|
||||
self::conviction->name => 'Nos Convictions',
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ enum BootstrapThemeEnum: int
|
|||
|
||||
/**
|
||||
* Optionnal labels definition
|
||||
*
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private const LABELS = [
|
||||
self::light->name => 'Light',
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ enum RoleEnum: int
|
|||
|
||||
/**
|
||||
* Optionnal labels definition.
|
||||
*
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private const LABELS = [
|
||||
self::conceptor->name => 'Concepteur',
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ class ActivityLogsController extends Controller
|
|||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param App\Models\ActivityLog $activity_log
|
||||
* @param \App\Models\ActivityLog $activity_log
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function show(ActivityLog $activity_log): \Illuminate\Contracts\View\View
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ class CommitmentController extends Controller
|
|||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param App\Models\Commitment $commitment
|
||||
* @param \App\Models\Commitment $commitment
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit(Commitment $commitment): \Illuminate\Contracts\View\View
|
||||
|
|
@ -139,7 +139,7 @@ class CommitmentController extends Controller
|
|||
{
|
||||
$commitment->products()->detach();
|
||||
|
||||
if ($commitment->explorerpage()->count() > 3) {
|
||||
if ($commitment->explorerpage()->count() === 0) {
|
||||
if ($commitment->deleteOrFail()) {
|
||||
return redirect()->route('bo.commitments.index')
|
||||
->with('success', __('crud.messages.has_been_deleted', [
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class JoinuspageController extends Controller
|
|||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\Joinuspages\UpdateJoinuspageRequest $request
|
||||
* @param \App\Http\Requests\Bo\Joinuspage\UpdateJoinuspageRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(UpdateJoinuspageRequest $request): \Illuminate\Http\RedirectResponse
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ class NewsController extends Controller
|
|||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param App\Models\News $news
|
||||
* @param \App\Models\News $news
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit(News $news): \Illuminate\Contracts\View\View
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ class ProductController extends Controller
|
|||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param App\Models\Product $product
|
||||
* @param \App\Models\Product $product
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit(Product $product): \Illuminate\Contracts\View\View
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ class RangeController extends Controller
|
|||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param App\Models\Range $range
|
||||
* @param \App\Models\Range $range
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit(Range $range): \Illuminate\Contracts\View\View
|
||||
|
|
@ -143,7 +143,9 @@ class RangeController extends Controller
|
|||
*/
|
||||
public function destroy(Range $range): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
if (!$range->products->isEmpty()) {
|
||||
/** @var \Illuminate\Database\Eloquent\Collection $products*/
|
||||
$products = $range->products;
|
||||
if (!$products->isEmpty()) {
|
||||
return redirect()->back()
|
||||
->with('error', __('crud.messages.cannot_be_deleted_relation', [
|
||||
'model' => Str::ucfirst(__('models.classes.range')),
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ class SeasonalSectionController extends Controller
|
|||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param App\Models\SeasonalSection $seasonalSection
|
||||
* @param \App\Models\SeasonalSection $seasonalSection
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit(SeasonalSection $seasonalSection): \Illuminate\Contracts\View\View
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ class StampController extends Controller
|
|||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param App\Models\Stamp $stamp
|
||||
* @param \App\Models\Stamp $stamp
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit(Stamp $stamp): \Illuminate\Contracts\View\View
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ class StaticPageController extends Controller
|
|||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param App\Models\StaticPage $static_page
|
||||
* @param \App\Models\StaticPage $static_page
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit(StaticPage $static_page): \Illuminate\Contracts\View\View
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ class TestimonialController extends Controller
|
|||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param App\Models\Testimonial $testimonial
|
||||
* @param \App\Models\Testimonial $testimonial
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit(Testimonial $testimonial): \Illuminate\Contracts\View\View
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ class UsersController extends Controller
|
|||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param App\Models\User $user
|
||||
* @param \App\Models\User $user
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit(User $user): \Illuminate\Contracts\View\View
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class Controller extends BaseController
|
|||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query The eloquent query builder.
|
||||
* @param string $search The query string.
|
||||
* @param callable $searchQuery The query string.
|
||||
* @param callable|null $searchQuery The query string.
|
||||
* @param string ...$fields Either a simple array or a string
|
||||
* in case of a string the two fields
|
||||
* would be concatenate to make the search.
|
||||
|
|
@ -35,7 +35,7 @@ class Controller extends BaseController
|
|||
protected function searchQuery(
|
||||
Builder $query,
|
||||
string $search,
|
||||
callable $searchQuery = null,
|
||||
callable|null $searchQuery = null,
|
||||
string ...$fields
|
||||
): \Illuminate\Database\Eloquent\Builder {
|
||||
if (count($fields)) {
|
||||
|
|
@ -94,7 +94,7 @@ class Controller extends BaseController
|
|||
return $query;
|
||||
}
|
||||
// Get models with relation's name/label.
|
||||
if (Str::endsWith($field, '_id') && $query->getModel()->has(Str::remove('_id', $field))) {
|
||||
if (Str::endsWith($field, '_id')) {
|
||||
$query->orWhereHas(Str::remove('_id', $field), function ($queryRelation) use ($field, $search) {
|
||||
if (Schema::hasColumn(Str::remove('_id', $field) . 's', 'name')) {
|
||||
$queryRelation->where('name', 'like', '%' . $search . '%');
|
||||
|
|
@ -122,12 +122,15 @@ class Controller extends BaseController
|
|||
*/
|
||||
protected function getSearchValue(Builder $query, string $search, string $field): string|array
|
||||
{
|
||||
$cast = $query->getModel()->getCasts()[$field] ?? null;
|
||||
if (
|
||||
count($query->getModel()->getCasts()) and // Check if the model has casts.
|
||||
isset($query->getModel()->getCasts()[$field]) and // Check if there is cast about specific field.
|
||||
enum_exists($query->getModel()->getCasts()[$field]) // Check if the cast is an enum.
|
||||
$cast and // Check if there is cast about specific field.
|
||||
enum_exists($cast) // Check if the cast is an enum.
|
||||
) {
|
||||
$cases = collect($query->getModel()->getCasts()[$field]::toArray());
|
||||
/** @var \App\Traits\Enums $cast */
|
||||
// @phpstan-ignore-next-line
|
||||
$cases = collect($cast::toArray());
|
||||
$enum = $cases->filter(function ($item) use ($search) {
|
||||
return preg_match('/' . Str::lower($search) . '/', Str::lower($item->label));
|
||||
});
|
||||
|
|
@ -148,12 +151,12 @@ class Controller extends BaseController
|
|||
{
|
||||
$rName = request()->route()->getName();
|
||||
$table = $query->getModel()->getTable();
|
||||
if (request()->sort_col) {
|
||||
Session::put("$rName.sort_col", request()->sort_col);
|
||||
if (request()->input('sort_col')) {
|
||||
Session::put("$rName.sort_col", request()->input('sort_col'));
|
||||
Session::put("$rName.sorted", true);
|
||||
}
|
||||
if (request()->sort_way) {
|
||||
Session::put("$rName.sort_way", request()->sort_way);
|
||||
if (request()->input('sort_way')) {
|
||||
Session::put("$rName.sort_way", request()->input('sort_way'));
|
||||
Session::put("$rName.sorted", true);
|
||||
}
|
||||
if (request()->rst) {
|
||||
|
|
@ -161,12 +164,16 @@ class Controller extends BaseController
|
|||
Session::remove("$rName.sort_col");
|
||||
Session::remove("$rName.sort_way");
|
||||
}
|
||||
if (request()->sort_col and request()->sort_way and Schema::hasColumn($table, request()->sort_col)) {
|
||||
if (
|
||||
!isset($ignore) or
|
||||
(isset($ignore) and !in_array(request()->sort_col, $ignore))
|
||||
request()->input('sort_col') and
|
||||
request()->input('sort_way') and
|
||||
Schema::hasColumn($table, request()->input('sort_col'))
|
||||
) {
|
||||
$query = $query->orderBy(\sprintf("$table.%s", request()->sort_col), request()->sort_way);
|
||||
if (!in_array(request()->input('sort_col'), $ignore)) {
|
||||
$query = $query->orderBy(
|
||||
\sprintf("$table.%s", request()->input('sort_col')),
|
||||
request()->input('sort_way')
|
||||
);
|
||||
}
|
||||
} elseif (Schema::hasColumn($table, 'order')) {
|
||||
$query = $query->orderBy('order', 'ASC');
|
||||
|
|
@ -193,7 +200,7 @@ class Controller extends BaseController
|
|||
*/
|
||||
protected function paginate(
|
||||
Builder $query,
|
||||
ItemsPerPaginationEnum $pagination = null
|
||||
ItemsPerPaginationEnum|null $pagination = null
|
||||
): \Illuminate\Contracts\Pagination\LengthAwarePaginator {
|
||||
$currentRoutePath = Str::slug(request()->route()->getName());
|
||||
$cacheKey = "pagination.{$currentRoutePath}";
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ class NewsController extends Controller
|
|||
|
||||
/** @var \App\Models\News $newsModels */
|
||||
$newsModels = News::query()->where('published', true)->orderBy('publish_at', 'desc')->paginate(12);
|
||||
|
||||
return view('fo.pages.news.index', \compact('staticPageModel', 'newsModels'));
|
||||
}
|
||||
|
||||
|
|
@ -62,7 +63,7 @@ class NewsController extends Controller
|
|||
})
|
||||
->orderBy('publish_at', 'desc')
|
||||
->get();
|
||||
$newsModels = CollectionHelper::paginateManually($newsModels, 12, request()->page);
|
||||
$newsModels = CollectionHelper::paginateManually($newsModels, 12, request()->page ?? 1);
|
||||
return response()->json($newsModels);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Http\Controllers\Fo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Lib\Helpers\CollectionHelper;
|
||||
use App\Models\Product;
|
||||
|
||||
class ProductController extends Controller
|
||||
|
|
@ -10,16 +11,35 @@ class ProductController extends Controller
|
|||
/**
|
||||
* Display the product page.
|
||||
*
|
||||
* @param \App\Models\Product $product
|
||||
* @param string $slug
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function show(Product $product): \Illuminate\Contracts\View\View
|
||||
public function show(string $slug): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$otherProductModels = $product->range->products()
|
||||
->where('id', '!=', $product->id)
|
||||
$productModel = Product::query()->where('slug', $slug)->firstOrFail();
|
||||
|
||||
$otherProductModels = $productModel->range->products()
|
||||
->where('id', '!=', $productModel->id)
|
||||
->where('published', true)
|
||||
->inRandomOrder()
|
||||
->get();
|
||||
return view('fo.pages.products.show', compact('product', 'otherProductModels'));
|
||||
|
||||
return view('fo.pages.products.show', compact('productModel', 'otherProductModels'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get filtered products.
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function productsFiltered(): \Illuminate\Http\JsonResponse
|
||||
{
|
||||
$productModels = Product::query()
|
||||
->where('published', true)
|
||||
->where('range_id', request()->range_id)
|
||||
->orderBy('order', 'asc')
|
||||
->get();
|
||||
$productModels = CollectionHelper::paginateManually($productModels, 12, request()->page ?? 1);
|
||||
return response()->json($productModels);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace App\Http\Controllers\Fo;
|
|||
|
||||
use App\Enums\StaticPageType;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Lib\Helpers\CollectionHelper;
|
||||
use App\Models\Product;
|
||||
use App\Models\Range;
|
||||
use App\Models\StaticPage;
|
||||
|
|
@ -17,12 +18,12 @@ class RangeController extends Controller
|
|||
*/
|
||||
public function index(): \Illuminate\Contracts\View\View
|
||||
{
|
||||
/** @var \App\Models\Range $rangeModels */
|
||||
$rangeModels = Range::query()->where('published', true)->orderBy('order')->get();
|
||||
|
||||
/** @var \App\Models\StaticPage $staticPageModel */
|
||||
$staticPageModel = StaticPage::query()->where('type', StaticPageType::ranges)->firstOrFail();
|
||||
|
||||
/** @var \App\Models\Range $rangeModels */
|
||||
$rangeModels = Range::query()->where('published', true)->orderBy('order')->paginate(12);
|
||||
|
||||
return view('fo.pages.ranges.index', compact('rangeModels', 'staticPageModel'));
|
||||
}
|
||||
|
||||
|
|
@ -38,8 +39,27 @@ class RangeController extends Controller
|
|||
$rangeModel = Range::query()->where('published', true)->where('slug', $slug)->firstOrFail();
|
||||
|
||||
/** @var \App\Models\Product $productModels */
|
||||
$productModels = Product::query()->where('range_id', $rangeModel->id)->where('published', true)->get();
|
||||
$productModels = Product::query()
|
||||
->where('range_id', $rangeModel->id)
|
||||
->where('published', true)
|
||||
->orderBy('order')
|
||||
->paginate(12);
|
||||
|
||||
return view('fo.pages.ranges.show', compact('rangeModel', 'productModels'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get filtered ranges.
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function rangesFiltered(): \Illuminate\Http\JsonResponse
|
||||
{
|
||||
$productModels = Range::query()
|
||||
->where('published', true)
|
||||
->orderBy('order', 'asc')
|
||||
->get();
|
||||
$productModels = CollectionHelper::paginateManually($productModels, 12, request()->page ?? 1);
|
||||
return response()->json($productModels);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Http\Controllers\Fo;
|
||||
|
||||
use App\Enums\Contact\ObjectEnum;
|
||||
use App\Enums\StaticPageType;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Fo\ContactRequest;
|
||||
|
|
@ -27,7 +28,7 @@ class StaticPageController extends Controller
|
|||
* @param \App\Models\StaticPage $aboutUsPage
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function aboutUs(StaticPage $aboutUsPage)
|
||||
public function aboutUs(StaticPage $aboutUsPage): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$aboutUsPage = StaticPage::query()->where('type', StaticPageType::aboutus)
|
||||
->get();
|
||||
|
|
@ -40,7 +41,7 @@ class StaticPageController extends Controller
|
|||
* @param \App\Models\StaticPage $legalPage
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function legals(StaticPage $legalPage)
|
||||
public function legals(StaticPage $legalPage): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$legalPage = StaticPage::query()->where('type', StaticPageType::legals)->get();
|
||||
return view('fo.pages.legals', ['staticPageModel' => $legalPage[0]]);
|
||||
|
|
@ -52,7 +53,7 @@ class StaticPageController extends Controller
|
|||
* @param \App\Models\StaticPage $policiesPage
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function policies(StaticPage $policiesPage)
|
||||
public function policies(StaticPage $policiesPage): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$policiesPage = StaticPage::query()->where('type', StaticPageType::confidentiality)->get();
|
||||
return view('fo.pages.legals', ['staticPageModel' => $policiesPage[0]]);
|
||||
|
|
@ -103,14 +104,22 @@ class StaticPageController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
* Handle contactForm Request
|
||||
*
|
||||
* @param \App\Http\Requests\Fo\ContactRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function contactForm(ContactRequest $request): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
Mail::to(\config('mail.from.address'))->send(new SendContactMail((object)$request->validated()));
|
||||
if ($request->object === strval(ObjectEnum::customerService->value())) {
|
||||
$receivers = \config('mail.contactform.customerService');
|
||||
} else {
|
||||
$receivers = \config('mail.contactform.receiver');
|
||||
}
|
||||
|
||||
foreach ($receivers as $email) {
|
||||
Mail::to($email)->send(new SendContactMail((object)$request->validated()));
|
||||
}
|
||||
|
||||
return redirect()->route('fo.contact.show')
|
||||
->with(
|
||||
|
|
@ -177,14 +186,17 @@ class StaticPageController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
* Handle joinusForm Request
|
||||
*
|
||||
* @param \App\Http\Requests\Fo\JoinusRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function joinusForm(JoinusRequest $request): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
Mail::to(\config('mail.from.address'))->send(new SendJoinusMail((object)$request->validated()));
|
||||
$receivers = \config('mail.contactform.receiver');
|
||||
foreach ($receivers as $email) {
|
||||
Mail::to($email)->send(new SendJoinusMail((object)$request->validated()));
|
||||
}
|
||||
|
||||
return redirect()->route('fo.joinus.show')
|
||||
->with(
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
@ -65,5 +71,6 @@ class Kernel extends HttpKernel
|
|||
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
|
||||
'htmlsanitize' => \App\Http\Middleware\HtmlSanitizer::class,
|
||||
'local-development' => \App\Http\Middleware\LocalDevelopment::class,
|
||||
];
|
||||
}
|
||||
|
|
|
|||
25
app/Http/Middleware/LocalDevelopment.php
Normal file
25
app/Http/Middleware/LocalDevelopment.php
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class LocalDevelopment
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
if (app()->environment() != 'local') {
|
||||
return abort(403, 'You are not authorized to access this');
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
|
|
@ -59,12 +59,17 @@ class SecureHeaders
|
|||
config('app.debug') ? "https://{$host}:4443" : '',
|
||||
'https://yl.s-web.fr',
|
||||
]) . ';',
|
||||
"img-src * https://yl.s-web.fr data: blob:;",
|
||||
"img-src 'self' data: blob: " . implode(' ', [
|
||||
'https://yl.s-web.fr',
|
||||
// * VITE DEV
|
||||
config('app.debug') ? "https://{$host}:4443" : ''
|
||||
]) . ';',
|
||||
'frame-src ' . implode(' ', [
|
||||
'https://www.google.com/recaptcha/',
|
||||
'https://recaptcha.google.com/recaptcha/',
|
||||
'https://www.google.com/maps/',
|
||||
'https://www.youtube.com',
|
||||
'https://player.vimeo.com',
|
||||
]) . ';',
|
||||
"font-src 'self' data: " . \implode(' ', [
|
||||
// * VITE DEV
|
||||
|
|
@ -93,6 +98,7 @@ class SecureHeaders
|
|||
"$scheme://www.google-analytics.com",
|
||||
'https://www.google.com/recaptcha/',
|
||||
'https://www.gstatic.com/recaptcha/',
|
||||
'https://yl.s-web.fr',
|
||||
// * VITE DEV
|
||||
config('app.debug') ? "https://{$host}:4443" : '',
|
||||
]) . ';'
|
||||
|
|
@ -103,8 +109,11 @@ class SecureHeaders
|
|||
implode(' ', $cspPolicies) . $reportUri
|
||||
);
|
||||
$response->headers->set('Feature-Policy', \implode(',', [
|
||||
'fullscreen', 'accelerometer', 'encrypted-media',
|
||||
'gyroscope', 'picture-in-picture'
|
||||
'fullscreen',
|
||||
'accelerometer',
|
||||
'encrypted-media',
|
||||
'gyroscope',
|
||||
'picture-in-picture'
|
||||
]) . ';');
|
||||
return $response;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,14 +27,14 @@ class UpdateConvictionpageRequest extends FormRequest
|
|||
public function rules()
|
||||
{
|
||||
return [
|
||||
'key_feed' => 'required|numeric',
|
||||
'key_earth_1' => 'required|numeric',
|
||||
'key_earth_2' => 'required|numeric',
|
||||
'key_together_1' => 'required|numeric',
|
||||
'key_together_2' => 'required|numeric',
|
||||
'key_together_3' => 'required|numeric',
|
||||
'key_together_4' => 'required|numeric',
|
||||
'key_territory' => 'required|numeric',
|
||||
'key_feed' => 'required|numeric|max:2147483647',
|
||||
'key_earth_1' => 'required|numeric|max:2147483647',
|
||||
'key_earth_2' => 'required|numeric|max:2147483647',
|
||||
'key_together_1' => 'required|numeric|max:2147483647',
|
||||
'key_together_2' => 'required|numeric|max:2147483647',
|
||||
'key_together_3' => 'required|numeric|max:2147483647',
|
||||
'key_together_4' => 'required|numeric|max:2147483647',
|
||||
'key_territory' => 'required|numeric|max:2147483647',
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
namespace App\Http\Requests\Bo\Homepage;
|
||||
|
||||
use App\Rules\IsValidVimeoId;
|
||||
use App\Rules\IsValidYoutubeId;
|
||||
use App\Traits\Requests\HasPicture;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
|
|
@ -26,6 +28,9 @@ class UpdateHomepageRequest extends FormRequest
|
|||
*/
|
||||
protected function prepareForValidation()
|
||||
{
|
||||
$this->merge([
|
||||
'display_video' => $this->boolean('display_video')
|
||||
]);
|
||||
$this->mergePicture('picture');
|
||||
}
|
||||
|
||||
|
|
@ -44,10 +49,20 @@ class UpdateHomepageRequest extends FormRequest
|
|||
'picture_title' => 'required|string|between:3,255',
|
||||
'presentation_title' => 'required|string|between:3,255',
|
||||
'presentation_content' => 'required|string',
|
||||
'display_video' => 'present|boolean',
|
||||
'video_id' => [
|
||||
'nullable', 'required_if:display_video,true',
|
||||
function (string $attribute, mixed $value, \Closure $fail) {
|
||||
if (!IsValidYoutubeId::validates($value) and !IsValidVimeoId::validates($value)) {
|
||||
(new IsValidYoutubeId())->validate($attribute, $value, $fail);
|
||||
(new IsValidVimeoId())->validate($attribute, $value, $fail);
|
||||
}
|
||||
}
|
||||
],
|
||||
];
|
||||
return \array_merge(
|
||||
$rules,
|
||||
$this->pictureRules('picture', 640, 390, 640, 390, false),
|
||||
$this->pictureRules('picture', 640, 390, 640, 390, true, requiredIf: 'display_video,false'),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -59,6 +74,7 @@ class UpdateHomepageRequest extends FormRequest
|
|||
public function attributes(): array
|
||||
{
|
||||
return [
|
||||
'video_id' => trans('validation.custom.video_id'),
|
||||
'title_part1' => trans('validation.custom.title_part1'),
|
||||
'title_part2' => trans('validation.custom.title_part2'),
|
||||
'title_part3' => trans('validation.custom.title_part3'),
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
namespace App\Http\Requests\Bo\Joinuspage;
|
||||
|
||||
use App\Rules\IsValidVimeoId;
|
||||
use App\Rules\IsValidYoutubeId;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class UpdateJoinuspageRequest extends FormRequest
|
||||
|
|
@ -24,7 +26,15 @@ class UpdateJoinuspageRequest extends FormRequest
|
|||
public function rules()
|
||||
{
|
||||
return [
|
||||
'video_id' => 'required|string|regex:%([^"&?\/\s]{11})%i',
|
||||
'video_id' => [
|
||||
'required', 'string',
|
||||
function (string $attribute, mixed $value, \Closure $fail) {
|
||||
if (!IsValidYoutubeId::validates($value) and !IsValidVimeoId::validates($value)) {
|
||||
(new IsValidYoutubeId())->validate($attribute, $value, $fail);
|
||||
(new IsValidVimeoId())->validate($attribute, $value, $fail);
|
||||
}
|
||||
}
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ class StoreNewsRequest extends FormRequest
|
|||
'subtitle' => 'required|string|between:3,255',
|
||||
'content' => 'required|string|min:15',
|
||||
'published' => 'required|boolean',
|
||||
'publish_at' => 'nullable|date',
|
||||
'publish_at' => 'required|date',
|
||||
'unpublish_at' => 'nullable|date|after:publish_at',
|
||||
|
||||
];
|
||||
|
|
|
|||
|
|
@ -68,8 +68,8 @@ class StoreProductRequest extends FormRequest
|
|||
return \array_merge(
|
||||
$rules,
|
||||
$this->pictureRules('picture_thumbnail', 332, 252, 332, 252, false),
|
||||
$this->pictureRules('picture_ambiance', 774, 515, 774, 515, false),
|
||||
$this->pictureRules('picture_packshot', 327, 252, 327, 252, false),
|
||||
$this->pictureRules('picture_ambiance', 1115, 790, 1115, 790, false),
|
||||
$this->pictureRules('picture_packshot', 560, 480, 560, 480, false),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -89,35 +89,35 @@ class StoreProductRequest extends FormRequest
|
|||
// phpcs:enable
|
||||
$nutritionnal_values = json_encode([
|
||||
"energyKj" => [
|
||||
"label" => "Energie en Kj",
|
||||
"label" => "ÉNERGIE (kJ)",
|
||||
"value" => $this->nutritionnal_values['energy_kj'],
|
||||
],
|
||||
"energyKcal" => [
|
||||
"label" => "Energie en kcal",
|
||||
"label" => "ÉNERGIE (kcal)",
|
||||
"value" => $this->nutritionnal_values['energy_kcal'],
|
||||
],
|
||||
"fat" => [
|
||||
"label" => "Matières grasses",
|
||||
"label" => "MATIÈRES GRASSES (g)",
|
||||
"value" => $this->nutritionnal_values['fat'],
|
||||
],
|
||||
"saturated-fat" => [
|
||||
"label" => "dont acides gras saturés",
|
||||
"label" => "ACIDES GRAS SATURÉS (g)",
|
||||
"value" => $this->nutritionnal_values['saturated_fat'],
|
||||
],
|
||||
"carbohydrate" => [
|
||||
"label" => "Glucides",
|
||||
"label" => "GLUCIDES (g)",
|
||||
"value" => $this->nutritionnal_values['carbohydrate'],
|
||||
],
|
||||
"sugar" => [
|
||||
"label" => "dont sucres",
|
||||
"label" => "SUCRES (g)",
|
||||
"value" => $this->nutritionnal_values['sugar'],
|
||||
],
|
||||
"proteins" => [
|
||||
"label" => "Protéines",
|
||||
"label" => "PROTÉINES (g)",
|
||||
"value" => $this->nutritionnal_values['proteins'],
|
||||
],
|
||||
"salt" => [
|
||||
"label" => "Sel",
|
||||
"label" => "SEL (g)",
|
||||
"value" => $this->nutritionnal_values['salt'],
|
||||
]
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ class StoreRangeRequest extends FormRequest
|
|||
return \array_merge(
|
||||
$rules,
|
||||
$this->pictureRules('picture', 466, 440, 466, 440, false),
|
||||
$this->pictureRules('picture_productsheet', 332, 442, 332, 442, false),
|
||||
$this->pictureRules('picture_productsheet', 680, 300, 680, 300, false),
|
||||
$this->pictureRules('picture_thumbnail', 246, 337, 246, 337, false),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,8 +24,10 @@ class UpdateStaticPageRequest extends FormRequest
|
|||
*/
|
||||
public function prepareForValidation(): void
|
||||
{
|
||||
/** @var \App\Models\StaticPage $staticPageModel */
|
||||
$staticPageModel = $this->route('static_page');
|
||||
if (
|
||||
\in_array($this->route('static_page')->type, [
|
||||
\in_array($staticPageModel->type, [
|
||||
\App\Enums\StaticPageType::confidentiality,
|
||||
\App\Enums\StaticPageType::legals
|
||||
])
|
||||
|
|
|
|||
|
|
@ -1,229 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Bo;
|
||||
|
||||
use App\Enums\InputType;
|
||||
use App\Lib\Helpers\ToolboxHelper;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
abstract class UpdateMiniCrudRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* The model parameter name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $modelName = null;
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return auth('backend')->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
|
||||
* @phpcs:disable Generic.Metrics.NestingLevel.TooHigh
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
// phpcs:enable
|
||||
$rules = [];
|
||||
foreach ($this->{$this->modelName}->data as $iptName => $input) {
|
||||
$input = \json_decode(\json_encode($input), true);
|
||||
switch ($input['inputType']) {
|
||||
case InputType::number->value:
|
||||
$rules = array_merge($rules, [
|
||||
"data.$iptName.value" => $this->compileValidate('required|numeric', $input)
|
||||
]);
|
||||
break;
|
||||
case InputType::videoYoutube->value:
|
||||
$rules = array_merge($rules, [
|
||||
"data.$iptName.value" => $this->compileValidate('regex:%([^"&?\/\s]{11})%i', $input)
|
||||
]);
|
||||
break;
|
||||
case InputType::videoVimeo->value:
|
||||
$rules = array_merge($rules, [
|
||||
"data.$iptName.value" => $this->compileValidate('regex:%([0-9]{8,10})%i', $input)
|
||||
]);
|
||||
break;
|
||||
case InputType::video->value:
|
||||
$rules = array_merge($rules, [
|
||||
"data.$iptName.value" => $this->compileValidate([
|
||||
'regex:%([0-9]{8,10}|[^"&?\/\s]{11})%i'
|
||||
], $input)
|
||||
]);
|
||||
break;
|
||||
case InputType::string->value:
|
||||
$rules = array_merge($rules, [
|
||||
"data.$iptName.value" => $this->compileValidate('required|string|min:3', $input)
|
||||
]);
|
||||
break;
|
||||
case InputType::text->value:
|
||||
$mergeRules = $this->compileValidate('required|string|min:15', $input);
|
||||
$mergeRules = collect($mergeRules)
|
||||
->map(function ($rule) {
|
||||
if (\strpos($rule, 'max:') !== false) {
|
||||
$max = \intval(str_replace('max:', '', $rule));
|
||||
return function ($attribute, $value, $fail) use ($max) {
|
||||
if (\strlen(\strip_tags($value)) > $max) {
|
||||
$fail("$attribute ne doit pas excéder $max caractères");
|
||||
}
|
||||
};
|
||||
}
|
||||
return $rule;
|
||||
});
|
||||
$rules = array_merge($rules, [
|
||||
"data.$iptName.value" => $mergeRules
|
||||
]);
|
||||
break;
|
||||
case InputType::image->value:
|
||||
$required = $this->isUpdate() ? 'sometimes' : 'required';
|
||||
|
||||
$ipt = $this->data[$iptName];
|
||||
$max = isset($ipt['dimensionsMax']);
|
||||
$dim = \is_string($input['dimensions']) ? collect(explode(
|
||||
',',
|
||||
(isset($ipt['dimensionsMax']) and is_string($ipt['dimensionsMax'])) ?
|
||||
$ipt['dimensionsMax'] : $input['dimensions']
|
||||
))->mapWithKeys(function ($v) {
|
||||
$v = explode(' ', $v);
|
||||
return [$v[0] => $v[1]];
|
||||
}) : $input['dimensions'];
|
||||
|
||||
// * Adapt dimensions
|
||||
$sizes = (object)[
|
||||
'minHeight' => $dim['height'],
|
||||
'maxHeight' => $dim['height'],
|
||||
'minWith' => $dim['width'],
|
||||
'maxWith' => $dim['width'],
|
||||
];
|
||||
$rules = array_merge($rules, [
|
||||
"data.$iptName.value" => [
|
||||
function (string $attribute, $value, callable $fail) use ($sizes) {
|
||||
return ToolboxHelper::validatePicture($attribute, $value, $fail, $sizes);
|
||||
}
|
||||
],
|
||||
$this->compileValidate(
|
||||
implode('|', [
|
||||
$required,
|
||||
'image',
|
||||
'mimes:png,jpg,jpeg',
|
||||
sprintf(
|
||||
'dimensions:%s=%d,%s=%d',
|
||||
$max ? 'max_height' : 'height',
|
||||
$dim['height'],
|
||||
$max ? 'max_width' : 'width',
|
||||
$dim['width']
|
||||
)
|
||||
]),
|
||||
$input
|
||||
),
|
||||
"data.$iptName.alt" => $this->compileValidate("$required|string|min:5", $input),
|
||||
"data.$iptName.title" => $this->compileValidate("$required|string|min:5", $input)
|
||||
]);
|
||||
break;
|
||||
case InputType::url->value:
|
||||
$rules = array_merge($rules, [
|
||||
"data.$iptName.value" => [
|
||||
'required', 'url',
|
||||
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
|
||||
function ($attribute, $value, $fail) {
|
||||
try {
|
||||
ToolboxHelper::assertNoInternalUrls($attribute, $value);
|
||||
ToolboxHelper::assertNoInternalBoUrls($attribute, $value);
|
||||
} catch (ValidationException $e) {
|
||||
$fail(collect($e->errors())->first()[0]);
|
||||
}
|
||||
}
|
||||
]
|
||||
]);
|
||||
break;
|
||||
case InputType::boolean->value:
|
||||
$all = $this->all();
|
||||
$nested = ToolboxHelper::dotStringToNestedArray(
|
||||
"data.$iptName.value",
|
||||
$this->input("data.$iptName.value") ? true : false
|
||||
);
|
||||
$all = ToolboxHelper::arrayMergeRecursiveDistinct($all, $nested);
|
||||
$this->merge($all);
|
||||
$rules = array_merge($rules, [
|
||||
"data.$iptName.value" => 'boolean'
|
||||
]);
|
||||
break;
|
||||
} //end switch
|
||||
} //end foreach
|
||||
return $rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param string|array $inputTypeValidate
|
||||
* @param array $input
|
||||
* @return array
|
||||
*/
|
||||
public function compileValidate(string|array $inputTypeValidate, array $input): array
|
||||
{
|
||||
if (\is_string($inputTypeValidate)) {
|
||||
$inputTypeValidate = explode('|', $inputTypeValidate);
|
||||
}
|
||||
/** @var array|string */
|
||||
$inputValidate = \collect($input)->get('validate', $input);
|
||||
$inputValidate = \is_string($inputValidate) ? explode('|', $inputValidate) : $inputValidate;
|
||||
foreach ($inputValidate as $validate) {
|
||||
if (!\in_array($validate, $inputTypeValidate)) {
|
||||
$inputTypeValidate[] = $validate;
|
||||
}
|
||||
}
|
||||
|
||||
$test = \collect($inputTypeValidate)->all();
|
||||
$test = \collect($inputTypeValidate)->sort(function ($valueA, $valueB) {
|
||||
$valueA = $this->ruleHasToComeFirst($valueA) ? 0 : 2;
|
||||
$valueB = $this->ruleHasToComeFirst($valueB) ? 1 : 2;
|
||||
return $valueA - $valueB;
|
||||
})->unique()->all();
|
||||
|
||||
return \collect($inputTypeValidate)->unique()->sort(function ($valueA, $valueB) {
|
||||
$valueA = $this->ruleHasToComeFirst($valueA) ? 0 : 2;
|
||||
$valueB = $this->ruleHasToComeFirst($valueB) ? 1 : 2;
|
||||
return $valueA - $valueB;
|
||||
})->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the rulle need to come first ?
|
||||
*
|
||||
* @param string $rule
|
||||
* @return boolean
|
||||
*/
|
||||
private function ruleHasToComeFirst(string $rule): bool
|
||||
{
|
||||
$rule = \collect(\explode(':', $rule, 1))->filter()->first(null, '');
|
||||
return \collect([
|
||||
'nullable', 'present', 'required', 'required_if',
|
||||
'required_unless', 'required_with', 'required_with_all',
|
||||
'required_without', 'required_without_all', 'required_with_all',
|
||||
'missing', 'missing_if', 'missing_unless',
|
||||
'missing_with', 'missing_with_all',
|
||||
])->first(fn (string $firstRule) => \strpos($rule, $firstRule) === 0) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this request an update request ?
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private function isUpdate(): bool
|
||||
{
|
||||
return $this->isMethod('PUT');
|
||||
}
|
||||
}
|
||||
|
|
@ -3,9 +3,10 @@
|
|||
namespace App\Http\Requests\Bo\Users;
|
||||
|
||||
use App\Enums\Users\RoleEnum;
|
||||
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
|
||||
{
|
||||
|
|
@ -16,7 +17,7 @@ class StoreUserRequest extends FormRequest
|
|||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return auth('backend')->check();
|
||||
return Gate::check('create', User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -24,10 +25,10 @@ class StoreUserRequest extends FormRequest
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function prepareForValidation()
|
||||
protected function prepareForValidation(): void
|
||||
{
|
||||
$this->merge([
|
||||
'published' => $this->published ? true : false
|
||||
'published' => $this->boolean('published')
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -42,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',
|
||||
];
|
||||
|
|
@ -66,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')
|
||||
];
|
||||
|
|
|
|||
|
|
@ -2,23 +2,30 @@
|
|||
|
||||
namespace App\Http\Requests\Bo\Users;
|
||||
|
||||
use Illuminate\Validation\Rules\Password;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class UpdateUserRequest extends StoreUserRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return Gate::check('update', $this->route('user'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the data for validation.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function prepareForValidation()
|
||||
protected function prepareForValidation(): void
|
||||
{
|
||||
$this->merge([
|
||||
'published' => $this->published ? true : false,
|
||||
'password' => $this->password ? $this->password : $this->route('user')->password,
|
||||
'password_confirmation' => $this->password_confirmation ?
|
||||
$this->password_confirmation :
|
||||
$this->route('user')->password
|
||||
'published' => $this->boolean('published'),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -33,15 +40,7 @@ class UpdateUserRequest extends StoreUserRequest
|
|||
'email' => [
|
||||
'required',
|
||||
'email:rfc,strict,dns,spoof,filter',
|
||||
'unique:users,email,' . $this->route('user')->getKey() . ',id',
|
||||
],
|
||||
'password' => [
|
||||
'required', 'required_with:password_confirmation', 'confirmed', 'max:255', Password::min(8)
|
||||
->letters()
|
||||
->mixedCase()
|
||||
->numbers()
|
||||
->symbols()
|
||||
->uncompromised()
|
||||
Rule::unique('users', 'email')->ignore(\optional($this->route('user'))->getRouteKey())
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,10 +20,6 @@ class ContactRequest extends FormRequest
|
|||
*/
|
||||
protected function prepareForValidation()
|
||||
{
|
||||
$this->merge([
|
||||
'accept_rules' => $this->accept_rules ? true : false,
|
||||
'send_data' => $this->send_data ? true : false,
|
||||
]);
|
||||
$this->mergePicture('file');
|
||||
}
|
||||
|
||||
|
|
@ -31,9 +27,11 @@ class ContactRequest extends FormRequest
|
|||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
// phpcs:enable
|
||||
ToolboxHelper::validateRecaptcha($this, \config('services.google.recaptcha.version'));
|
||||
|
||||
$rules = [
|
||||
|
|
@ -43,15 +41,19 @@ class ContactRequest extends FormRequest
|
|||
'society' => 'sometimes|nullable|string|between:3,255',
|
||||
'email' => 'required|email:rfc,strict,dns,spoof,filter|max:255',
|
||||
'phone' => 'sometimes|nullable|numeric|min:0',
|
||||
'address' => 'sometimes|nullable|string|between:3,255',
|
||||
'postal_code' => 'sometimes|nullable|numeric|min:0',
|
||||
'city' => 'sometimes|nullable|string|between:3,255',
|
||||
'address' => 'required|string|between:3,255',
|
||||
'postal_code' => 'required|numeric|min:0',
|
||||
'city' => 'required|string|between:3,255',
|
||||
'object' => ['required', new Enum(ObjectEnum::class)],
|
||||
'message' => 'required|string|between:3,500',
|
||||
];
|
||||
if ($this->object === strval(ObjectEnum::customerService->value())) {
|
||||
$rules = \array_merge($rules, [
|
||||
'product_name' => [
|
||||
'nullable', 'string', 'between:3,255',
|
||||
// @phpcs:ignore Generic.Files.LineLength.TooLong
|
||||
'required_with:product_date_limit,product_barcode,product_lot,product_date_consumption,product_location',
|
||||
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
|
||||
'string',
|
||||
'between:3,255',
|
||||
'required',
|
||||
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
|
||||
function ($attribute, $value, $fail) {
|
||||
if ($this->get("object") != ObjectEnum::customerService->value()) {
|
||||
$fail(\trans('le Champs :field doit être vide lorsque le champs objet
|
||||
|
|
@ -63,10 +65,9 @@ class ContactRequest extends FormRequest
|
|||
}
|
||||
],
|
||||
'product_date_limit' => [
|
||||
'sometimes', 'nullable', 'string', 'between:3,255',
|
||||
// @phpcs:ignore Generic.Files.LineLength.TooLong
|
||||
'required_with:product_name,product_barcode,product_lot,product_date_consumption,product_location',
|
||||
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
|
||||
'required',
|
||||
'date',
|
||||
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
|
||||
function ($attribute, $value, $fail) {
|
||||
if ($this->get("object") != ObjectEnum::customerService->value()) {
|
||||
$fail(\trans('le Champs :field doit être vide lorsque le champs objet
|
||||
|
|
@ -78,10 +79,10 @@ class ContactRequest extends FormRequest
|
|||
}
|
||||
],
|
||||
'product_barcode' => [
|
||||
'sometimes', 'nullable', 'numeric', 'min:0',
|
||||
// @phpcs:ignore Generic.Files.LineLength.TooLong
|
||||
'required_with:product_name,product_date_limit,product_lot,product_date_consumption,product_location',
|
||||
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
|
||||
'numeric',
|
||||
'min:0',
|
||||
'required',
|
||||
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
|
||||
function ($attribute, $value, $fail) {
|
||||
if ($this->get("object") != ObjectEnum::customerService->value()) {
|
||||
$fail(\trans('le Champs :field doit être vide lorsque le champs objet
|
||||
|
|
@ -93,10 +94,10 @@ class ContactRequest extends FormRequest
|
|||
}
|
||||
],
|
||||
'product_lot' => [
|
||||
'sometimes', 'nullable', 'numeric', 'min:0',
|
||||
// @phpcs:ignore Generic.Files.LineLength.TooLong
|
||||
'required_with:product_name,product_date_limit,product_barcode,product_date_consumption,product_location',
|
||||
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
|
||||
'numeric',
|
||||
'min:0',
|
||||
'required',
|
||||
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
|
||||
function ($attribute, $value, $fail) {
|
||||
if ($this->get("object") != ObjectEnum::customerService->value()) {
|
||||
$fail(\trans('le Champs :field doit être vide lorsque le champs objet
|
||||
|
|
@ -108,10 +109,9 @@ class ContactRequest extends FormRequest
|
|||
}
|
||||
],
|
||||
'product_date_consumption' => [
|
||||
'sometimes', 'nullable', 'string', 'between:3,255',
|
||||
// @phpcs:ignore Generic.Files.LineLength.TooLong
|
||||
'required_with:product_name,product_date_limit,product_barcode,product_lot,product_location',
|
||||
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
|
||||
'required',
|
||||
'date',
|
||||
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
|
||||
function ($attribute, $value, $fail) {
|
||||
if ($this->get("object") != ObjectEnum::customerService->value()) {
|
||||
$fail(\trans('le Champs :field doit être vide lorsque le champs objet
|
||||
|
|
@ -123,10 +123,10 @@ class ContactRequest extends FormRequest
|
|||
}
|
||||
],
|
||||
'product_location' => [
|
||||
'sometimes', 'nullable', 'string', 'between:3,255',
|
||||
// @phpcs:ignore Generic.Files.LineLength.TooLong
|
||||
'required_with:product_name,product_date_limit,product_barcode,product_lot,product_date_consumption',
|
||||
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
|
||||
'string',
|
||||
'between:3,255',
|
||||
'required',
|
||||
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
|
||||
function ($attribute, $value, $fail) {
|
||||
if ($this->get("object") != ObjectEnum::customerService->value()) {
|
||||
$fail(\trans('le Champs :field doit être vide lorsque le champs objet
|
||||
|
|
@ -137,10 +137,8 @@ class ContactRequest extends FormRequest
|
|||
}
|
||||
}
|
||||
],
|
||||
'message' => 'required|string|between:3,255',
|
||||
'accept_rules' => 'required|boolean',
|
||||
'send_data' => 'required|boolean',
|
||||
];
|
||||
]);
|
||||
} //end if
|
||||
if (
|
||||
isset(request()->file) and
|
||||
(request()->file->getClientMimeType() === "image/jpeg" ||
|
||||
|
|
@ -152,8 +150,8 @@ class ContactRequest extends FormRequest
|
|||
0,
|
||||
1920,
|
||||
1080,
|
||||
3000,
|
||||
true,
|
||||
3000,
|
||||
'product_name,product_date_limit,product_barcode,product_lot,product_date_consumption,product_location'
|
||||
));
|
||||
} elseif (isset(request()->file) and (request()->file->getClientMimeType() === "application/pdf")) {
|
||||
|
|
@ -161,6 +159,20 @@ class ContactRequest extends FormRequest
|
|||
//phpcs:ignore Generic.Files.LineLength.TooLong
|
||||
'file' => 'sometimes|nullable|mimes:pdf|required_with:product_name,product_date_limit,product_barcode,product_lot,product_date_consumption,product_location'
|
||||
]);
|
||||
} elseif (
|
||||
isset(request()->file) and
|
||||
(request()->file->getClientMimeType() !== "application/pdf") and
|
||||
(request()->file->getClientMimeType() !== "image/jpeg") and
|
||||
(request()->file->getClientMimeType() !== "image/png")
|
||||
) {
|
||||
$rules = \array_merge($rules, [
|
||||
'file' => [
|
||||
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
|
||||
function ($attribute, $value, $fail) {
|
||||
$fail(\trans('Le format du fichier doit être .jpg, .png ou .pdf'));
|
||||
}
|
||||
],
|
||||
]);
|
||||
} //end if
|
||||
return $rules;
|
||||
}
|
||||
|
|
@ -190,8 +202,6 @@ class ContactRequest extends FormRequest
|
|||
'product_date_consumption' => trans('validation.custom.product_date_consumption'),
|
||||
'product_location' => trans('validation.custom.product_location'),
|
||||
'message' => trans('validation.attributes.message'),
|
||||
'accept_rules' => trans('validation.custom.accept_rules'),
|
||||
'send_data' => trans('validation.custom.send_data'),
|
||||
'file' => trans('validation.custom.file'),
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,10 @@
|
|||
|
||||
namespace App\Http\Requests\Fo;
|
||||
|
||||
use App\Enums\DesiredLocation;
|
||||
use App\Lib\Helpers\ToolboxHelper;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rules\Enum;
|
||||
|
||||
class JoinusRequest extends FormRequest
|
||||
{
|
||||
|
|
@ -12,7 +14,7 @@ class JoinusRequest extends FormRequest
|
|||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
public function rules(): array
|
||||
{
|
||||
ToolboxHelper::validateRecaptcha($this, \config('services.google.recaptcha.version'));
|
||||
|
||||
|
|
@ -21,7 +23,8 @@ class JoinusRequest extends FormRequest
|
|||
'first_name' => 'required|string|between:3,255',
|
||||
'email' => 'required|email:rfc,strict,dns,spoof,filter|max:255',
|
||||
'phone' => 'required|numeric|min:0',
|
||||
'message' => 'required|string|between:3,255',
|
||||
'desired_location' => ['required', new Enum(DesiredLocation::class)],
|
||||
'message' => 'required|string|between:3,500',
|
||||
"file" => "sometimes|nullable|mimes:pdf|max:10000"
|
||||
];
|
||||
}
|
||||
|
|
@ -38,6 +41,7 @@ class JoinusRequest extends FormRequest
|
|||
'last_name' => trans('validation.attributes.last_name'),
|
||||
'email' => trans('validation.attributes.email'),
|
||||
'phone' => trans('validation.attributes.phone'),
|
||||
'desired_location' => trans('validation.custom.desired_location'),
|
||||
'message' => trans('validation.attributes.message'),
|
||||
'file' => trans('validation.attributes.file'),
|
||||
];
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ class SeasonalSectionStatusUpdate
|
|||
*/
|
||||
public function handle()
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Collection<array-key, \App\Models\SeasonalSections> */
|
||||
/** @var \Illuminate\Database\Eloquent\Collection<array-key, \App\Models\SeasonalSection> */
|
||||
$seasonalsectionsListToPublish = SeasonalSection::query()
|
||||
->where('publish_at', '<=', Carbon::now()->toDateTime())
|
||||
->whereNotNull('publish_at')
|
||||
|
|
@ -30,7 +30,7 @@ class SeasonalSectionStatusUpdate
|
|||
$seasonalsections->published = true;
|
||||
$seasonalsections->saveOrFail();
|
||||
}
|
||||
/** @var \Illuminate\Database\Eloquent\Collection<array-key, \App\Models\SeasonalSections> */
|
||||
/** @var \Illuminate\Database\Eloquent\Collection<array-key, \App\Models\SeasonalSection> */
|
||||
$seasonalsectionsListToUnPublish = SeasonalSection::query()
|
||||
->where('unpublish_at', '<=', Carbon::now()->toDateTime())
|
||||
->whereNotNull('unpublish_at')
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ class ExceptionsHelper
|
|||
$traceStr .= self::handleArgs($stack);
|
||||
}
|
||||
$traceStr .= ")\n";
|
||||
} elseif (isset($stack['function'])) {
|
||||
} else {
|
||||
$traceStr .= "{$stack['function']}(";
|
||||
if (isset($stack['args'])) {
|
||||
$traceStr .= self::handleArgs($stack);
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ class FileStorageHelper
|
|||
Model $model,
|
||||
$file,
|
||||
bool $slugify = false,
|
||||
string $filename = null,
|
||||
string|null $filename = null,
|
||||
bool $private = false
|
||||
): string {
|
||||
// phpcs:enable
|
||||
|
|
@ -152,7 +152,7 @@ class FileStorageHelper
|
|||
public static function storeModelFilesFromHtml(
|
||||
Model $model,
|
||||
string $htmlString,
|
||||
string $oldHtmlString = null
|
||||
string|null $oldHtmlString = null
|
||||
): string {
|
||||
\collect(self::onlyUploadedFilesWithFileManager(self::findFilesInHtml($htmlString)))
|
||||
->each(function (string $path) use ($model, &$htmlString) {
|
||||
|
|
@ -309,7 +309,6 @@ class FileStorageHelper
|
|||
$private ? 'app/private/modelfiles' : 'app/public/modelfiles',
|
||||
$tableName,
|
||||
$filename,
|
||||
$private
|
||||
);
|
||||
$filename = self::getFileUniqueName($folderPath, $filename);
|
||||
return "{$folderPath}/{$filename}";
|
||||
|
|
@ -404,7 +403,7 @@ class FileStorageHelper
|
|||
$filename = Str::of($filename)->ltrim('.-');
|
||||
// * Optional beautification
|
||||
if ($beautify) {
|
||||
$filename = static::beautifyFilename($filename);
|
||||
$filename = self::beautifyFilename($filename);
|
||||
}
|
||||
// * Maximize filename length to 255 bytes http://serverfault.com/a/9548/44086
|
||||
/** @var string */
|
||||
|
|
|
|||
|
|
@ -175,11 +175,10 @@ class ToolboxHelper
|
|||
$url = $match;
|
||||
try {
|
||||
$request = Request::create($url);
|
||||
// If a route is match then it do not throws exception.
|
||||
if (
|
||||
\parse_url(config('app.url'), \PHP_URL_HOST) === \parse_url($url, \PHP_URL_HOST) &&
|
||||
$routes->match($request)
|
||||
) {
|
||||
// Assert route matches existing routes.
|
||||
$routes->match($request);
|
||||
// ? Is url internal ?
|
||||
if (\parse_url(config('app.url'), \PHP_URL_HOST) === \parse_url($url, \PHP_URL_HOST)) {
|
||||
// Removes the matched url.
|
||||
throw ValidationException::withMessages([
|
||||
$field => trans(
|
||||
|
|
@ -205,14 +204,14 @@ class ToolboxHelper
|
|||
* @param array|string $replace
|
||||
* @param array|string $subject
|
||||
* @param integer $count
|
||||
* @return array|string
|
||||
* @return array|string|false
|
||||
*/
|
||||
public static function mbReplace(
|
||||
array|string $search,
|
||||
array|string $replace,
|
||||
array|string $subject,
|
||||
int &$count = 0
|
||||
): array|string {
|
||||
): array|string|false {
|
||||
if (!is_array($search) && is_array($replace)) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -289,9 +288,12 @@ class ToolboxHelper
|
|||
public static function getOriginal(Model $model, string $attribute): mixed
|
||||
{
|
||||
if (\in_array('Spatie\Translatable\HasTranslations', \class_uses_recursive($model))) {
|
||||
// @phpstan-ignore-next-line
|
||||
return $model->getTranslation(
|
||||
$attribute,
|
||||
// @phpstan-ignore-next-line
|
||||
$model->getLocale(),
|
||||
// @phpstan-ignore-next-line
|
||||
$model->useFallbackLocale()
|
||||
);
|
||||
}
|
||||
|
|
@ -361,14 +363,16 @@ class ToolboxHelper
|
|||
/**
|
||||
* Convert deeply an object to array
|
||||
*
|
||||
* @param array|object $input
|
||||
* @param mixed $input
|
||||
* @return array
|
||||
* @throws \RuntimeException If $input var is a scalar value.
|
||||
*/
|
||||
public static function objectToArray($input): array
|
||||
public static function objectToArray(mixed $input): array
|
||||
{
|
||||
// Only process if it's an object or array being passed to the function.
|
||||
if (is_object($input) or is_array($input)) {
|
||||
if (!(is_object($input) or is_array($input))) {
|
||||
throw new \RuntimeException('Cannot handle $input of type ' . \gettype($input));
|
||||
}
|
||||
$ret = (array)$input;
|
||||
foreach ($ret as &$item) {
|
||||
// Recursively process EACH element only if not scalar.
|
||||
|
|
@ -376,22 +380,21 @@ class ToolboxHelper
|
|||
self::objectToArray($item) : $item;
|
||||
}
|
||||
return $ret;
|
||||
} else {
|
||||
throw new \RuntimeException('Cannot handle $input of type ' . \gettype($input));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert deeply an array to object
|
||||
*
|
||||
* @param array|object $input
|
||||
* @param mixed $input
|
||||
* @return object
|
||||
* @throws \RuntimeException If $input var is a scalar value.
|
||||
*/
|
||||
public static function arrayToObject($input): object
|
||||
public static function arrayToObject(mixed $input): object
|
||||
{
|
||||
// Only process if it's an object or array being passed to the function.
|
||||
if (is_object($input) or is_array($input)) {
|
||||
if (!(is_object($input) or is_array($input))) {
|
||||
throw new \RuntimeException('Cannot handle $input of type ' . \gettype($input));
|
||||
}
|
||||
$ret = (object)$input;
|
||||
foreach ($ret as &$item) {
|
||||
// Recursively process EACH element only if not scalar.
|
||||
|
|
@ -399,9 +402,6 @@ class ToolboxHelper
|
|||
self::arrayToObject($item) : $item;
|
||||
}
|
||||
return $ret;
|
||||
} else {
|
||||
throw new \RuntimeException('Cannot handle $input of type ' . \gettype($input));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -409,11 +409,11 @@ class ToolboxHelper
|
|||
*
|
||||
* @param string $attribute
|
||||
* @param string|null $value
|
||||
* @param callback $fail
|
||||
* @param callable $fail
|
||||
* @param object $sizes
|
||||
* @return void
|
||||
*/
|
||||
public static function validatePicture(string $attribute, string|null $value, callable $fail, object $sizes)
|
||||
public static function validatePicture(string $attribute, string|null $value, callable $fail, object $sizes): void
|
||||
{
|
||||
if (!($useStorage = Storage::exists($value)) and !File::exists($value)) {
|
||||
$fail(trans(':attribute n\'existe pas dans le système de fichier', [
|
||||
|
|
@ -432,7 +432,7 @@ class ToolboxHelper
|
|||
'attribute' => $attribute
|
||||
]));
|
||||
}
|
||||
if (!($dimensions = \getimagesize($fileFullPath)) or !isset($dimensions[0]) or !isset($dimensions[1])) {
|
||||
if (!($dimensions = \getimagesize($fileFullPath))) {
|
||||
$fail(trans(':attribute impossible de valider les dimensions', [
|
||||
'attribute' => $attribute
|
||||
]));
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ namespace App\Mail;
|
|||
use App\Enums\Contact\ObjectEnum;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Address;
|
||||
use Illuminate\Mail\Mailables\Attachment;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
|
|
@ -17,7 +16,7 @@ class SendContactMail extends Mailable
|
|||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var \App\Mail\Contact
|
||||
* @var \stdClass
|
||||
*/
|
||||
private \stdClass $data;
|
||||
|
||||
|
|
@ -40,16 +39,11 @@ class SendContactMail extends Mailable
|
|||
*/
|
||||
public function envelope(): \Illuminate\Mail\Mailables\Envelope
|
||||
{
|
||||
$subject = ObjectEnum::make($this->data->object) ?
|
||||
ObjectEnum::make($this->data->object)->label() :
|
||||
__('Nouveau message');
|
||||
return new Envelope(
|
||||
from: new Address(
|
||||
$this->data->email,
|
||||
($this->data->first_name !== null || $this->data->last_name !== null) ?
|
||||
(($this->data->first_name ?? '') . " " . ($this->data->last_name ?? '')) :
|
||||
null
|
||||
),
|
||||
to: [new Address(config('mail.from.address'), config('mail.from.name'))],
|
||||
subject: sprintf('%s - %s', ObjectEnum::make($this->data->object)->label() ??
|
||||
__('Nouveau message'), config('app.name')),
|
||||
subject: sprintf('%s - %s', $subject, config('app.name')),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -101,8 +95,6 @@ class SendContactMail extends Mailable
|
|||
* @property string $product_lot
|
||||
* @property string $product_date_consumption
|
||||
* @property string $product_location
|
||||
* @property boolean $accept_rules
|
||||
* @property boolean $send_data
|
||||
* @property \Illuminate\Http\UploadedFile $file
|
||||
* @phpcs:disable PSR1.Classes.ClassDeclaration.MultipleClasses
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
namespace App\Mail;
|
||||
|
||||
use App\Enums\DesiredLocation;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Address;
|
||||
use Illuminate\Mail\Mailables\Attachment;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
|
|
@ -16,7 +16,7 @@ class SendJoinusMail extends Mailable
|
|||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var \App\Mail\Joinus
|
||||
* @var \stdClass
|
||||
*/
|
||||
private \stdClass $data;
|
||||
|
||||
|
|
@ -25,10 +25,10 @@ class SendJoinusMail extends Mailable
|
|||
*
|
||||
* @param \stdClass $data
|
||||
* @return void
|
||||
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
|
||||
*/
|
||||
public function __construct(\stdClass $data)
|
||||
{
|
||||
$data->desired_location = DesiredLocation::make($data->desired_location)->label();
|
||||
$this->data = clone $data;
|
||||
}
|
||||
|
||||
|
|
@ -40,13 +40,6 @@ class SendJoinusMail extends Mailable
|
|||
public function envelope(): \Illuminate\Mail\Mailables\Envelope
|
||||
{
|
||||
return new Envelope(
|
||||
from: new Address(
|
||||
$this->data->email,
|
||||
($this->data->first_name !== null || $this->data->last_name !== null) ?
|
||||
(($this->data->first_name ?? '') . " " . ($this->data->last_name ?? '')) :
|
||||
null
|
||||
),
|
||||
to: [new Address(config('mail.from.address'), config('mail.from.name'))],
|
||||
subject: sprintf('%s - %s', __('Candidature spontanée'), config('app.name')),
|
||||
);
|
||||
}
|
||||
|
|
@ -86,6 +79,7 @@ class SendJoinusMail extends Mailable
|
|||
* @property string $first_name
|
||||
* @property string $email
|
||||
* @property string $phone
|
||||
* @property \App\Enums\DesiredLocation $desired_location
|
||||
* @property string $message
|
||||
* @property \Illuminate\Http\UploadedFile $file
|
||||
* @phpcs:disable PSR1.Classes.ClassDeclaration.MultipleClasses
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
namespace App\Models;
|
||||
|
||||
use App\Enums\ActivityLogs\ActivityLogsEventEnum;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
|
|
@ -12,8 +11,8 @@ use Illuminate\Support\Facades\Schema;
|
|||
/**
|
||||
* @property string $model Target model.
|
||||
* @property string $model_id Id of the target model.
|
||||
* @property string $event Event of this activity (ActivityLogsEventEnum).
|
||||
* @property string $data Changes.
|
||||
* @property \App\Enums\ActivityLogs\ActivityLogsEventEnum $event Event of this activity (ActivityLogsEventEnum).
|
||||
* @property array $data Changes.
|
||||
* @property-read \Illuminate\Support\Carbon $created_at Created date.
|
||||
*
|
||||
* @property-read \App\Models\User $user User BelongsTo relation.
|
||||
|
|
@ -82,19 +81,20 @@ class ActivityLog extends Model
|
|||
$activity->model_id = $model->getKey();
|
||||
$activity->event = $eventEnum;
|
||||
$activity->data = static::getChangedColumns($activity, $model, $eventEnum);
|
||||
$activity->created_at = Carbon::now();
|
||||
// @phpstan-ignore-next-line
|
||||
$activity->created_at = now();
|
||||
$activity->saveOrFail();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get old, new columns that has changed.
|
||||
*
|
||||
* @param \self $activity
|
||||
* @param self $activity
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @param \App\Enums\ActivityLogs\ActivityLogsEventEnum $eventEnum
|
||||
* @return array|null
|
||||
* @return array
|
||||
*/
|
||||
public static function getChangedColumns(self $activity, Model $model, ActivityLogsEventEnum $eventEnum): array|null
|
||||
public static function getChangedColumns(self $activity, Model $model, ActivityLogsEventEnum $eventEnum): array
|
||||
{
|
||||
$modelClassName = $activity->model_class;
|
||||
/** Get type of each fields of the target model */
|
||||
|
|
@ -103,16 +103,17 @@ class ActivityLog extends Model
|
|||
$activity->model_id
|
||||
)->first();
|
||||
if ($targetModel != null) {
|
||||
// phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
|
||||
$targetModelTypes = collect($targetModel->toArray())
|
||||
// phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
|
||||
->map(function ($field, $fieldIndex) use ($targetModel) {
|
||||
return Schema::getColumnType($targetModel->getTable(), $fieldIndex);
|
||||
})->toArray();
|
||||
// phpcs:enable
|
||||
}
|
||||
/** Return old, new and type of values changed */
|
||||
return ($eventEnum === ActivityLogsEventEnum::updated) ?
|
||||
array_intersect_key($targetModelTypes, $model->getChanges()) : null;
|
||||
array_intersect_key($targetModelTypes, $model->getChanges()) : [];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
// * RELATIONS
|
||||
|
|
@ -122,7 +123,7 @@ class ActivityLog extends Model
|
|||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
public function user(): \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,9 +11,11 @@ use Illuminate\Database\Eloquent\Model;
|
|||
* @property string $title_part1 Title part 1.
|
||||
* @property string $title_part2 Title part 2.
|
||||
* @property string $title_part3 Title part 3.
|
||||
* @property string $picture Path of the picture (640px * 390px).
|
||||
* @property string|null $picture Path of the picture (640px * 390px).
|
||||
* @property string $picture_alt Picture alt attribute.
|
||||
* @property string $picture_title Picture title attribute.
|
||||
* @property string $video_id The youtube or vimeo video Id.
|
||||
* @property boolean $display_video Wether to display video or picture.
|
||||
* @property string $presentation_title Presentation title.
|
||||
* @property string $presentation_content WYSIWYG - Presentation content.
|
||||
* @property-read \Carbon\Carbon $created_at Created date.
|
||||
|
|
@ -38,6 +40,17 @@ class Homepage extends Model
|
|||
'picture_title',
|
||||
'presentation_title',
|
||||
'presentation_content',
|
||||
'video_id',
|
||||
'display_video',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'display_video' => 'bool'
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -9,6 +9,12 @@ 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\Seo\Laravel\Interfaces\SeoInterface;
|
||||
use Uwil\Seo\Laravel\Objects\SeoItem;
|
||||
use Uwil\Seo\Laravel\Traits\SeoTrait;
|
||||
use Uwil\SitemapGenerator\Lib\SitemapHelper;
|
||||
|
||||
/**
|
||||
* @property string $seo_title SEO title.
|
||||
|
|
@ -31,10 +37,11 @@ use Illuminate\Support\Str;
|
|||
* @property-read \Carbon\Carbon $created_at Created date.
|
||||
* @property-read \Carbon\Carbon $updated_at Updated date.
|
||||
*/
|
||||
class News extends Model
|
||||
class News extends Model implements SeoInterface, Sitemapable
|
||||
{
|
||||
use ActivityLog;
|
||||
use HasFactory;
|
||||
use SeoTrait;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
|
|
@ -198,4 +205,35 @@ class News extends Model
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// * SEO TRAIT OVERLOAD
|
||||
/**
|
||||
* Transform to seoModel
|
||||
*
|
||||
* @return \Uwil\Seo\Laravel\Objects\SeoItem
|
||||
*/
|
||||
public function toSeoItem(): SeoItem
|
||||
{
|
||||
return new SeoItem(
|
||||
\trans('models.classes.' . Str::singular($this->getTable())),
|
||||
$this->seo_title,
|
||||
$this->seo_description,
|
||||
$this->published ?? false,
|
||||
\route(\config('seo.bo_route_prefix') . $this->getTable() . '.edit', $this),
|
||||
$this->published ? \route('fo.' . $this->getTable() . '.show', $this) : ''
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* toSitemapTag method
|
||||
*
|
||||
* @return Url|string|array
|
||||
*/
|
||||
public function toSitemapTag(): Url | string | array
|
||||
{
|
||||
$model = $this;
|
||||
$route = 'fo.news.show';
|
||||
$params = ['slug' => $model->slug];
|
||||
return SitemapHelper::generateUrl($route, $params, $model);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,12 @@ 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\Seo\Laravel\Interfaces\SeoInterface;
|
||||
use Uwil\Seo\Laravel\Objects\SeoItem;
|
||||
use Uwil\Seo\Laravel\Traits\SeoTrait;
|
||||
use Uwil\SitemapGenerator\Lib\SitemapHelper;
|
||||
|
||||
/**
|
||||
* @phpcs:disable Generic.Files.LineLength.TooLong
|
||||
|
|
@ -41,10 +47,11 @@ use Illuminate\Support\Str;
|
|||
* @property-read \App\Models\Range $range Range Belongs to relationship.
|
||||
* @phpcs:enable
|
||||
*/
|
||||
class Product extends Model
|
||||
class Product extends Model implements SeoInterface, Sitemapable
|
||||
{
|
||||
use ActivityLog;
|
||||
use HasFactory;
|
||||
use SeoTrait;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
|
|
@ -189,4 +196,35 @@ class Product extends Model
|
|||
{
|
||||
return $this->belongsToMany(Commitment::class);
|
||||
}
|
||||
|
||||
// * SEO TRAIT OVERLOAD
|
||||
/**
|
||||
* Transform to seoModel
|
||||
*
|
||||
* @return \Uwil\Seo\Laravel\Objects\SeoItem
|
||||
*/
|
||||
public function toSeoItem(): SeoItem
|
||||
{
|
||||
return new SeoItem(
|
||||
\trans('models.classes.' . Str::singular($this->getTable())),
|
||||
$this->seo_title,
|
||||
$this->seo_description,
|
||||
$this->published ?? false,
|
||||
\route(\config('seo.bo_route_prefix') . $this->getTable() . '.edit', $this),
|
||||
$this->published ? \route('fo.' . $this->getTable() . '.show', $this) : ''
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* toSitemapTag method
|
||||
*
|
||||
* @return Url|string|array
|
||||
*/
|
||||
public function toSitemapTag(): Url | string | array
|
||||
{
|
||||
$model = $this;
|
||||
$route = 'fo.products.show';
|
||||
$params = ['slug' => $model->slug];
|
||||
return SitemapHelper::generateUrl($route, $params, $model);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,12 @@ 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\Seo\Laravel\Interfaces\SeoInterface;
|
||||
use Uwil\Seo\Laravel\Objects\SeoItem;
|
||||
use Uwil\Seo\Laravel\Traits\SeoTrait;
|
||||
use Uwil\SitemapGenerator\Lib\SitemapHelper;
|
||||
|
||||
// phpcs:disable Generic.Files.LineLength.TooLong
|
||||
/**
|
||||
|
|
@ -22,7 +28,7 @@ use Illuminate\Support\Str;
|
|||
* @property string $picture Path of the picture (466px * 440px).
|
||||
* @property string $picture_alt Picture alt attribute.
|
||||
* @property string $picture_title Picture title attribute.
|
||||
* @property string $picture_productsheet Path of the picture of the product sheet (332px * 442px).
|
||||
* @property string $picture_productsheet Path of the picture of the product sheet (680px * 300px).
|
||||
* @property string $picture_productsheet_alt Picture alt attribute of the product sheet.
|
||||
* @property string $picture_productsheet_title Picture title attribute of the product sheet.
|
||||
* @property string $picture_thumbnail Path of the thumbnail (246px * 337px).
|
||||
|
|
@ -36,10 +42,11 @@ use Illuminate\Support\Str;
|
|||
* @property-read \App\Models\Products $products Products Has Many relationship.
|
||||
*/
|
||||
// phpcs:enable
|
||||
class Range extends Model
|
||||
class Range extends Model implements SeoInterface, Sitemapable
|
||||
{
|
||||
use ActivityLog;
|
||||
use HasFactory;
|
||||
use SeoTrait;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
|
|
@ -170,4 +177,35 @@ class Range extends Model
|
|||
{
|
||||
return $this->hasMany(Product::class);
|
||||
}
|
||||
|
||||
// * SEO TRAIT OVERLOAD
|
||||
/**
|
||||
* Transform to seoModel
|
||||
*
|
||||
* @return \Uwil\Seo\Laravel\Objects\SeoItem
|
||||
*/
|
||||
public function toSeoItem(): SeoItem
|
||||
{
|
||||
return new SeoItem(
|
||||
\trans('models.classes.' . Str::singular($this->getTable())),
|
||||
$this->seo_title,
|
||||
$this->seo_description,
|
||||
$this->published ?? false,
|
||||
\route(\config('seo.bo_route_prefix') . $this->getTable() . '.edit', $this),
|
||||
$this->published ? \route('fo.' . $this->getTable() . '.show', $this) : ''
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* toSitemapTag method
|
||||
*
|
||||
* @return Url|string|array
|
||||
*/
|
||||
public function toSitemapTag(): Url | string | array
|
||||
{
|
||||
$model = $this;
|
||||
$route = 'fo.ranges.show';
|
||||
$params = ['slug' => $model->slug];
|
||||
return SitemapHelper::generateUrl($route, $params, $model);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ namespace App\Models;
|
|||
use App\Lib\Helpers\FileStorageHelper;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
/**
|
||||
* @property string $picture Path of the picture (120px * 120px).
|
||||
|
|
@ -54,9 +55,14 @@ class Stamp extends Model
|
|||
});
|
||||
static::updated(function (self $model) {
|
||||
FileStorageHelper::removeOldFile($model, 'picture');
|
||||
Cache::forget('randomStampsFooter');
|
||||
});
|
||||
static::deleted(function (self $model) {
|
||||
FileStorageHelper::removeFile($model, 'picture');
|
||||
Cache::forget('randomStampsFooter');
|
||||
});
|
||||
static::created(function () {
|
||||
Cache::forget('randomStampsFooter');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 Uwil\Seo\Laravel\Interfaces\SeoInterface;
|
||||
use Uwil\Seo\Laravel\Objects\SeoItem;
|
||||
use Uwil\Seo\Laravel\Traits\SeoTrait;
|
||||
|
||||
/**
|
||||
* @property \App\Enums\StaticPageType $type Page type (StaticPageEnum).
|
||||
|
|
@ -19,10 +22,11 @@ use Illuminate\Support\Str;
|
|||
* @property-read \Illuminate\Support\Carbon $created_at Created date.
|
||||
* @property-read \Illuminate\Support\Carbon $updated_at Updated date.
|
||||
*/
|
||||
class StaticPage extends Model
|
||||
class StaticPage extends Model implements SeoInterface
|
||||
{
|
||||
use ActivityLog;
|
||||
use HasFactory;
|
||||
use SeoTrait;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
|
|
@ -57,7 +61,7 @@ class StaticPage extends Model
|
|||
});
|
||||
static::updating(function (self $model) {
|
||||
// * ASSERTIONS
|
||||
static::assertTitleIsUnique($model->title, $model->id);
|
||||
self::assertTitleIsUnique($model->title, $model->id);
|
||||
|
||||
// * CHANGES
|
||||
$model->slug = Str::slug($model->title);
|
||||
|
|
@ -83,4 +87,22 @@ class StaticPage extends Model
|
|||
ToolboxHelper::assertFieldIsUnique($table, 'title', $title, $id);
|
||||
ToolboxHelper::assertFieldIsUnique($table, 'slug', Str::slug($title), $id);
|
||||
}
|
||||
|
||||
// * SEO TRAIT OVERLOAD
|
||||
/**
|
||||
* Transform to seoModel
|
||||
*
|
||||
* @return \Uwil\Seo\Laravel\Objects\SeoItem
|
||||
*/
|
||||
public function toSeoItem(): SeoItem
|
||||
{
|
||||
return new SeoItem(
|
||||
\trans('models.classes.' . Str::singular($this->getTable())),
|
||||
$this->seo_title,
|
||||
$this->seo_description,
|
||||
true,
|
||||
\route(\config('seo.bo_route_prefix') . $this->getTable() . '.edit', $this),
|
||||
''
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,16 +4,15 @@ namespace App\Models;
|
|||
|
||||
use App\Enums\Users\RoleEnum;
|
||||
use App\Traits\Models\ActivityLog;
|
||||
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 Publication status.
|
||||
* @property \Illuminate\Support\Carbon $published_at Publication status update date.
|
||||
|
|
@ -37,7 +36,6 @@ class User extends Authenticatable
|
|||
'first_name',
|
||||
'last_name',
|
||||
'email',
|
||||
'password',
|
||||
'role',
|
||||
'published',
|
||||
'published_at',
|
||||
|
|
@ -49,7 +47,6 @@ class User extends Authenticatable
|
|||
* @var array<int, string>
|
||||
*/
|
||||
protected $hidden = [
|
||||
'password',
|
||||
'remember_token',
|
||||
];
|
||||
|
||||
|
|
@ -60,7 +57,7 @@ class User extends Authenticatable
|
|||
*/
|
||||
protected $casts = [
|
||||
'role' => RoleEnum::class,
|
||||
'email_verified_at' => 'datetime',
|
||||
'last_connection' => 'date',
|
||||
'published' => 'boolean',
|
||||
];
|
||||
|
||||
|
|
@ -72,7 +69,6 @@ class User extends Authenticatable
|
|||
protected static function booted(): void
|
||||
{
|
||||
static::creating(function (self $model) {
|
||||
static::updatePassword($model);
|
||||
// * Prevent user elevation privileges
|
||||
throw_if(
|
||||
auth('backend')->user() and auth('backend')->user()->role->value() > $model->role->value(),
|
||||
|
|
@ -80,7 +76,6 @@ class User extends Authenticatable
|
|||
);
|
||||
});
|
||||
static::updating(function (self $model) {
|
||||
static::updatePassword($model);
|
||||
if (optional(auth('backend')->user())->getKey() === $model->getKey()) {
|
||||
\validator(
|
||||
['published' => $model->published],
|
||||
|
|
@ -95,31 +90,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);
|
||||
}
|
||||
}
|
||||
|
||||
// * RELATIONS
|
||||
|
||||
/**
|
||||
* Activities logs One-to-many relationship.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function activityLogs(): \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
{
|
||||
return $this->hasMany(ActivityLog::class);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class TranslationServiceProvider extends ServiceProvider
|
|||
/**
|
||||
* Gather provided langs checking from files
|
||||
*
|
||||
* @return \Illuminate\Support\Collection<string, string>
|
||||
* @return \Illuminate\Support\Collection<int, string>
|
||||
*/
|
||||
private function collectLocalesStrings(): Collection
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace App\Providers;
|
|||
|
||||
use Illuminate\Pagination\Paginator;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\View;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
|
@ -20,6 +21,7 @@ class ViewServiceProvider extends ServiceProvider
|
|||
$appInfos = Cache::remember('composer', 360, function () {
|
||||
return json_decode(File::get(\app_path('../composer.json')));
|
||||
});
|
||||
|
||||
// Share composer.json infos.
|
||||
if (isset($appInfos->name) and isset($appInfos->version)) {
|
||||
View::share('cpsr_name', $appInfos->name);
|
||||
|
|
@ -28,12 +30,33 @@ class ViewServiceProvider extends ServiceProvider
|
|||
|
||||
if (!app()->runningInConsole()) {
|
||||
// * FORCE BOOTSTRAP PAGINATOR (or custom if in front)
|
||||
// Early boot, request wont be filled as expected.
|
||||
if (collect(explode('/', \request()->getPathInfo()))->get(1) === 'bo') {
|
||||
// For the moment, we exclude the seo page because the new pagination system doesn't work in the package.
|
||||
if (
|
||||
collect(explode('/', \request()->getPathInfo()))->get(1) === 'bo' &&
|
||||
collect(explode('/', \request()->getPathInfo()))->last() !== 'seo'
|
||||
) {
|
||||
Paginator::defaultView('bo.modules.pagination');
|
||||
} else {
|
||||
Paginator::useBootstrapFive();
|
||||
}
|
||||
}
|
||||
|
||||
// Get all the stamps that are pubished.
|
||||
$stamps = Cache::remember('randomStampsFooter', 360, function () {
|
||||
return DB::table('stamps')
|
||||
->select('picture', 'picture_alt', 'picture_title')
|
||||
->where('published', true)
|
||||
->get();
|
||||
});
|
||||
/**
|
||||
* Share a collection of 1 or 2 random stamps for footer.
|
||||
* First, check if $stamps is not empty, if not,
|
||||
* we count if the number of stamp in $stamps is greater than 2.
|
||||
* Then, pick 1 or 2 stamp(s) depending on the number of stamps.
|
||||
*/
|
||||
View::share(
|
||||
'randomStampsFooter',
|
||||
$stamps->isNotEmpty() ? $stamps->random($stamps->count() >= 2 ? 2 : 1) : []
|
||||
);
|
||||
} //end if
|
||||
}
|
||||
}
|
||||
|
|
|
|||
43
app/Rules/IsValidVimeoId.php
Normal file
43
app/Rules/IsValidVimeoId.php
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace App\Rules;
|
||||
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* Validate a vimeo ID regex
|
||||
*
|
||||
* @package App\Rules
|
||||
*/
|
||||
class IsValidVimeoId implements ValidationRule
|
||||
{
|
||||
/**
|
||||
* Run the validation rule.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @param mixed $value
|
||||
* @param \Closure(string):\Illuminate\Translation\PotentiallyTranslatedString $fail
|
||||
* @return void
|
||||
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInImplementedInterfaceBeforeLastUsed
|
||||
* @phpcs:disable Squiz.Commenting.FunctionComment.IncorrectTypeHint
|
||||
*/
|
||||
public function validate(string $attribute, mixed $value, \Closure $fail): void
|
||||
{
|
||||
// phpcs:enable
|
||||
if (!self::validates($value)) {
|
||||
$fail(trans('validation.vimeo_id'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a value
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return boolean
|
||||
*/
|
||||
public static function validates(mixed $value): bool
|
||||
{
|
||||
return Str::of($value)->isMatch('/^[0-9]{8,10}$/');
|
||||
}
|
||||
}
|
||||
44
app/Rules/IsValidYoutubeId.php
Normal file
44
app/Rules/IsValidYoutubeId.php
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace App\Rules;
|
||||
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* Validate a youtube ID regex
|
||||
*
|
||||
* @url https://webapps.stackexchange.com/questions/54443/format-for-id-of-youtube-video
|
||||
* @package App\Rules
|
||||
*/
|
||||
class IsValidYoutubeId implements ValidationRule
|
||||
{
|
||||
/**
|
||||
* Run the validation rule.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @param mixed $value
|
||||
* @param \Closure(string):\Illuminate\Translation\PotentiallyTranslatedString $fail
|
||||
* @return void
|
||||
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInImplementedInterfaceBeforeLastUsed
|
||||
* @phpcs:disable Squiz.Commenting.FunctionComment.IncorrectTypeHint
|
||||
*/
|
||||
public function validate(string $attribute, mixed $value, \Closure $fail): void
|
||||
{
|
||||
// phpcs:enable
|
||||
if (!self::validates($value)) {
|
||||
$fail(trans('validation.youtube_id'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a value
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return boolean
|
||||
*/
|
||||
public static function validates(mixed $value): bool
|
||||
{
|
||||
return Str::of($value)->isMatch('/^[0-9A-Za-z_-]{10}[048AEIMQUYcgkosw]$/');
|
||||
}
|
||||
}
|
||||
|
|
@ -37,18 +37,16 @@ trait ChangesModelOrder
|
|||
|
||||
return DB::transaction(function () use ($request, $className, $model) {
|
||||
/** @var \Illuminate\Database\Eloquent\Model|null */
|
||||
$tmp = $className::where('order', $request->direction ? '<' : '>', $model->order)
|
||||
$tmp = $className::where('order', $request->direction ? '<' : '>', $model->getOriginal('order'))
|
||||
->orderBy('order', $request->direction ? 'DESC' : 'ASC')->first();
|
||||
|
||||
if (!$tmp) {
|
||||
return back()->with('error', trans('crud.messages.order_not_changed'));
|
||||
}
|
||||
|
||||
$newOrder = $tmp->order;
|
||||
$tmp->order = $model->order;
|
||||
$model->order = $newOrder;
|
||||
$tmp->saveOrFail();
|
||||
$model->saveOrFail();
|
||||
$newOrder = $tmp->getOriginal('order');
|
||||
$tmp->update(['order' => $model->getOriginal('order')]);
|
||||
$model->update(['order' => $newOrder]);
|
||||
Session::flash('success', trans('crud.messages.order_changed'));
|
||||
|
||||
return back();
|
||||
|
|
|
|||
|
|
@ -19,8 +19,7 @@ trait UpdateModelPublished
|
|||
*/
|
||||
public function changePublished(Model $model)
|
||||
{
|
||||
$model->published = !$model->published;
|
||||
$model->saveOrFail();
|
||||
$model->update(['published' => !$model->getOriginal('published')]);
|
||||
return redirect()->back()->with('success', trans(__('crud.messages.publish_status_saved')));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,9 +118,9 @@ trait BaseEnum
|
|||
/**
|
||||
* Fetch enum using value.
|
||||
*
|
||||
* @param \App\Traits\Enums\BaseEnum|integer|string $value
|
||||
* @param self|integer|string $value
|
||||
* @param string $field
|
||||
* @return \App\Traits\Enums\BaseEnum|null
|
||||
* @return self|null
|
||||
*/
|
||||
public static function make(self|int|string $value, string $field = 'value'): self|null
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Traits\Models;
|
||||
|
||||
use App\Models\ActivityLog as ModelsActivityLog;
|
||||
use App\Observers\ModelObserver;
|
||||
|
||||
/**
|
||||
|
|
@ -20,4 +21,16 @@ trait ActivityLog
|
|||
{
|
||||
static::observe(ModelObserver::class);
|
||||
}
|
||||
|
||||
// * RELATIONS
|
||||
|
||||
/**
|
||||
* Activities logs One-to-many relationship.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function activityLogs(): \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
{
|
||||
return $this->hasMany(ModelsActivityLog::class);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ use Illuminate\Support\Facades\Cache;
|
|||
/**
|
||||
* ! Use this only on limited elements, (not on tags, or products, or posts for ex.)
|
||||
*
|
||||
* @property private static array $cacheConditions Eloquent condition to cache elements (to be used in where statement).
|
||||
* @property array<string,string|integer|float|boolean> $cacheConditions
|
||||
* Eloquent condition to cache elements (to be used in where statement).
|
||||
*/
|
||||
trait IsCachedAsCollection
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,180 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Traits\Models;
|
||||
|
||||
use App\Enums\InputType;
|
||||
use App\Lib\Helpers\FileStorageHelper;
|
||||
use App\Lib\Helpers\ToolboxHelper;
|
||||
|
||||
trait MiniCrudModel
|
||||
{
|
||||
/**
|
||||
* Fill the model with an array of attributes.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return void
|
||||
* @throws \Illuminate\Database\Eloquent\MassAssignmentException If fill prop is not allowed.
|
||||
* @phpcs:disable Squiz.Commenting.FunctionComment.EmptyThrows
|
||||
*/
|
||||
public function fill(array $attributes)
|
||||
{
|
||||
// phpcs:enable
|
||||
parent::fill($attributes);
|
||||
if (isset($attributes['data'])) {
|
||||
$this->setData($attributes['data']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply function on data typed text while on save event
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function minicrudCreating()
|
||||
{
|
||||
/** @var array<string,array> */
|
||||
$data = $this->data;
|
||||
foreach ($data as &$input) {
|
||||
switch ($input['inputType']) {
|
||||
case InputType::text->value:
|
||||
$input['text'] = clean($input['text']);
|
||||
$input['text'] = FileStorageHelper::storeModelFilesFromHtml($this, $input['text']);
|
||||
break;
|
||||
} //end switch
|
||||
} //end foreach
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply function on data typed text while on update event
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function minicrudUpdating()
|
||||
{
|
||||
$this->minicrudCreating();
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply function on data typed text while on updated event
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function minicrudUpdated()
|
||||
{
|
||||
/** @var array */
|
||||
foreach ($this->data as $index => $input) {
|
||||
switch ($input['inputType']) {
|
||||
case InputType::text->value:
|
||||
$original = ToolboxHelper::getOriginal($this, 'data');
|
||||
FileStorageHelper::removeOldModelFilesFromHtml(
|
||||
$input['text'],
|
||||
$original[$index]['text'] ?? ''
|
||||
);
|
||||
break;
|
||||
} //end switch
|
||||
} //end foreach
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply function on data typed text while on deleted event
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function minicrudDeleted()
|
||||
{
|
||||
/** @var array */
|
||||
foreach ($this->data as $input) {
|
||||
switch ($input['inputType']) {
|
||||
case InputType::text->value:
|
||||
FileStorageHelper::removeModelFilesOfHtml($input['text']);
|
||||
break;
|
||||
} //end switch
|
||||
} //end foreach
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a specific prop
|
||||
*
|
||||
* @param array $data
|
||||
* @return void
|
||||
*/
|
||||
private function setData(array $data): void
|
||||
{
|
||||
$attrs = $this->attributes;
|
||||
if (isset($attrs['data'])) {
|
||||
unset($attrs['data']);
|
||||
}
|
||||
$this->setAttribute('data', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a specific prop
|
||||
*
|
||||
* @param array $value
|
||||
* @return void
|
||||
*/
|
||||
protected function setDataAttribute(array $value): void
|
||||
{
|
||||
$this->attributes['data'] = $this->castAttributeAsJson(
|
||||
'data',
|
||||
$this->serializeData($value)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a specific prop
|
||||
*
|
||||
* @param string|null $data
|
||||
* @return array
|
||||
*/
|
||||
protected function getDataAttribute(string|null $data): array
|
||||
{
|
||||
return $this->fromJson($data ?? $this->attributes['data'] ?? '[]');
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize properties
|
||||
*
|
||||
* @param array $data
|
||||
* @return array
|
||||
* @throws \ErrorException If input type is no handled.
|
||||
* @throws \Illuminate\Validation\ValidationException If url is a bo url.
|
||||
* @phpcs:disable Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
|
||||
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
|
||||
*/
|
||||
private function serializeData(array $data): array
|
||||
{
|
||||
foreach ($data as $o => $input) {
|
||||
switch ($input['inputType']) {
|
||||
case InputType::image->value:
|
||||
$data[$o]['value'] = \preg_replace(
|
||||
'/^\/|^/',
|
||||
'',
|
||||
FileStorageHelper::storeFile($this, $input['value'], true)
|
||||
);
|
||||
break;
|
||||
case InputType::selectEnum->value:
|
||||
case InputType::boolean->value:
|
||||
case InputType::password->value:
|
||||
case InputType::email->value:
|
||||
case InputType::number->value:
|
||||
case InputType::videoVimeo->value:
|
||||
case InputType::videoYoutube->value:
|
||||
case InputType::video->value:
|
||||
break;
|
||||
case InputType::string->value:
|
||||
case InputType::text->value:
|
||||
case InputType::url->value:
|
||||
ToolboxHelper::assertNoInternalBoUrls('content', $input['value']);
|
||||
break;
|
||||
default:
|
||||
throw new \ErrorException(sprintf(
|
||||
'Unknown input Type %s',
|
||||
$input['inputType']
|
||||
));
|
||||
} //end switch
|
||||
} //end foreach
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
|
@ -45,9 +45,11 @@ trait HasPicture
|
|||
* @param integer|null $minHeight
|
||||
* @param integer|null $maxWith
|
||||
* @param integer|null $maxHeight
|
||||
* @param integer|null $size
|
||||
* @param boolean $nullable
|
||||
* @param integer|null $size
|
||||
* @param string|null $requiredWith
|
||||
* @param string|null $requiredWithout
|
||||
* @param string|null $requiredIf
|
||||
* @return array
|
||||
*/
|
||||
public function pictureRules(
|
||||
|
|
@ -56,9 +58,11 @@ trait HasPicture
|
|||
?int $minHeight = null,
|
||||
?int $maxWith = null,
|
||||
?int $maxHeight = null,
|
||||
?int $size = null,
|
||||
bool $nullable = false,
|
||||
?int $size = null,
|
||||
?string $requiredWith = null,
|
||||
?string $requiredWithout = null,
|
||||
?string $requiredIf = null,
|
||||
): array {
|
||||
$dimensions = (object)[
|
||||
'minWith' => $minWith ?? $this->minWith,
|
||||
|
|
@ -69,10 +73,12 @@ trait HasPicture
|
|||
return [
|
||||
$name => [
|
||||
!$nullable ? 'required' : 'nullable',
|
||||
(strlen($requiredWith)) ? 'required_with:' . $requiredWith : '',
|
||||
($size) ? 'max:' . $size : '',
|
||||
(!empty($requiredWith)) ? "required_with:{$requiredWith}" : '',
|
||||
(!empty($requiredWithout)) ? "required_without:{$requiredWithout}" : '',
|
||||
(!empty($requiredIf)) ? "required_if:{$requiredIf}" : '',
|
||||
($size) ? "max:{$size}" : '',
|
||||
function (string $attribute, $value, callable $fail) use ($dimensions) {
|
||||
return ToolboxHelper::validatePicture($attribute, $value, $fail, $dimensions);
|
||||
ToolboxHelper::validatePicture($attribute, $value, $fail, $dimensions);
|
||||
}
|
||||
]
|
||||
];
|
||||
|
|
@ -107,7 +113,7 @@ trait HasPicture
|
|||
"{$name}Validate.*" => [
|
||||
'required',
|
||||
function (string $attribute, $value, callable $fail) use ($sizes) {
|
||||
return $this->validatePicture($attribute, $value, $fail, $sizes);
|
||||
ToolboxHelper::validatePicture($attribute, $value, $fail, $sizes);
|
||||
}
|
||||
]
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,31 +1,34 @@
|
|||
{
|
||||
"name": "uwil/agis",
|
||||
"version": "1.0.0",
|
||||
"version": "2.0.0",
|
||||
"type": "project",
|
||||
"description": "Agis website.",
|
||||
"require": {
|
||||
"php": "^8.2",
|
||||
"diglactic/laravel-breadcrumbs": "^8.0",
|
||||
"guzzlehttp/guzzle": "^7.2",
|
||||
"laravel/framework": "^10.0",
|
||||
"laravel/tinker": "^2.8",
|
||||
"laravel/ui": "^4.2",
|
||||
"php": "^8.5",
|
||||
"diglactic/laravel-breadcrumbs": "^10.1",
|
||||
"guzzlehttp/guzzle": "^7.9",
|
||||
"laravel/framework": "^12.0",
|
||||
"laravel/tinker": "^3.0",
|
||||
"laravel/ui": "^4.6",
|
||||
"mews/purifier": "^3.4",
|
||||
"sentry/sentry-laravel": "*"
|
||||
"scaler-tech/laravel-saml2": "^2.5",
|
||||
"sentry/sentry-laravel": "^4.25",
|
||||
"uwil/laravel-admin-secure": "^6.0",
|
||||
"uwil/k8s-laravel": "^3.0",
|
||||
"uwil/seo-laravel": "^4.0",
|
||||
"uwil/sitemap-generator": "^5.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"fakerphp/faker": "^1.9.1",
|
||||
"kitloong/laravel-migrations-generator": "^6.8",
|
||||
"krlove/eloquent-model-generator": "dev-l10-compatibility",
|
||||
"laravel-lang/common": "^4.0",
|
||||
"fakerphp/faker": "^1.23",
|
||||
"larastan/larastan": "^3.0",
|
||||
"laravel-lang/common": "^6.0",
|
||||
"laravel/pint": "^1.0",
|
||||
"laravel/sail": "^1.18",
|
||||
"mockery/mockery": "^1.4.4",
|
||||
"nunomaduro/collision": "^7.0",
|
||||
"phpunit/phpunit": "^10.0",
|
||||
"laravel/sail": "^1.41",
|
||||
"mockery/mockery": "^1.6",
|
||||
"nunomaduro/collision": "^8.6",
|
||||
"phpunit/phpunit": "^11.5",
|
||||
"slevomat/coding-standard": "^8.10",
|
||||
"spatie/laravel-ignition": "^2.0",
|
||||
"thedoctor0/laravel-factory-generator": "^1.2"
|
||||
"spatie/laravel-ignition": "^2.9"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
|
@ -36,8 +39,8 @@
|
|||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/laravel-shift/eloquent-model-generator.git"
|
||||
"type": "composer",
|
||||
"url": "https://lab.s-web.fr/api/v4/group/23/-/packages/composer/packages.json"
|
||||
}
|
||||
],
|
||||
"autoload-dev": {
|
||||
|
|
|
|||
8199
composer.lock
generated
8199
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
|
||||
|
|
|
|||
|
|
@ -96,6 +96,11 @@ return [
|
|||
'name' => env('MAIL_FROM_NAME', 'Example'),
|
||||
],
|
||||
|
||||
'contactform' => [
|
||||
'receiver' => explode(',', env('MAIL_CONTACTFORM_RECEIVER', 'hello@example.com')),
|
||||
'customerService' => explode(',', env('MAIL_CONTACTFORM_CUSTOMER_SERVICE_RECEIVER'))
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Markdown Mail Settings
|
||||
|
|
|
|||
397
config/saml2.php
Normal file
397
config/saml2.php
Normal file
|
|
@ -0,0 +1,397 @@
|
|||
<?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)
|
||||
|
||||
];
|
||||
12
config/seo.php
Normal file
12
config/seo.php
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'bo_route_prefix' => 'bo.',
|
||||
'blade' => 'bo.pages.seo.index',
|
||||
'middlewares' => [
|
||||
'web',
|
||||
'admin-secure',
|
||||
'auth:backend'
|
||||
],
|
||||
'guard' => 'backend'
|
||||
];
|
||||
|
|
@ -38,4 +38,8 @@ return [
|
|||
'version' => env('GOOGLE_RECAPTCHA_VERSION', "3") === "3" ? true : false
|
||||
]
|
||||
],
|
||||
|
||||
'matomo' => [
|
||||
'site_id' => env('MATOMO_SITE_ID')
|
||||
]
|
||||
];
|
||||
|
|
|
|||
85
config/sitemap-generator.php
Normal file
85
config/sitemap-generator.php
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
/**
|
||||
* Single route names
|
||||
*
|
||||
* Ex:
|
||||
*
|
||||
* 'singlePages' => [
|
||||
* 'homepage',
|
||||
* ],
|
||||
*/
|
||||
'singlePages' => [
|
||||
'fo.homepage',
|
||||
'fo.explorer',
|
||||
'fo.convictions',
|
||||
'fo.joinus.show',
|
||||
'fo.contact.show',
|
||||
'fo.aboutus.show',
|
||||
'fo.legals.show',
|
||||
'fo.policies.show',
|
||||
'fo.ranges.index',
|
||||
'fo.news.index'
|
||||
],
|
||||
|
||||
/**
|
||||
* Model namespaces with filters
|
||||
*
|
||||
* Ex:
|
||||
* 'cruds' => [
|
||||
* [
|
||||
* 'model' => 'App\Models\Product',
|
||||
* 'filters' => [
|
||||
* ['published', '=', true]
|
||||
* ]
|
||||
* ],
|
||||
* [
|
||||
* 'model' => 'App\Models\Article',
|
||||
* 'filters' => []
|
||||
* ]
|
||||
* ],
|
||||
*/
|
||||
'cruds' => [
|
||||
[
|
||||
'model' => 'App\Models\Product',
|
||||
'filters' => [
|
||||
['published', '=', true]
|
||||
],
|
||||
|
||||
],
|
||||
[
|
||||
'model' => 'App\Models\Range',
|
||||
'filters' => [
|
||||
['published', '=', true]
|
||||
],
|
||||
|
||||
],
|
||||
[
|
||||
'model' => 'App\Models\News',
|
||||
'filters' => [
|
||||
['published', '=', true]
|
||||
],
|
||||
|
||||
]
|
||||
],
|
||||
|
||||
/**
|
||||
* Enable or disable schedule for the job
|
||||
* If set to true the sitemap generator will be run
|
||||
* using the 'cron' instruction
|
||||
*/
|
||||
'schedule' => true,
|
||||
|
||||
/**
|
||||
* If you want to set specific
|
||||
* instruction for when to schedule job
|
||||
* you can set this with a cron instruction
|
||||
* You can generate one using https://crontab.guru/
|
||||
*
|
||||
* schedule must be set to true
|
||||
*
|
||||
* Default is every day at 15:45
|
||||
*/
|
||||
'cron' => '45 15 * * *',
|
||||
];
|
||||
|
|
@ -20,35 +20,35 @@ class ProductFactory extends Factory
|
|||
|
||||
$nutritionnal_values = [
|
||||
'energyKj' => [
|
||||
'label' => 'Energie en Kj',
|
||||
'label' => 'ÉNERGIE (kJ)',
|
||||
'value' => fake()->randomFloat(2, 0, 70)
|
||||
],
|
||||
'energyKcal' => [
|
||||
'label' => 'Energie en kcal',
|
||||
'label' => 'ÉNERGIE (kcal)',
|
||||
'value' => fake()->randomFloat(2, 0, 70)
|
||||
],
|
||||
'fat' => [
|
||||
'label' => 'Matières grasses',
|
||||
'label' => 'MATIÈRES GRASSES (g)',
|
||||
'value' => fake()->randomFloat(2, 0, 70)
|
||||
],
|
||||
'saturated-fat' => [
|
||||
'label' => 'dont acides gras saturés',
|
||||
'label' => 'ACIDES GRAS SATURÉS (g)',
|
||||
'value' => fake()->randomFloat(2, 0, 70)
|
||||
],
|
||||
'carbohydrate' => [
|
||||
'label' => 'Glucides',
|
||||
'label' => 'GLUCIDES (g)',
|
||||
'value' => fake()->randomFloat(2, 0, 70)
|
||||
],
|
||||
'sugar' => [
|
||||
'label' => 'dont sucres',
|
||||
'label' => 'SUCRES (g)',
|
||||
'value' => fake()->randomFloat(2, 0, 70)
|
||||
],
|
||||
'proteins' => [
|
||||
'label' => 'Protéines',
|
||||
'label' => 'PROTÉINES (g)',
|
||||
'value' => fake()->randomFloat(2, 0, 70)
|
||||
],
|
||||
'salt' => [
|
||||
'label' => 'Sel',
|
||||
'label' => 'SEL (g)',
|
||||
'value' => fake()->randomFloat(2, 0, 70)
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@ class UserFactory extends Factory
|
|||
'first_name' => fake()->firstname(),
|
||||
'last_name' => fake()->lastname(),
|
||||
'email' => fake()->unique()->safeEmail(),
|
||||
'email_verified_at' => now(),
|
||||
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi',
|
||||
'remember_token' => Str::random(10),
|
||||
'role' => \collect(RoleEnum::toArray())->random()->value,
|
||||
'published' => $published,
|
||||
|
|
@ -36,7 +34,7 @@ class UserFactory extends Factory
|
|||
*/
|
||||
public function unverified(): static
|
||||
{
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found
|
||||
return $this->state(fn(array $attributes) => [
|
||||
'email_verified_at' => null,
|
||||
]);
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 3.3 KiB |
BIN
database/factories/assets/ranges/default-picture-680x300.png
Normal file
BIN
database/factories/assets/ranges/default-picture-680x300.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.6 KiB |
|
|
@ -15,14 +15,14 @@ return new class extends Migration
|
|||
{
|
||||
Schema::create('convictionpages', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->float('key_feed')->comment('Chiffre clé \'bien nourrir\'');
|
||||
$table->float('key_earth_1')->comment('Chiffre clé \'respecter la terre\' 1');
|
||||
$table->float('key_earth_2')->comment('Chiffre clé \'respecter la terre\' 2');
|
||||
$table->float('key_together_1')->comment('Chiffre clé \'vivre ensemble\' 1');
|
||||
$table->float('key_together_2')->comment('Chiffre clé \'vivre ensemble\' 2');
|
||||
$table->float('key_together_3')->comment('Chiffre clé \'vivre ensemble\' 3');
|
||||
$table->float('key_together_4')->comment('Chiffre clé \'vivre ensemble\' 4');
|
||||
$table->float('key_territory')->comment('Chiffre clé \'intégrer son territoire\'');
|
||||
$table->float('key_feed', 12)->comment('Chiffre clé \'bien nourrir\'');
|
||||
$table->float('key_earth_1', 12)->comment('Chiffre clé \'respecter la terre\' 1');
|
||||
$table->float('key_earth_2', 12)->comment('Chiffre clé \'respecter la terre\' 2');
|
||||
$table->float('key_together_1', 12)->comment('Chiffre clé \'vivre ensemble\' 1');
|
||||
$table->float('key_together_2', 12)->comment('Chiffre clé \'vivre ensemble\' 2');
|
||||
$table->float('key_together_3', 12)->comment('Chiffre clé \'vivre ensemble\' 3');
|
||||
$table->float('key_together_4', 12)->comment('Chiffre clé \'vivre ensemble\' 4');
|
||||
$table->float('key_territory', 12)->comment('Chiffre clé \'intégrer son territoire\'');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ return new class extends Migration
|
|||
$table->string('picture_alt')->comment('Attribut alt pour l\'image picture');
|
||||
$table->string('picture_title')->comment('Attribut title pour l\'image picture');
|
||||
$table->string('picture_productsheet')
|
||||
->comment('Path de l\'image à afficher sur les fiches produits de cette gamme (332px * 442px)');
|
||||
->comment('Path de l\'image à afficher sur les fiches produits de cette gamme (680px * 300px)');
|
||||
$table->string('picture_productsheet_alt')
|
||||
->comment('Attribut alt de l\'image à afficher sur les fiches produits');
|
||||
$table->string('picture_productsheet_title')
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
<?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('homepages', function (Blueprint $table) {
|
||||
$table->string('picture')->nullable()->change()
|
||||
->comment('Path de l\'image de la page d\'accueil (640px * 390px)');
|
||||
$table->string('youtube_video_id')->after('picture_title')
|
||||
->nullable()
|
||||
->default(null)
|
||||
->comment('L\ídentifiant de la vidéo Youtube');
|
||||
$table->boolean('display_video')->after('youtube_video_id')
|
||||
->default(false)
|
||||
->comment('Afficher la video ou l\'image');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('homepages', function (Blueprint $table) {
|
||||
$table->string('picture')->change()
|
||||
->comment('Path de l\'image de la page d\'accueil (640px * 390px)');
|
||||
$table->dropColumn('youtube_video_id');
|
||||
$table->dropColumn('display_video');
|
||||
});
|
||||
}
|
||||
};
|
||||
32
database/migrations/2024_02_09_111729_setup_vimeo_video.php
Normal file
32
database/migrations/2024_02_09_111729_setup_vimeo_video.php
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<?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('homepages', function (Blueprint $table) {
|
||||
$table->renameColumn('youtube_video_id', 'video_id');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('homepages', function (Blueprint $table) {
|
||||
$table->renameColumn('video_id', 'youtube_video_id');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -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');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -21,7 +21,7 @@ class RangeSeeder extends Seeder
|
|||
'../database/factories/assets/ranges/default-picture-466x440.png'
|
||||
)));
|
||||
$range->picture_productsheet = FileStorageHelper::storeFile($range, new \SplFileInfo(\resource_path(
|
||||
'../database/factories/assets/ranges/default-picture-332x442.png'
|
||||
'../database/factories/assets/ranges/default-picture-680x300.png'
|
||||
)));
|
||||
$range->picture_thumbnail = FileStorageHelper::storeFile($range, new \SplFileInfo(\resource_path(
|
||||
'../database/factories/assets/ranges/default-picture-246x337.png'
|
||||
|
|
|
|||
|
|
@ -36,10 +36,10 @@ class StaticPageSeeder extends Seeder
|
|||
'type' => StaticPageType::legals,
|
||||
],
|
||||
[
|
||||
'seo_title' => 'Seo title pour la page mentions légales',
|
||||
'seo_description' => 'Seo description pour la page mentions légales',
|
||||
'title' => 'Mentions légales',
|
||||
'slug' => Str::slug('Mentions légales'),
|
||||
'seo_title' => 'Seo title pour la page mentions légales et CGU',
|
||||
'seo_description' => 'Seo description pour la page mentions légales et CGU',
|
||||
'title' => 'Mentions légales et CGU',
|
||||
'slug' => Str::slug('Mentions légales et CGU'),
|
||||
'type' => StaticPageType::legals,
|
||||
'content' => \clean(\fake()->randomHtml(6, 7)),
|
||||
]
|
||||
|
|
|
|||
177
manifest.yaml
Normal file
177
manifest.yaml
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: ${CI_PROJECT_PATH_SLUG}-config-map
|
||||
data:
|
||||
APP_NAME: "${APP_APP_NAME}"
|
||||
APP_ENV: "${APP_APP_ENV}"
|
||||
APP_KEY: "${APP_APP_KEY}"
|
||||
APP_DEBUG: "${APP_APP_DEBUG}"
|
||||
APP_URL: "https://${REDIRECT}${APP_DOMAIN}"
|
||||
LOG_CHANNEL: "k8s"
|
||||
DB_HOST: "${APP_DB_HOST}"
|
||||
DB_DATABASE: "${APP_DB_DATABASE}"
|
||||
DB_USERNAME: "${APP_DB_USERNAME}"
|
||||
DB_PASSWORD: "${APP_DB_PASSWORD}"
|
||||
MAIL_HOST: "${APP_MAIL_HOST}"
|
||||
MAIL_PORT: "${APP_MAIL_PORT}"
|
||||
MAIL_USERNAME: "${APP_MAIL_USERNAME}"
|
||||
MAIL_PASSWORD: "${APP_MAIL_PASSWORD}"
|
||||
MAIL_ENCRYPTION: "${APP_MAIL_ENCRYPTION}"
|
||||
MAIL_FROM_ADDRESS: "${APP_MAIL_FROM_ADDRESS}"
|
||||
MAIL_FROM_NAME: "${APP_APP_NAME}"
|
||||
MAIL_CONTACTFORM_RECEIVER: "${APP_MAIL_CONTACTFORM_RECEIVER}"
|
||||
MAIL_CONTACTFORM_CUSTOMER_SERVICE_RECEIVER: "${APP_MAIL_CONTACTFORM_CUSTOMER_SERVICE_RECEIVER}"
|
||||
LDC_WEB_API_KEY: "${APP_LDC_WEB_API_KEY}"
|
||||
GOOGLE_RECAPTCHA_PRIVATE: "${APP_GOOGLE_RECAPTCHA_PRIVATE}"
|
||||
GOOGLE_RECAPTCHA_PUBLIC: "${APP_GOOGLE_RECAPTCHA_PUBLIC}"
|
||||
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}"
|
||||
SAML2_DEFAULT_TENANT_UUID: "${APP_SAML2_DEFAULT_TENANT_UUID}"
|
||||
UWIL_ADMIN_SECURE_CIDR_LIST: "${APP_GLOBAL_UWIL_ADMIN_SECURE_CIDR_LIST}"
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: ${CI_PROJECT_PATH_SLUG}-pvc-storage
|
||||
spec:
|
||||
storageClassName: "csi-cinder-classic"
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: $APP_PVC_SIZE
|
||||
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: ${CI_PROJECT_PATH_SLUG}-deployment
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: ${CI_PROJECT_PATH_SLUG}-app
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
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
|
||||
resources:
|
||||
limits:
|
||||
cpu: "${APP_CI_CPU_LIMIT}"
|
||||
memory: "${APP_CI_MEMORY_LIMIT}"
|
||||
requests:
|
||||
cpu: "${APP_CI_CPU_REQUEST}"
|
||||
memory: "${APP_CI_MEMORY_REQUEST}"
|
||||
volumeMounts:
|
||||
- name: storage
|
||||
mountPath: /app/srcs/storage
|
||||
imagePullSecrets:
|
||||
- name: docker-registry-credentials
|
||||
securityContext:
|
||||
runAsUser: 82
|
||||
runAsGroup: 82
|
||||
fsGroup: 82
|
||||
fsGroupChangePolicy: "OnRootMismatch"
|
||||
volumes:
|
||||
- name: storage
|
||||
persistentVolumeClaim:
|
||||
claimName: ${CI_PROJECT_PATH_SLUG}-pvc-storage
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: ${CI_PROJECT_PATH_SLUG}-service
|
||||
spec:
|
||||
selector:
|
||||
app: ${CI_PROJECT_PATH_SLUG}-app
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
|
||||
---
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
name: ${CI_PROJECT_PATH_SLUG}-ingress-route
|
||||
spec:
|
||||
entryPoints:
|
||||
- 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
|
||||
tls:
|
||||
secretName: ${CRT_TLS_NAME}
|
||||
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: ${CI_PROJECT_PATH_SLUG}-cronjob
|
||||
spec:
|
||||
schedule: "* * * * *"
|
||||
successfulJobsHistoryLimit: 1
|
||||
failedJobsHistoryLimit: 1
|
||||
concurrencyPolicy: Forbid
|
||||
jobTemplate:
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
affinity:
|
||||
podAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
- 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: storage
|
||||
persistentVolumeClaim:
|
||||
claimName: ${CI_PROJECT_PATH_SLUG}-pvc-storage
|
||||
securityContext:
|
||||
runAsUser: 82
|
||||
runAsGroup: 82
|
||||
fsGroup: 82
|
||||
fsGroupChangePolicy: "OnRootMismatch"
|
||||
restartPolicy: OnFailure
|
||||
3226
package-lock.json
generated
3226
package-lock.json
generated
File diff suppressed because it is too large
Load diff
43
package.json
43
package.json
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"private": true,
|
||||
"name": "srcs",
|
||||
"scripts": {
|
||||
"vite": "vite --clearScreen false",
|
||||
"prod": "vite build --mode production",
|
||||
|
|
@ -15,12 +16,11 @@
|
|||
"devDependencies": {
|
||||
"@babel/core": "^7.22.11",
|
||||
"@babel/types": "^7.21.2",
|
||||
"@fortawesome/fontawesome-svg-core": "latest",
|
||||
"@fortawesome/free-brands-svg-icons": "latest",
|
||||
"@fortawesome/free-regular-svg-icons": "latest",
|
||||
"@fortawesome/free-solid-svg-icons": "latest",
|
||||
"@fortawesome/vue-fontawesome": "^3.0.3",
|
||||
"@ldc-web/cookie-notice": "^3.0.9",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.5.1",
|
||||
"@fortawesome/free-regular-svg-icons": "^6.5.1",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.5.1",
|
||||
"@fortawesome/vue-fontawesome": "^3.0.5",
|
||||
"@ldc-web/cookie-notice": "^6.0.3",
|
||||
"@sipec/vue3-tags-input": "^3.0.4",
|
||||
"@types/bootstrap": "^5.2.7",
|
||||
"@types/node": "^20.8.2",
|
||||
|
|
@ -28,11 +28,10 @@
|
|||
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
||||
"@typescript-eslint/parser": "^5.36.2",
|
||||
"@vitejs/plugin-basic-ssl": "^1.0.1",
|
||||
"@vitejs/plugin-legacy": "latest",
|
||||
"@vitejs/plugin-vue": "latest",
|
||||
"@vitejs/plugin-vue": "^4.6.2",
|
||||
"@vue/compiler-sfc": "latest",
|
||||
"@vue/eslint-config-typescript": "latest",
|
||||
"@vue/tsconfig": "latest",
|
||||
"@vue/tsconfig": "^0.4.0",
|
||||
"axios": "^1.5.1",
|
||||
"bootstrap": "^5.3.2",
|
||||
"chart.js": "^4.4.0",
|
||||
|
|
@ -40,33 +39,37 @@
|
|||
"eslint": "latest",
|
||||
"eslint-import-resolver-alias": "^1.1.2",
|
||||
"eslint-plugin-vue": "latest",
|
||||
"laravel-vite-plugin": "latest",
|
||||
"laravel-vite-plugin": "^0.8.1",
|
||||
"postcss-discard-comments": "^6.0.0",
|
||||
"prettier": "latest",
|
||||
"print-js": "^1.6.0",
|
||||
"resolve-url-loader": "^5.0.0",
|
||||
"rollup-plugin-copy": "^3.5.0",
|
||||
"sass": "latest",
|
||||
"slugify": "^1.6.6",
|
||||
"stylelint": "latest",
|
||||
"stylelint": "^15.11.0",
|
||||
"stylelint-config-idiomatic-order": "github:ream88/stylelint-config-idiomatic-order",
|
||||
"stylelint-config-sass-guidelines": "latest",
|
||||
"stylelint-config-standard-scss": "latest",
|
||||
"stylelint-scss": "latest",
|
||||
"stylelint-config-sass-guidelines": "^10.0.0",
|
||||
"stylelint-config-standard-scss": "^11.1.0",
|
||||
"stylelint-scss": "^5.3.2",
|
||||
"sweetalert2": "^11.7.31",
|
||||
"swiper": "^10.2.0",
|
||||
"swiper": "^11.0.5",
|
||||
"terser": "latest",
|
||||
"toastify-js": "^1.12.0",
|
||||
"ts-loader": "^9.3.1",
|
||||
"typescript": ">=3.3.1 <5.2.0",
|
||||
"typescript-eslint": "latest",
|
||||
"typescript": "latest",
|
||||
"vite": "^4.5.1",
|
||||
"vite-plugin-babel": "latest",
|
||||
"vite-plugin-checker": "latest",
|
||||
"vite-plugin-eslint": "latest",
|
||||
"vite-plugin-stylelint": "latest",
|
||||
"vite": "^4.0.0",
|
||||
"vue-eslint-parser": "^9.1.0",
|
||||
"vue-loader": "^16.8.3",
|
||||
"vue": "latest",
|
||||
"vue-tsc": "1.6.0"
|
||||
"vue-eslint-parser": "^9.3.2",
|
||||
"vue-loader": "^17.3.1",
|
||||
"vue-tsc": "1.8.11"
|
||||
},
|
||||
"dependencies": {
|
||||
"meow": "^9.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
10
phpstan.neon
Normal file
10
phpstan.neon
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
includes:
|
||||
- vendor/larastan/larastan/extension.neon
|
||||
|
||||
parameters:
|
||||
|
||||
paths:
|
||||
- app/
|
||||
|
||||
# Level 9 is the highest level
|
||||
level: 5
|
||||
13
production-resources.yaml
Normal file
13
production-resources.yaml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Certificate
|
||||
metadata:
|
||||
name: $APP_DOMAIN
|
||||
spec:
|
||||
dnsNames:
|
||||
- $APP_DOMAIN
|
||||
- www.${APP_DOMAIN}
|
||||
secretName: $APP_DOMAIN
|
||||
issuerRef:
|
||||
name: $APP_CERT_ISSUER
|
||||
kind: ClusterIssuer
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 0 B After Width: | Height: | Size: 15 KiB |
|
|
@ -1,2 +1,13 @@
|
|||
User-agent: *
|
||||
Disallow:
|
||||
Disallow: /bo
|
||||
|
||||
User-agent: GPTBot
|
||||
Disallow: /
|
||||
|
||||
User-agent: Amazonbot
|
||||
Disallow: /
|
||||
|
||||
User-agent: ClaudeBot
|
||||
Disallow: /
|
||||
|
||||
Sitemap: https://www.agis-sa.fr/sitemap.xml
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue