From 84d1ec9578ce6bc47022c95e9cdd630425d57948 Mon Sep 17 00:00:00 2001 From: Noah Lancien Date: Mon, 20 Apr 2026 09:51:06 +0200 Subject: [PATCH] fix: :bug: Use the packaged admin-secure middleware --- .../Controllers/Fo/StaticPageController.php | 2 +- app/Http/Kernel.php | 1 - app/Http/Middleware/AdminSecureMiddleware.php | 49 ------ app/Lib/AdminSecure.php | 131 --------------- app/Lib/Options.php | 159 ------------------ composer.json | 1 + composer.lock | 80 ++++++++- phpcs.xml | 6 - 8 files changed, 74 insertions(+), 355 deletions(-) delete mode 100644 app/Http/Middleware/AdminSecureMiddleware.php delete mode 100644 app/Lib/AdminSecure.php delete mode 100644 app/Lib/Options.php diff --git a/app/Http/Controllers/Fo/StaticPageController.php b/app/Http/Controllers/Fo/StaticPageController.php index 5597b3e..307c3be 100644 --- a/app/Http/Controllers/Fo/StaticPageController.php +++ b/app/Http/Controllers/Fo/StaticPageController.php @@ -26,7 +26,7 @@ class StaticPageController extends Controller /** * Game rules show * - * @param \App\Models\StaticPage $legalPage + * @param \App\Models\StaticPage $rulesPage * @return \Illuminate\Contracts\View\View */ public function rules(StaticPage $rulesPage) diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 9b7a8f8..857758a 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -73,6 +73,5 @@ class Kernel extends HttpKernel 'htmlsanitize' => \App\Http\Middleware\HtmlSanitizer::class, 'crm_questions' => \App\Http\Middleware\CrmMiddlewareQuestions::class, 'json_only' => \App\Http\Middleware\JsonOnly::class, - 'admin-secure' => \App\Http\Middleware\AdminSecureMiddleware::class, ]; } diff --git a/app/Http/Middleware/AdminSecureMiddleware.php b/app/Http/Middleware/AdminSecureMiddleware.php deleted file mode 100644 index 1851b93..0000000 --- a/app/Http/Middleware/AdminSecureMiddleware.php +++ /dev/null @@ -1,49 +0,0 @@ -getCidrList()) - ->reduce(function ($initial, $ip_range) use ($client_ip) { - return $initial || IP::contains( - $ip_range, - $client_ip - )->unwrap(); - }); - - $ip_is_allowed_by_config = \collect(AdminSecure::getOptions()->getCidrAllowedList()) - ->reduce(function ($initial, $ip_range) use ($client_ip) { - return $initial || IP::contains( - $ip_range, - $client_ip - )->unwrap(); - }); - - if ($ip_is_allowed or $ip_is_allowed_by_config or AdminSecure::ipIsPrivate($client_ip)) { - return $next($request); - } - - abort(403, \trans('Denied IP')); - } -} diff --git a/app/Lib/AdminSecure.php b/app/Lib/AdminSecure.php deleted file mode 100644 index 9a3de64..0000000 --- a/app/Lib/AdminSecure.php +++ /dev/null @@ -1,131 +0,0 @@ -server('HTTP_X_FORWARDED_FOR') ?? request()->getClientIp(); - $ip = IPAddress::Make($ip); - - if ($ip->isErr()) { - throw new \Exception(\trans('Client IP not valid ') . $ip->getErr()); - } - return $ip->unwrap(); - } - - /** - * Check if ipV4 is private - * - * @param \Dxw\CIDR\IPv4Address $ipv4_address - * @return boolean - */ - private static function ipV4IsPrivate(IPv4Address $ipv4_address): bool - { - return \collect(self::$private_ip_v4_cidr_list) - ->concat([self::$private_ip_v4_loopback_cidr]) - ->map(function (string $ipv4_cidr) { - return IPv4Range::Make($ipv4_cidr)->unwrap(); - }) - ->reduce(function ($initial, IPv4Range $ipv4_range) use ($ipv4_address) { - return $initial || $ipv4_range->containsAddress($ipv4_address); - }); - } - - /** - * Check if ipV6 is private - * - * @param \Dxw\CIDR\IPv6Address $ipv6_address - * @return boolean - */ - private static function ipV6IsPrivate(IPv6Address $ipv6_address): bool - { - return \collect(self::$private_ip_v6_cidr_list) - ->concat([self::$private_ip_v6_loopback_cidr]) - ->map(function (string $ipv6_cidr) { - return IPv6Range::Make($ipv6_cidr)->unwrap(); - }) - ->reduce(function ($initial, IPv6Range $ipv6_range) use ($ipv6_address) { - return $initial || $ipv6_range->containsAddress($ipv6_address); - }); - } - - /** - * Get Admin secure options - * - * @return \App\Lib\Options - */ - public static function getOptions(): Options - { - if (!self::$options) { - self::$options = new Options(\config('admin-secure')); - } - return self::$options; - } -} diff --git a/app/Lib/Options.php b/app/Lib/Options.php deleted file mode 100644 index b627087..0000000 --- a/app/Lib/Options.php +++ /dev/null @@ -1,159 +0,0 @@ - The configuration options - */ - private $options; - - /** - * @var \Symfony\Component\OptionsResolver\OptionsResolver The options resolver - */ - private $resolver; - - /** - * The cache key where to store config cidr list. - * - * @var string - */ - private static $cache_config_key = 'uwil_ip_cidr_config_list'; - - /** - * Class constructor. - * - * @param array $options The configuration options. - */ - public function __construct(array $options = []) - { - $this->resolver = new OptionsResolver(); - - $this->configureOptions($this->resolver); - - $this->options = $this->resolver->resolve($options); - } - - /** - * Get cidr list - * - * @return array<\Dxw\CIDR\IPv4Range|\Dxw\CIDR\IPv6Range> - */ - public function getCidrList(): array - { - return $this->options['cidrList']; - } - - /** - * Get cidr project allowed list - * - * @return array<\Dxw\CIDR\IPv4Range|\Dxw\CIDR\IPv6Range> - */ - public function getCidrAllowedList(): array - { - return $this->options['cidrProjectAllowedList']; - } - - /** - * Configures the options of the client. - * - * @param \Symfony\Component\OptionsResolver\OptionsResolver $resolver The resolver for the options. - * @return void - */ - private function configureOptions(OptionsResolver $resolver): void - { - $resolver->setDefaults([ - 'cidrList' => [], - 'cidrProjectAllowedList' => [] - ]); - - $resolver->setNormalizer('cidrList', \Closure::fromCallable([$this, 'normalizeCidrList'])); - $resolver->setNormalizer('cidrProjectAllowedList', \Closure::fromCallable([$this, 'normalizeCidrProjectList'])); - } - - /** - * Normalise Cidr list for cidrList option - * - * @param \Symfony\Component\OptionsResolver\Options $options - * @param string|null $value - * @return array - * @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed - */ - private function normalizeCidrList( - \Symfony\Component\OptionsResolver\Options $options, - ?string $value - ): array { - // phpcs:enable - return $this->doNormalizeCidrList($value, 'cidrList'); - } - - /** - * Normalise Cidr list for cidrProjectAllowedList option - * - * @param \Symfony\Component\OptionsResolver\Options $options - * @param string|null $value - * @return array - * @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed - */ - private function normalizeCidrProjectList( - \Symfony\Component\OptionsResolver\Options $options, - ?string $value - ): array { - // phpcs:enable - return $this->doNormalizeCidrList($value, 'cidrProjectAllowedList'); - } - - /** - * Normalize CIDR list with specific cache key. - * - * @param string|null $value - * @param string $optionName - * @return array<\Dxw\CIDR\IPv4Range|\Dxw\CIDR\IPv6Range> - */ - private function doNormalizeCidrList(?string $value, string $optionName): array - { - $cacheConfigKey = self::$cache_config_key . '_' . $optionName; - $allowed_cidr_config_list = collect(explode(',', strval($value)))->filter(); - $allowed_cidr_config_list_hash = \md5($allowed_cidr_config_list->implode(',')); - $allowed_cidr_list = []; - - // Flush cache if config hash changed - if ($allowed_cidr_config_list_hash !== \collect(Cache::get($cacheConfigKey))->get('hash')) { - Cache::forget($cacheConfigKey); - - /** @var array<\Dxw\CIDR\IPv4Range|\Dxw\CIDR\IPv6Range> $allowed_cidr_list */ - $allowed_cidr_list = $allowed_cidr_config_list - ->map(function (string $cidr) { - $ip_range = !IPv4Range::Make($cidr)->isErr() ? IPv4Range::Make($cidr) : IPv6Range::Make($cidr); - if ($ip_range->isErr()) { - throw new \Exception(\trans( - 'CIDR LIST not valid (ipv4 or ipv6 cidr) :cidr', - [ - 'cidr' => $cidr - ] - )); - } - return $ip_range->unwrap(); - })->all(); - } - - /** @var array<\Dxw\CIDR\IPv4Range|\Dxw\CIDR\IPv6Range> $allowed_cidr_list */ - return \collect(Cache::rememberForever($cacheConfigKey, function() use ($allowed_cidr_list, $allowed_cidr_config_list_hash) { - return [ - 'list' => $allowed_cidr_list, - 'hash' => $allowed_cidr_config_list_hash - ]; - }))->get('list'); - } -} diff --git a/composer.json b/composer.json index d89ab95..2eac2f9 100644 --- a/composer.json +++ b/composer.json @@ -18,6 +18,7 @@ "propaganistas/laravel-phone": "^6.0", "scaler-tech/laravel-saml2": "^2.7", "sentry/sentry-laravel": "*", + "uwil/admin-secure-laravel": "^5.1", "uwil/k8s-laravel": "*", "uwil/sitemap-generator": "^7.0" }, diff --git a/composer.lock b/composer.lock index 00f5b71..6a7eb8e 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "5bb9c0c92c6cc9e3d97d2b24f7649b30", + "content-hash": "d7d9dedbe54aec6e39746313cae1d017", "packages": [ { "name": "axlon/laravel-postal-code-validation", @@ -6320,20 +6320,20 @@ }, { "name": "symfony/options-resolver", - "version": "v8.0.8", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "b48bce0a70b914f6953dafbd10474df232ed4de8" + "reference": "2888fcdc4dc2fd5f7c7397be78631e8af12e02b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/b48bce0a70b914f6953dafbd10474df232ed4de8", - "reference": "b48bce0a70b914f6953dafbd10474df232ed4de8", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/2888fcdc4dc2fd5f7c7397be78631e8af12e02b4", + "reference": "2888fcdc4dc2fd5f7c7397be78631e8af12e02b4", "shasum": "" }, "require": { - "php": ">=8.4", + "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3" }, "type": "library", @@ -6367,7 +6367,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v8.0.8" + "source": "https://github.com/symfony/options-resolver/tree/v7.4.8" }, "funding": [ { @@ -6387,7 +6387,7 @@ "type": "tidelift" } ], - "time": "2026-03-30T15:14:47+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/polyfill-ctype", @@ -7942,6 +7942,70 @@ }, "time": "2025-12-02T11:56:42+00:00" }, + { + "name": "uwil/admin-secure-laravel", + "version": "5.1.0", + "source": { + "type": "git", + "url": "git@lab.s-web.fr:ldc-web/projets/ldc-web-admin-secure-laravel.git", + "reference": "0299d8397111b5a80ea3200a9fd387b94c34f208" + }, + "dist": { + "type": "zip", + "url": "https://lab.s-web.fr/api/v4/projects/20/packages/composer/archives/uwil/admin-secure-laravel.zip?sha=0299d8397111b5a80ea3200a9fd387b94c34f208", + "reference": "0299d8397111b5a80ea3200a9fd387b94c34f208", + "shasum": "" + }, + "require": { + "dxw/cidr": "^3.2", + "illuminate/support": "~11|~12|~13", + "laravel/framework": "~11|~12|~13", + "php": "^8.3", + "symfony/options-resolver": "^7.0" + }, + "require-dev": { + "larastan/larastan": "^2.9", + "orchestra/testbench": "^9", + "phpunit/php-code-coverage": "^11", + "phpunit/phpunit": "^11", + "slevomat/coding-standard": "^8", + "squizlabs/php_codesniffer": "^3" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Uwil\\AdminSecure\\Laravel\\AdminSecureServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Uwil\\AdminSecure\\Laravel\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "Uwil\\AdminSecure\\Laravel\\Tests\\": "tests" + } + }, + "scripts": { + "test": [ + "vendor/bin/phpunit" + ], + "post-autoload-dump": [ + "@php ./vendor/bin/testbench package:discover --ansi" + ] + }, + "license": [ + "MIT" + ], + "description": "Restrict access to LDC Network", + "support": { + "email": "digital@ldc.fr", + "issues": "https://lab.s-web.fr/ldc-web/projets/ldc-web-admin-secure-laravel/-/issues" + } + }, { "name": "uwil/k8s-laravel", "version": "3.0.0", diff --git a/phpcs.xml b/phpcs.xml index 8edd8ef..2c09cd5 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -30,8 +30,6 @@ - - @@ -45,9 +43,6 @@ - - - @@ -80,7 +75,6 @@ -