Compare commits
30 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d0c4dbc6f0 | ||
|
|
6f687a8cd4 | ||
|
|
71453c6a8c | ||
|
|
cb88b7ddb5 | ||
|
|
c67e0b476f | ||
|
|
cd6bb56bb6 | ||
|
|
ddb4c688dc | ||
|
|
c2eb783716 | ||
|
|
92dbff8b1c | ||
|
|
1a4f23106f | ||
|
|
facbea062e | ||
|
|
267cec076b | ||
|
|
594f03f834 | ||
|
|
c54dad85ee | ||
|
|
0299d83971 | ||
|
|
6bed78da14 | ||
|
|
f376e1dd4b | ||
|
|
a4e0fafa16 | ||
|
|
26f818b6b9 | ||
|
|
4afdddde91 | ||
|
|
e5056174bc | ||
|
|
61efdb6099 | ||
|
|
5cf7ba3b45 | ||
|
|
572d90b1c5 | ||
|
|
f142732754 | ||
|
|
625685de1a | ||
|
|
b05ed93c2b | ||
|
|
5f0c6b136f | ||
|
|
c538f5d349 | ||
|
|
0b398200c8 |
28 changed files with 12121 additions and 536 deletions
|
|
@ -3,16 +3,22 @@ root = true
|
||||||
[*]
|
[*]
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
end_of_line = lf
|
end_of_line = lf
|
||||||
insert_final_newline = true
|
indent_size = 4
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 4
|
insert_final_newline = true
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
[*.json]
|
|
||||||
indent_size = 4
|
|
||||||
|
|
||||||
[*.md]
|
[*.md]
|
||||||
trim_trailing_whitespace = false
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
[*.{yml,yaml}]
|
[*.{yml,yaml}]
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|
||||||
|
[docker-compose.yml]
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[*.scss]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.{tsx,ts,cjs}]
|
||||||
|
indent_size = 2
|
||||||
|
|
|
||||||
11
.gitignore
vendored
11
.gitignore
vendored
|
|
@ -1,7 +1,4 @@
|
||||||
workspace.code-workspace
|
vendor/
|
||||||
vendor
|
node_modules/
|
||||||
.phpunit.result.cache
|
/auth.json
|
||||||
.phpunit.cache
|
/.npmrc
|
||||||
.vscode/launch.json
|
|
||||||
composer.lock
|
|
||||||
build
|
|
||||||
11
.gitlab/issue_templates/bug.md
Normal file
11
.gitlab/issue_templates/bug.md
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
## Comportement constaté
|
||||||
|
|
||||||
|
|
||||||
|
## Comportement attendu
|
||||||
|
|
||||||
|
|
||||||
|
## Solution envisagée
|
||||||
|
|
||||||
|
|
||||||
|
## Étapes pour la reproduction du bug
|
||||||
|
*
|
||||||
7
.gitlab/issue_templates/feature.md
Normal file
7
.gitlab/issue_templates/feature.md
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
## Présentation du besoin
|
||||||
|
|
||||||
|
|
||||||
|
## Implémentation
|
||||||
|
|
||||||
|
|
||||||
|
## Maquettes, documentations...
|
||||||
3
.husky/commit-msg
Normal file
3
.husky/commit-msg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
npx --no -- commitlint --config node_modules/@uwil/husky-config/commitlint.config.cjs --edit $1
|
||||||
27
.vscode/settings.json
vendored
27
.vscode/settings.json
vendored
|
|
@ -1,3 +1,26 @@
|
||||||
{
|
{
|
||||||
"phpcs.executablePath": "vendor/bin/phpcs"
|
"workbench.colorCustomizations": {
|
||||||
}
|
"activityBar.activeBackground": "#00d6d6",
|
||||||
|
"activityBar.activeBorder": "#1a1d02",
|
||||||
|
"activityBar.background": "#00d6d6",
|
||||||
|
"activityBar.foreground": "#15202b",
|
||||||
|
"activityBar.inactiveForeground": "#15202b99",
|
||||||
|
"activityBarBadge.background": "#df00df",
|
||||||
|
"activityBarBadge.foreground": "#e7e7e7",
|
||||||
|
"sash.hoverBorder": "#00d6d6",
|
||||||
|
"statusBar.background": "#00a3a3",
|
||||||
|
"statusBar.foreground": "#e7e7e7",
|
||||||
|
"statusBarItem.hoverBackground": "#00d6d6",
|
||||||
|
"statusBarItem.remoteBackground": "#00a3a3",
|
||||||
|
"statusBarItem.remoteForeground": "#e7e7e7",
|
||||||
|
"titleBar.activeBackground": "#00a3a3",
|
||||||
|
"titleBar.activeForeground": "#e7e7e7",
|
||||||
|
"titleBar.inactiveBackground": "#00a3a399",
|
||||||
|
"titleBar.inactiveForeground": "#e7e7e799",
|
||||||
|
"commandCenter.border": "#e7e7e799"
|
||||||
|
},
|
||||||
|
"peacock.remoteColor": "#00a3a3",
|
||||||
|
"intelephense.environment.phpVersion": "8.3.0",
|
||||||
|
"intelephense.completion.fullyQualifyGlobalConstantsAndFunctions": true,
|
||||||
|
"intelephense.phpdoc.useFullyQualifiedNames": true
|
||||||
|
}
|
||||||
101
CHANGELOG.md
Normal file
101
CHANGELOG.md
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to `laravel-admin-secure` will be documented in this file.
|
||||||
|
|
||||||
|
- The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||||
|
- This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html),
|
||||||
|
- Commits respect [Conventionnal commits](https://www.conventionalcommits.org/en/v1.0.0/) & use [Gitmoji](https://gitmoji.dev/).
|
||||||
|
|
||||||
|
## **[v6.0.1] - 05/10/2026**
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- chore: ⬆️ bump dependencies
|
||||||
|
|
||||||
|
## **[v6.0.0] - 22/06/2026**
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- feat: ✨ add commit lint from husky configuration
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- chore: 🔧 update linters configuration
|
||||||
|
- chore: 🔧 rename package into laravel-admin-secure
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- perf: 🚨 resolve linters errors
|
||||||
|
|
||||||
|
## **[v5.1.0] - 17/04/2026**
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- chore: :arrow_up: Added Laravel 13 compatibility
|
||||||
|
|
||||||
|
## **[v5.0.0] - 09/01/2026**
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- feat: ✨ Remove LDC Web API dependency
|
||||||
|
|
||||||
|
## **[v4.0.0] - 07/04/2025**
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- feat: ✨ add Laravel 12 compatibility
|
||||||
|
|
||||||
|
## **[v3.0.0] - 03/09/2024**
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Add Laravel 11 compatibility
|
||||||
|
- Bump deps for Laravel 11
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Change namespace for UWIL complience
|
||||||
|
|
||||||
|
## **[v2.0.3] - 04/04/2024**
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Add staging to environnements where sync command should be executed
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- PHPCS and PHPSTAN fixes
|
||||||
|
|
||||||
|
## **[v2.0.2] - 19/09/2024**
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- fixed artisan command to fetch list
|
||||||
|
|
||||||
|
## **[v2.0.1] - 19/09/2023**
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Delete API key
|
||||||
|
- Artisan config cache fix
|
||||||
|
- Cache was ignored
|
||||||
|
|
||||||
|
## **[v2.0.0] - 05/06/2023**
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Bump laravel 10
|
||||||
|
- Add manual Cird possibility
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Allows connections from private ip ranges
|
||||||
|
- Add posibility to config manual CIDR exceptions
|
||||||
|
|
||||||
|
## **[v1.0.1] - 04/07/2022**
|
||||||
|
|
||||||
|
- Run scheduled only on production envirronement
|
||||||
|
|
||||||
|
## **[v1.0.0] - 24/06/2022**
|
||||||
|
|
||||||
|
- Initial release
|
||||||
7
MIGRATION.md
Normal file
7
MIGRATION.md
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
# Migration
|
||||||
|
|
||||||
|
All notable changes to `laravel-admin-secure` will be documented in this file.
|
||||||
|
|
||||||
|
## v5.1.1 -> v6.0.0
|
||||||
|
- renommage du package de `ldc-web-admin-secure-laravel` en `laravel-admin-secure`,
|
||||||
|
- changement du namespace pour le middleware de `Uwil\AdminSecure\Laravel\Http\Middleware` à `Uwil\LaravelAdminSecure\Middlewares`.
|
||||||
80
README.md
80
README.md
|
|
@ -1,35 +1,59 @@
|
||||||
# LDC Web Admin Secure Laravel
|
# UWIL Laravel Admin Secure
|
||||||
|
|
||||||
## Install on Laravel
|
UWIL Laravel Admin Secure est un package à installer afin de protéger nos interfaces d'administration à une liste d'IPs spécifiques.
|
||||||
```
|
|
||||||
composer req ldc/web-admin-secure-laravel
|
|
||||||
```
|
|
||||||
.env.example :
|
|
||||||
|
|
||||||
```dotenv
|
## Table des matières
|
||||||
# ADMIN SECURE
|
|
||||||
# - API ENDPOINT (Optional)
|
- [UWIL Laravel Admin Secure](#uwil-laravel-admin-secure)
|
||||||
LDC_WEB_API_ENDPOINT="https://ldc-web.ldc.fr/api/ldc-networks"
|
- [Table des matières](#table-des-matières)
|
||||||
# - API KEY
|
- [Compatibilité](#Compatibilité)
|
||||||
LDC_WEB_API_KEY=""
|
- [Documentation](#documentation)
|
||||||
|
- [Installation](#installation)
|
||||||
|
- [Détails](#détails)
|
||||||
|
- [Changelog](#changelog)
|
||||||
|
- [Copyright et licence](#copyright-et-licence)
|
||||||
|
|
||||||
|
## Compatibilité
|
||||||
|
|
||||||
|
| Version | [1.0.0](https://lab.s-web.fr/ldc-web/projets/laravel-admin-secure/-/tree/1.0.0?ref_type=tags) -> [1.0.1](https://lab.s-web.fr/ldc-web/projets/laravel-admin-secure/-/tree/1.0.1?ref_type=tags) | [2.0.0](https://lab.s-web.fr/ldc-web/projets/laravel-admin-secure/-/tree/2.0.0?ref_type=tags) -> [2.0.3](https://lab.s-web.fr/ldc-web/projets/laravel-admin-secure/-/tree/2.0.3?ref_type=tags) | [3.0.0](https://lab.s-web.fr/ldc-web/projets/laravel-admin-secure/-/tree/3.0.0?ref_type=tags) | [4.0.0](https://lab.s-web.fr/ldc-web/projets/laravel-admin-secure/-/tree/4.0.0?ref_type=tags) -> [5.0.0](https://lab.s-web.fr/ldc-web/projets/laravel-admin-secure/-/tree/5.0.0?ref_type=tags) | [5.1.0](https://lab.s-web.fr/ldc-web/projets/laravel-admin-secure/-/tree/5.1.0?ref_type=tags) -> [6.0.1](https://lab.s-web.fr/ldc-web/projets/laravel-admin-secure/-/tree/6.0.1?ref_type=tags) |
|
||||||
|
|:-------------------------------------------------------------------------|:--:|:--:|:--:|:--:|:--:|
|
||||||
|
| [laravel\framework^13.0](https://github.com/laravel/framework/tree/13.x) | ❌ | ❌ | ❌ | ❌ | ✅ |
|
||||||
|
| [laravel\framework^12.0](https://github.com/laravel/framework/tree/12.x) | ❌ | ❌ | ❌ | ✅ | ✅ |
|
||||||
|
| [laravel\framework^11.0](https://github.com/laravel/framework/tree/11.x) | ❌ | ❌ | ✅ | ✅ | ✅ |
|
||||||
|
| [laravel\framework^10.0](https://github.com/laravel/framework/tree/10.x) | ❌ | ✅ | ❌ | ❌ | ❌ |
|
||||||
|
| [laravel\framework^9.0](https://github.com/laravel/framework/tree/10.x) | ✅ | ❌ | ❌ | ❌ | ❌ |
|
||||||
|
| [laravel\framework^8.0](https://github.com/laravel/framework/tree/10.x) | ✅ | ❌ | ❌ | ❌ | ❌ |
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
1. Installer ce package composer comme ceci:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
composer req uwil/laravel-admin-secure
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Ajouter simplement l'alias du middleware `admin-secure` sur les routes que vous voulez protéger,
|
||||||
|
|
||||||
|
2. Enfin, renseigner la liste des IPs dans votre `.env`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# UWIL ADMIN SECURE
|
||||||
|
# - LIST SEPARATED WITH ',' (Required)
|
||||||
|
UWIL_ADMIN_SECURE_CIDR_LIST=""
|
||||||
# - LIST SEPARATED WITH ',' (Optional)
|
# - LIST SEPARATED WITH ',' (Optional)
|
||||||
LDC_WEB_CIDR_MANUAL_ALLOWED_LIST=""
|
UWIL_ADMIN_SECURE_CIDR_PROJECT_ALLOWED_LIST=""
|
||||||
```
|
```
|
||||||
|
|
||||||
README.md :
|
## Changelog
|
||||||
```
|
|
||||||
Put every min in PROD :
|
|
||||||
php artisan schedule:run
|
|
||||||
```
|
|
||||||
|
|
||||||
## Available Commands
|
Dernière version v6.0.1.
|
||||||
```
|
|
||||||
ldcweb:admin-secure-sync
|
|
||||||
```
|
|
||||||
## Usage
|
|
||||||
Put 'admin-secure' middleware on route to protect it.
|
|
||||||
## Cron configure
|
|
||||||
|
|
||||||
Nothing to do command is already configureed to run everyday.
|
Voir le journal de modifications [CHANGELOG.md](CHANGELOG.md) pour les détails.
|
||||||
You just need to install this package.
|
|
||||||
**!! Runs only in production !!**
|
## Copyright et licence
|
||||||
|
|
||||||
|
Laravel Admin Secure est écrit et maintenu par UWIL.
|
||||||
|
|
||||||
|
Copyright (c) 2022 et au-delà UWIL.
|
||||||
|
|
|
||||||
31
changelog.md
31
changelog.md
|
|
@ -1,31 +0,0 @@
|
||||||
# Changelog
|
|
||||||
|
|
||||||
## **Version 2.0.2**
|
|
||||||
|
|
||||||
### *2.0.2 Fixed*
|
|
||||||
|
|
||||||
- fixed artisan command to fetch list
|
|
||||||
|
|
||||||
## **Version 2.0.1**
|
|
||||||
|
|
||||||
### *2.0.1 Fixed*
|
|
||||||
|
|
||||||
- artisan config cache fix
|
|
||||||
- Cache was ignored
|
|
||||||
|
|
||||||
## **Version 2.0.0**
|
|
||||||
|
|
||||||
### *2.0.0 Changed*
|
|
||||||
|
|
||||||
- Bump laravel 10
|
|
||||||
- Add manual Cird possibility
|
|
||||||
|
|
||||||
## **Version 1.0.1**
|
|
||||||
|
|
||||||
### *1.0.1 Changed*
|
|
||||||
|
|
||||||
- Run scheduled only on production envirronement
|
|
||||||
|
|
||||||
## **Version 1.0.0**
|
|
||||||
|
|
||||||
### Initial release
|
|
||||||
1
commitlint.config.cjs
Normal file
1
commitlint.config.cjs
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
module.exports = require('@uwil/husky-config/commitlint.config.cjs');
|
||||||
|
|
@ -1,50 +1,64 @@
|
||||||
{
|
{
|
||||||
"name": "ldc/web-admin-secure-laravel",
|
"name": "uwil/laravel-admin-secure",
|
||||||
"description": "Restrict access to LDC Network",
|
"description": "Restrict access to LDC Network",
|
||||||
|
"type": "library",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"authors": [
|
"version": "6.0.1",
|
||||||
{
|
"keywords": [
|
||||||
"name": "Vincent BRIDIER",
|
"uwil",
|
||||||
"email": "vincent.bridier@ldc.fr",
|
"laravel",
|
||||||
"homepage": "https://www.ldc.fr"
|
"security"
|
||||||
}
|
|
||||||
],
|
],
|
||||||
|
"readme": "https://lab.s-web.fr/ldc-web/projets/laravel-admin-secure/-/blob/main/README.md",
|
||||||
|
"support": {
|
||||||
|
"email": "digital@ldc.fr",
|
||||||
|
"issues": "https://lab.s-web.fr/ldc-web/projets/laravel-admin-secure/-/issues"
|
||||||
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=8.2",
|
"php": "^8.3",
|
||||||
"illuminate/support": "~10",
|
"illuminate/support": "~11|~12|~13",
|
||||||
"laravel/framework": "~10",
|
"laravel/framework": "~11|~12|~13",
|
||||||
"symfony/options-resolver": "^3.4.43|^4.4.30|^5.0.11|^6.0",
|
"symfony/options-resolver": "^7.0|^8.0",
|
||||||
"dxw/cidr": "^3.1"
|
"dxw/cidr": "^4.0.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^9",
|
"driftingly/rector-laravel": "^2.3",
|
||||||
"squizlabs/php_codesniffer": "^3",
|
"larastan/larastan": "^3.9",
|
||||||
"orchestra/testbench": "^8",
|
"laravel/pint": "^1.29",
|
||||||
"slevomat/coding-standard": "^7",
|
"orchestra/testbench": "^11.1",
|
||||||
"phpunit/php-code-coverage": "^9"
|
"slevomat/coding-standard": "^8.3",
|
||||||
},
|
"squizlabs/php_codesniffer": "^3.7"
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"LDC\\WebAdminSecureLaravel\\": "src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload-dev": {
|
|
||||||
"psr-4": {
|
|
||||||
"LDC\\WebAdminSecureLaravel\\Tests\\": "tests"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"extra": {
|
|
||||||
"laravel": {
|
|
||||||
"providers": [
|
|
||||||
"LDC\\WebAdminSecureLaravel\\AdminSecureServiceProvider"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"post-autoload-dump": [
|
"post-autoload-dump": [
|
||||||
"@php ./vendor/bin/testbench package:discover --ansi"
|
"@php ./vendor/bin/testbench package:discover --ansi"
|
||||||
],
|
],
|
||||||
"test": "vendor/bin/phpunit"
|
"phpcs": [
|
||||||
|
"./vendor/bin/phpcs"
|
||||||
|
],
|
||||||
|
"phpstan": [
|
||||||
|
"./vendor/bin/phpstan"
|
||||||
|
],
|
||||||
|
"rector": [
|
||||||
|
"./vendor/bin/rector"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Uwil\\LaravelAdminSecure\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload-dev": {
|
||||||
|
"psr-4": {
|
||||||
|
"Uwil\\LaravelAdminSecure\\Tests\\": "tests"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"providers": [
|
||||||
|
"Uwil\\LaravelAdminSecure\\AdminSecureServiceProvider"
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"allow-plugins": {
|
"allow-plugins": {
|
||||||
|
|
|
||||||
10198
composer.lock
generated
Normal file
10198
composer.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,7 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'endpoint' => env('LDC_WEB_API_ENDPOINT', 'https://ldc-web.ldc.fr/api/ldc-networks'),
|
'cidrList' => env('UWIL_ADMIN_SECURE_CIDR_LIST'),
|
||||||
'apiKey' => env('LDC_WEB_API_KEY'),
|
'cidrProjectAllowedList' => env('UWIL_ADMIN_SECURE_CIDR_PROJECT_ALLOWED_LIST'),
|
||||||
'cidrManualAllowedList' => env('LDC_WEB_CIDR_MANUAL_ALLOWED_LIST')
|
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2022 LDC Service Web
|
Copyright (c) 2022 LDC Digital
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
||||||
1324
package-lock.json
generated
Normal file
1324
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
8
package.json
Normal file
8
package.json
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"name": "laravel-admin-secure",
|
||||||
|
"version": "6.0.1",
|
||||||
|
"description": "UWIL K8S utils",
|
||||||
|
"dependencies": {
|
||||||
|
"@uwil/husky-config": "^1.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
144
phpcs.xml
144
phpcs.xml
|
|
@ -1,122 +1,62 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<ruleset name="RealWorld" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="vendor/squizlabs/php_codesniffer/phpcs.xsd">
|
<ruleset name="Php Coding Standard"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="vendor/squizlabs/php_codesniffer/phpcs.xsd">
|
||||||
|
|
||||||
|
<description>Optimized standard: Static analysis complementary to Pint.</description>
|
||||||
|
|
||||||
<arg name="colors" />
|
<arg name="colors" />
|
||||||
<arg name="extensions" value="php" />
|
<arg name="extensions" value="php" />
|
||||||
|
<arg name="parallel" value="75" />
|
||||||
<file>src/</file>
|
<file>src/</file>
|
||||||
<rule ref="PSR1" />
|
<file>config/</file>
|
||||||
<rule ref="PSR12" />
|
|
||||||
|
<exclude-pattern>*/vendor/*</exclude-pattern>
|
||||||
|
<exclude-pattern>*/storage/*</exclude-pattern>
|
||||||
|
<exclude-pattern>*/packages/*</exclude-pattern>
|
||||||
|
<exclude-pattern type="relative">*.blade.php</exclude-pattern>
|
||||||
|
|
||||||
|
<rule ref="PSR12"/>
|
||||||
|
|
||||||
<rule ref="Generic.Classes.DuplicateClassName"/>
|
|
||||||
<rule ref="Generic.CodeAnalysis.EmptyStatement"/>
|
<rule ref="Generic.CodeAnalysis.EmptyStatement"/>
|
||||||
<rule ref="Generic.CodeAnalysis.ForLoopShouldBeWhileLoop"/>
|
|
||||||
<rule ref="Generic.CodeAnalysis.ForLoopWithTestFunctionCall"/>
|
|
||||||
<rule ref="Generic.CodeAnalysis.JumbledIncrementer"/>
|
|
||||||
<rule ref="Generic.CodeAnalysis.UnconditionalIfStatement"/>
|
<rule ref="Generic.CodeAnalysis.UnconditionalIfStatement"/>
|
||||||
<rule ref="Generic.CodeAnalysis.UnnecessaryFinalModifier"/>
|
|
||||||
<rule ref="Generic.CodeAnalysis.UnusedFunctionParameter"/>
|
|
||||||
<rule ref="Generic.CodeAnalysis.UselessOverridingMethod"/>
|
<rule ref="Generic.CodeAnalysis.UselessOverridingMethod"/>
|
||||||
<rule ref="Generic.Commenting.DocComment.SpacingBeforeTags"/>
|
<rule ref="Generic.Metrics.CyclomaticComplexity">
|
||||||
<rule ref="Generic.Commenting.Todo"/>
|
<properties>
|
||||||
<rule ref="Generic.Commenting.Fixme"/>
|
<property name="complexity" value="10"/>
|
||||||
<rule ref="Generic.ControlStructures.InlineControlStructure"/>
|
<property name="absoluteComplexity" value="20"/>
|
||||||
<rule ref="Generic.Files.ByteOrderMark"/>
|
</properties>
|
||||||
<rule ref="Generic.Files.LineEndings"/>
|
</rule>
|
||||||
<rule ref="Generic.Files.LineLength"/>
|
|
||||||
<rule ref="Generic.Formatting.DisallowMultipleStatements"/>
|
|
||||||
<rule ref="Generic.Formatting.MultipleStatementAlignment"/>
|
|
||||||
<rule ref="Generic.Formatting.NoSpaceAfterCast"/>
|
|
||||||
<rule ref="Generic.Functions.CallTimePassByReference"/>
|
|
||||||
<rule ref="Generic.Functions.FunctionCallArgumentSpacing"/>
|
|
||||||
<rule ref="Generic.Metrics.CyclomaticComplexity"/>
|
|
||||||
<rule ref="Generic.Metrics.NestingLevel"/>
|
<rule ref="Generic.Metrics.NestingLevel"/>
|
||||||
<rule ref="Generic.NamingConventions.ConstructorName"/>
|
|
||||||
<rule ref="Generic.NamingConventions.UpperCaseConstantName"/>
|
|
||||||
<rule ref="Generic.NamingConventions.CamelCapsFunctionName"/>
|
|
||||||
<rule ref="Generic.PHP.DeprecatedFunctions"/>
|
<rule ref="Generic.PHP.DeprecatedFunctions"/>
|
||||||
<rule ref="Generic.PHP.DisallowShortOpenTag"/>
|
|
||||||
<rule ref="Generic.PHP.ForbiddenFunctions"/>
|
<rule ref="Generic.PHP.ForbiddenFunctions"/>
|
||||||
<rule ref="Generic.PHP.NoSilencedErrors"/>
|
<rule ref="Generic.PHP.NoSilencedErrors"/>
|
||||||
<rule ref="Generic.Strings.UnnecessaryStringConcat"/>
|
|
||||||
<rule ref="Generic.WhiteSpace.DisallowTabIndent"/>
|
|
||||||
<rule ref="Generic.WhiteSpace.ScopeIndent"/>
|
|
||||||
<rule ref="MySource.PHP.EvalObjectFactory"/>
|
|
||||||
<rule ref="MySource.PHP.GetRequestData"/>
|
|
||||||
<rule ref="MySource.PHP.AjaxNullComparison"/>
|
|
||||||
<rule ref="PEAR.Classes.ClassDeclaration"/>
|
|
||||||
<rule ref="PEAR.Commenting.InlineComment"/>
|
|
||||||
<rule ref="PSR1.Classes.ClassDeclaration"/>
|
|
||||||
<rule ref="PSR1.Files.SideEffects"/>
|
|
||||||
<rule ref="PSR2.Classes.ClassDeclaration"/>
|
|
||||||
<rule ref="PSR2.Classes.PropertyDeclaration"/>
|
|
||||||
<rule ref="PSR2.ControlStructures.ElseIfDeclaration"/>
|
|
||||||
<rule ref="PSR2.ControlStructures.SwitchDeclaration"/>
|
|
||||||
<rule ref="PSR2.Files.EndFileNewline"/>
|
|
||||||
<rule ref="PSR2.Methods.MethodDeclaration"/>
|
|
||||||
<rule ref="PSR2.Namespaces.NamespaceDeclaration"/>
|
|
||||||
<rule ref="PSR2.Namespaces.UseDeclaration"/>
|
|
||||||
<rule ref="Squiz.PHP.CommentedOutCode"/>
|
|
||||||
<rule ref="Squiz.PHP.DisallowMultipleAssignments">
|
|
||||||
<exclude name="Squiz.PHP.DisallowMultipleAssignments.FoundInControlStructure" />
|
|
||||||
</rule>
|
|
||||||
<rule ref="Squiz.PHP.DisallowSizeFunctionsInLoops"/>
|
|
||||||
|
|
||||||
<rule ref="Squiz.PHP.DiscouragedFunctions">
|
|
||||||
<properties>
|
|
||||||
<property name="error" value="true"/>
|
|
||||||
</properties>
|
|
||||||
</rule>
|
|
||||||
<rule ref="Squiz.PHP.Eval"/>
|
<rule ref="Squiz.PHP.Eval"/>
|
||||||
<rule ref="Squiz.PHP.GlobalKeyword"/>
|
<rule ref="Squiz.PHP.GlobalKeyword"/>
|
||||||
<rule ref="Squiz.PHP.Heredoc"/>
|
|
||||||
<rule ref="Squiz.PHP.InnerFunctions"/>
|
|
||||||
<rule ref="Squiz.PHP.LowercasePHPFunctions"/>
|
|
||||||
<rule ref="Squiz.PHP.NonExecutableCode"/>
|
<rule ref="Squiz.PHP.NonExecutableCode"/>
|
||||||
<rule ref="Squiz.Scope.MemberVarScope"/>
|
|
||||||
<rule ref="Squiz.Scope.MethodScope"/>
|
|
||||||
<rule ref="Squiz.Scope.StaticThisUsage"/>
|
<rule ref="Squiz.Scope.StaticThisUsage"/>
|
||||||
<rule ref="Squiz.WhiteSpace.LanguageConstructSpacing"/>
|
|
||||||
<rule ref="Squiz.WhiteSpace.LogicalOperatorSpacing"/>
|
|
||||||
<rule ref="Squiz.WhiteSpace.MemberVarSpacing">
|
|
||||||
<properties>
|
|
||||||
<property name="spacingBeforeFirst " value="false"/>
|
|
||||||
</properties>
|
|
||||||
</rule>
|
|
||||||
<rule ref="Squiz.WhiteSpace.OperatorSpacing">
|
|
||||||
<properties>
|
|
||||||
<property name="ignoreNewlines" value="true"/>
|
|
||||||
</properties>
|
|
||||||
</rule>
|
|
||||||
<rule ref="Squiz.WhiteSpace.ObjectOperatorSpacing">
|
|
||||||
<properties>
|
|
||||||
<property name="ignoreNewlines" value="true"/>
|
|
||||||
</properties>
|
|
||||||
</rule>
|
|
||||||
<rule ref="Squiz.WhiteSpace.ScopeKeywordSpacing"/>
|
|
||||||
<rule ref="Squiz.WhiteSpace.SemicolonSpacing"/>
|
|
||||||
<rule ref="Squiz.Commenting.BlockComment">
|
|
||||||
<exclude name="Squiz.Commenting.BlockComment.WrongStart" />
|
|
||||||
</rule>
|
|
||||||
<rule ref="Squiz.Commenting.ClassComment">
|
|
||||||
<exclude name="Squiz.Commenting.ClassComment.Missing" />
|
|
||||||
<exclude name="Squiz.Commenting.ClassComment.TagNotAllowed" />
|
|
||||||
</rule>
|
|
||||||
<rule ref="Squiz.Commenting.DocCommentAlignment"/>
|
|
||||||
<rule ref="Squiz.Commenting.EmptyCatchComment"/>
|
|
||||||
<rule ref="Squiz.Commenting.FunctionComment">
|
|
||||||
<exclude name="Squiz.Commenting.FunctionComment.MissingParamComment" />
|
|
||||||
</rule>
|
|
||||||
<rule ref="Squiz.Commenting.FunctionCommentThrowTag"/>
|
|
||||||
<rule ref="Squiz.Commenting.InlineComment">
|
|
||||||
<exclude name="Squiz.Commenting.InlineComment.DocBlock" />
|
|
||||||
</rule>
|
|
||||||
<rule ref="Squiz.Commenting.LongConditionClosingComment">
|
|
||||||
<exclude name="Squiz.Commenting.LongConditionClosingComment.SpacingBefore" />
|
|
||||||
</rule>
|
|
||||||
<rule ref="Squiz.Commenting.PostStatementComment"/>
|
|
||||||
<rule ref="Squiz.Commenting.VariableComment"/>
|
|
||||||
<rule ref="SlevomatCodingStandard.Namespaces.UnusedUses.UnusedUse" />
|
|
||||||
|
|
||||||
<!-- For Laravel migrations -->
|
<rule ref="Generic.NamingConventions.ConstructorName"/>
|
||||||
|
<rule ref="Generic.NamingConventions.CamelCapsFunctionName"/>
|
||||||
|
|
||||||
|
<rule ref="Generic.Files.LineLength">
|
||||||
|
<properties>
|
||||||
|
<property name="lineLimit" value="150"/>
|
||||||
|
<property name="absoluteLineLimit" value="250"/>
|
||||||
|
</properties>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
<rule ref="SlevomatCodingStandard.Namespaces.UnusedUses" />
|
||||||
|
|
||||||
|
<rule ref="SlevomatCodingStandard.TypeHints.DeclareStrictTypes">
|
||||||
|
<properties>
|
||||||
|
<property name="spacesCountAroundEqualsSign" value="0" />
|
||||||
|
<property name="declareOnFirstLine" value="false" />
|
||||||
|
<property name="linesCountBeforeDeclare" value="1" />
|
||||||
|
<property name="linesCountAfterDeclare" value="1" />
|
||||||
|
</properties>
|
||||||
|
</rule>
|
||||||
|
|
||||||
<rule ref="PSR1.Classes.ClassDeclaration.MissingNamespace">
|
<rule ref="PSR1.Classes.ClassDeclaration.MissingNamespace">
|
||||||
<exclude-pattern>*/database/migrations/*</exclude-pattern>
|
<exclude-pattern>*/database/migrations/*</exclude-pattern>
|
||||||
</rule>
|
</rule>
|
||||||
|
|
|
||||||
14
phpstan.neon
Normal file
14
phpstan.neon
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
includes:
|
||||||
|
- vendor/larastan/larastan/extension.neon
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
paths:
|
||||||
|
- config/
|
||||||
|
- src/
|
||||||
|
|
||||||
|
level: 7
|
||||||
|
|
||||||
|
ignoreErrors:
|
||||||
|
-
|
||||||
|
message: '#Called .env. outside of the config directory#'
|
||||||
|
path: config/*
|
||||||
80
pint.json
Normal file
80
pint.json
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
{
|
||||||
|
"preset": "laravel",
|
||||||
|
"exclude": [
|
||||||
|
"packages"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"indentation_type": true,
|
||||||
|
"single_line_empty_body": false,
|
||||||
|
"types_spaces": {
|
||||||
|
"space": "single",
|
||||||
|
"space_multiple_catch": "single"
|
||||||
|
},
|
||||||
|
"control_structure_braces": true,
|
||||||
|
"new_with_parentheses": {
|
||||||
|
"anonymous_class": true,
|
||||||
|
"named_class": true
|
||||||
|
},
|
||||||
|
"class_definition": {
|
||||||
|
"single_item_single_line": false,
|
||||||
|
"single_line": false,
|
||||||
|
"space_before_parenthesis": true
|
||||||
|
},
|
||||||
|
"curly_braces_position": {
|
||||||
|
"allow_single_line_empty_anonymous_classes": false,
|
||||||
|
"classes_opening_brace": "next_line_unless_newline_at_signature_end",
|
||||||
|
"anonymous_classes_opening_brace": "next_line_unless_newline_at_signature_end",
|
||||||
|
"control_structures_opening_brace": "same_line",
|
||||||
|
"functions_opening_brace": "next_line_unless_newline_at_signature_end",
|
||||||
|
"anonymous_functions_opening_brace": "same_line"
|
||||||
|
},
|
||||||
|
"binary_operator_spaces": {
|
||||||
|
"default": "align_single_space_minimal",
|
||||||
|
"operators": {
|
||||||
|
"=": "align_single_space",
|
||||||
|
"|": "single_space",
|
||||||
|
"=>": "align_single_space",
|
||||||
|
".=": "align_single_space"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"concat_space": {
|
||||||
|
"spacing": "one"
|
||||||
|
},
|
||||||
|
"align_multiline_comment": {
|
||||||
|
"comment_type": "all_multiline"
|
||||||
|
},
|
||||||
|
"array_indentation": true,
|
||||||
|
"method_chaining_indentation": true,
|
||||||
|
"statement_indentation": {
|
||||||
|
"stick_comment_to_next_continuous_control_statement": true
|
||||||
|
},
|
||||||
|
"no_unused_imports": true,
|
||||||
|
"fully_qualified_strict_types": {
|
||||||
|
"import_symbols": true,
|
||||||
|
"leading_backslash_in_global_namespace": true,
|
||||||
|
"phpdoc_tags": []
|
||||||
|
},
|
||||||
|
"visibility_required": {
|
||||||
|
"elements": [
|
||||||
|
"const",
|
||||||
|
"method",
|
||||||
|
"property"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"no_useless_else": true,
|
||||||
|
"function_declaration": {
|
||||||
|
"closure_function_spacing": "one",
|
||||||
|
"closure_fn_spacing": "one",
|
||||||
|
"trailing_comma_single_line": false
|
||||||
|
},
|
||||||
|
"single_line_after_imports": true,
|
||||||
|
"combine_consecutive_issets": true,
|
||||||
|
"array_syntax": {
|
||||||
|
"syntax": "short"
|
||||||
|
},
|
||||||
|
"single_quote": true,
|
||||||
|
"blank_line_after_namespace": true,
|
||||||
|
"blank_line_after_opening_tag": true,
|
||||||
|
"declare_strict_types": true
|
||||||
|
}
|
||||||
|
}
|
||||||
52
rector.php
Normal file
52
rector.php
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Rector\Config\RectorConfig;
|
||||||
|
use RectorLaravel\Rector\Class_\CommandHiddenPropertyToHiddenAttributeRector;
|
||||||
|
use RectorLaravel\Rector\Class_\DescriptionPropertyToDescriptionAttributeRector;
|
||||||
|
use RectorLaravel\Rector\Class_\FillablePropertyToFillableAttributeRector;
|
||||||
|
use RectorLaravel\Rector\Class_\HiddenPropertyToHiddenAttributeRector;
|
||||||
|
use RectorLaravel\Rector\Class_\ModelCastsPropertyToCastsMethodRector;
|
||||||
|
use RectorLaravel\Rector\Class_\SignaturePropertyToSignatureAttributeRector;
|
||||||
|
use RectorLaravel\Rector\Class_\TablePropertyToTableAttributeRector;
|
||||||
|
use RectorLaravel\Rector\Class_\WithoutTimestampsPropertyToWithoutTimestampsAttributeRector;
|
||||||
|
use RectorLaravel\Rector\MethodCall\ValidationRuleArrayStringValueToArrayRector;
|
||||||
|
use RectorLaravel\Set\LaravelLevelSetList;
|
||||||
|
use RectorLaravel\Set\LaravelSetList;
|
||||||
|
use RectorLaravel\Set\LaravelSetProvider;
|
||||||
|
|
||||||
|
return RectorConfig::configure()
|
||||||
|
->withSetProviders(LaravelSetProvider::class)
|
||||||
|
->withPaths([
|
||||||
|
__DIR__ . '/config',
|
||||||
|
__DIR__ . '/src',
|
||||||
|
])
|
||||||
|
->withPhpSets()
|
||||||
|
->withComposerBased(laravel: true)
|
||||||
|
->withSets([
|
||||||
|
LaravelLevelSetList::UP_TO_LARAVEL_130,
|
||||||
|
LaravelSetList::LARAVEL_ARRAYACCESS_TO_METHOD_CALL,
|
||||||
|
LaravelSetList::LARAVEL_CODE_QUALITY,
|
||||||
|
LaravelSetList::LARAVEL_COLLECTION,
|
||||||
|
LaravelSetList::LARAVEL_IF_HELPERS,
|
||||||
|
LaravelSetList::LARAVEL_LEGACY_FACTORIES_TO_CLASSES,
|
||||||
|
LaravelSetList::LARAVEL_TYPE_DECLARATIONS,
|
||||||
|
])
|
||||||
|
->withTypeCoverageLevel(0)
|
||||||
|
->withDeadCodeLevel(0)
|
||||||
|
->withCodeQualityLevel(0)
|
||||||
|
->withSkip([
|
||||||
|
// Disable Laravel notations.
|
||||||
|
CommandHiddenPropertyToHiddenAttributeRector::class,
|
||||||
|
DescriptionPropertyToDescriptionAttributeRector::class,
|
||||||
|
FillablePropertyToFillableAttributeRector::class,
|
||||||
|
HiddenPropertyToHiddenAttributeRector::class,
|
||||||
|
ModelCastsPropertyToCastsMethodRector::class,
|
||||||
|
SignaturePropertyToSignatureAttributeRector::class,
|
||||||
|
TablePropertyToTableAttributeRector::class,
|
||||||
|
WithoutTimestampsPropertyToWithoutTimestampsAttributeRector::class,
|
||||||
|
|
||||||
|
// Validation.
|
||||||
|
ValidationRuleArrayStringValueToArrayRector::class,
|
||||||
|
]);
|
||||||
|
|
@ -1,230 +1,102 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace LDC\WebAdminSecureLaravel;
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Uwil\LaravelAdminSecure;
|
||||||
|
|
||||||
use Dxw\CIDR\IPAddress;
|
use Dxw\CIDR\IPAddress;
|
||||||
use Dxw\CIDR\IPv4Address;
|
use Dxw\CIDR\IPv4Address;
|
||||||
use Dxw\CIDR\IPv4Range;
|
use Dxw\CIDR\IPv4Range;
|
||||||
use Dxw\CIDR\IPv6Address;
|
use Dxw\CIDR\IPv6Address;
|
||||||
use Dxw\CIDR\IPv6Range;
|
use Dxw\CIDR\IPv6Range;
|
||||||
use Illuminate\Http\Client\Response;
|
use Uwil\LaravelAdminSecure\Exceptions\AdminSecureException;
|
||||||
use Illuminate\Support\Facades\Cache;
|
|
||||||
use Illuminate\Support\Facades\Http;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use LDC\WebAdminSecureLaravel\Exceptions\AdminSecureException;
|
|
||||||
use LDC\WebAdminSecureLaravel\Exceptions\AdminSecureInvalidAdressException;
|
|
||||||
|
|
||||||
abstract class AdminSecure
|
abstract class AdminSecure
|
||||||
{
|
{
|
||||||
/**
|
/** @var array<int,string> Private ipV4 CIDR list. */
|
||||||
* The cache key where to store ip list.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private static string $cache_key = 'ldcweb_ip_list';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The cache time to live.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private static string $cache_ttl = '180 minutes';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private ipV4 CIDR list
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private static array $private_ip_v4_cidr_list = [
|
private static array $private_ip_v4_cidr_list = [
|
||||||
'10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16'
|
'10.0.0.0/8',
|
||||||
|
'172.16.0.0/12',
|
||||||
|
'192.168.0.0/16',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/** @var string Private ipV4 CIDR loopback. */
|
||||||
* Private ipV4 CIDR loopback
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private static string $private_ip_v4_loopback_cidr = '127.0.0.0/8';
|
private static string $private_ip_v4_loopback_cidr = '127.0.0.0/8';
|
||||||
|
|
||||||
/**
|
/** @var array<int,string> Private ipV6 CIDR list. */
|
||||||
* Private ipV6 CIDR list
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private static array $private_ip_v6_cidr_list = [
|
private static array $private_ip_v6_cidr_list = [
|
||||||
'fd00::/8'
|
'fd00::/8',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private ipV6 CIDR loopback
|
* Private ipV6 CIDR loopback
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
*/
|
||||||
private static string $private_ip_v6_loopback_cidr = '::1/128';
|
private static string $private_ip_v6_loopback_cidr = '::1/128';
|
||||||
|
|
||||||
/**
|
/** @var \Uwil\LaravelAdminSecure\Options|null Private options. */
|
||||||
* Private options
|
|
||||||
*
|
|
||||||
* @var \LDC\WebAdminSecureLaravelOptions|null
|
|
||||||
*/
|
|
||||||
private static $options = null;
|
private static $options = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if ip is private
|
* Check if ip is private.
|
||||||
*
|
|
||||||
* @param \Dxw\CIDR\IPv4Address|\Dxw\CIDR\IPv6Address $ip_address
|
|
||||||
* @return boolean
|
|
||||||
*/
|
*/
|
||||||
public static function ipIsPrivate(IPv4Address|IPv6Address $ip_address): bool
|
public static function ipIsPrivate(IPv4Address | IPv6Address $ip_address): bool
|
||||||
{
|
{
|
||||||
return \get_class($ip_address) === IPv4Address::class ?
|
return $ip_address instanceof IPv4Address ?
|
||||||
self::ipV4IsPrivate($ip_address) : self::ipV6IsPrivate($ip_address);
|
self::ipV4IsPrivate($ip_address) : self::ipV6IsPrivate($ip_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch client IP
|
* Fetch client IP.
|
||||||
*
|
*
|
||||||
* @return \Dxw\CIDR\IPv4Address|\Dxw\CIDR\IPv6Address
|
* @throws \Uwil\LaravelAdminSecure\Exceptions\AdminSecureException If the ip is invalid.
|
||||||
* @throws \LDC\WebAdminSecureLaravel\AdminSecureException If the ip is invalid.
|
|
||||||
*/
|
*/
|
||||||
public static function fetchClientIp(): IPv4Address|IPv6Address
|
public static function fetchClientIp(): IPv4Address | IPv6Address
|
||||||
{
|
{
|
||||||
// ! HA PROXY HACK.
|
// ! REVERSE PROXY HACK.
|
||||||
$ip = request()->server('HTTP_X_FORWARDED_FOR') ?? request()->getClientIp();
|
$forwarded = request()->server('HTTP_X_FORWARDED_FOR');
|
||||||
$ip = IPAddress::Make($ip);
|
$ip = is_string($forwarded) && $forwarded !== ''
|
||||||
|
? trim(explode(',', $forwarded)[0])
|
||||||
|
: request()->getClientIp() ?? '0.0.0.0';
|
||||||
|
$ip = IPAddress::Make($ip);
|
||||||
|
|
||||||
if ($ip->isErr()) {
|
if ($ip->isErr()) {
|
||||||
throw new AdminSecureException(\trans('Client IP not valid ') . $ip->getErr());
|
throw new AdminSecureException(\trans('Client IP not valid ') . $ip->getErr());
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ip->unwrap();
|
return $ip->unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get ip list from cache
|
* Check if ipV4 is private.
|
||||||
*
|
|
||||||
* @return array<\Dxw\CIDR\IPv4Address|\Dxw\CIDR\IPv6Address>
|
|
||||||
*/
|
|
||||||
public static function getCacheList(): array
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
/** @var array<\Dxw\CIDR\IPv4Address|\Dxw\CIDR\IPv6Address>|null $ip_list */
|
|
||||||
$ip_list = Cache::get(self::$cache_key);
|
|
||||||
if (!$ip_list) {
|
|
||||||
$ip_list = self::fetchIpList();
|
|
||||||
self::validateIpList($ip_list);
|
|
||||||
self::setCacheList($ip_list);
|
|
||||||
return $ip_list;
|
|
||||||
}
|
|
||||||
return $ip_list;
|
|
||||||
} catch (AdminSecureInvalidAdressException) {
|
|
||||||
$ip_list = self::fetchIpList();
|
|
||||||
self::validateIpList($ip_list);
|
|
||||||
self::setCacheList($ip_list);
|
|
||||||
return $ip_list;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set ip list to cache
|
|
||||||
*
|
|
||||||
* @param array<\Dxw\CIDR\IPv4Address|\Dxw\CIDR\IPv6Address> $ip_list
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public static function setCacheList(array $ip_list): void
|
|
||||||
{
|
|
||||||
Cache::put(self::$cache_key, $ip_list, \DateInterval::createFromDateString(self::$cache_ttl));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch Ip Adress list from LDC Web
|
|
||||||
*
|
|
||||||
* @return array<\Dxw\CIDR\IPv4Address|\Dxw\CIDR\IPv6Address>
|
|
||||||
* @throws \LDC\WebAdminSecureLaravel\AdminSecureException If Wrong env value.
|
|
||||||
* @throws \Illuminate\Http\Client\RequestException If calling admin secure fails.
|
|
||||||
* @phpcs:disable Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
|
|
||||||
*/
|
|
||||||
public static function fetchIpList(): array
|
|
||||||
{
|
|
||||||
// phpcs:enable
|
|
||||||
$endpoint = self::getOptions()->getEndpoint();
|
|
||||||
$key = self::getOptions()->getApiKey();
|
|
||||||
|
|
||||||
$response = Http::get($endpoint, ['token' => $key])->throw();
|
|
||||||
$adresses = self::parseAdresses($response);
|
|
||||||
|
|
||||||
Log::info(\sprintf('ADMINSECURE : Fetched %d ip(s) from LDC WEB', \count($adresses)));
|
|
||||||
|
|
||||||
return $adresses;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if ipV4 is private
|
|
||||||
*
|
|
||||||
* @param \Dxw\CIDR\IPv4Address $ipv4_address
|
|
||||||
* @return boolean
|
|
||||||
*/
|
*/
|
||||||
private static function ipV4IsPrivate(IPv4Address $ipv4_address): bool
|
private static function ipV4IsPrivate(IPv4Address $ipv4_address): bool
|
||||||
{
|
{
|
||||||
return \collect(self::$private_ip_v4_cidr_list)
|
return \collect(self::$private_ip_v4_cidr_list)
|
||||||
->concat([self::$private_ip_v4_loopback_cidr])
|
->concat([self::$private_ip_v4_loopback_cidr])
|
||||||
->map(fn (string $ipv4_cidr) => IPv4Range::Make($ipv4_cidr)->unwrap())
|
->map(fn (string $ipv4_cidr) => IPv4Range::Make($ipv4_cidr)->unwrap())
|
||||||
->reduce(fn (bool|null $initial, IPv4Range $ipv4_range) =>
|
->reduce(fn (?bool $initial, IPv4Range $ipv4_range) => $initial || $ipv4_range->containsAddress($ipv4_address));
|
||||||
$initial || $ipv4_range->containsAddress($ipv4_address));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if ipV6 is private
|
* Check if ipV6 is private.
|
||||||
*
|
|
||||||
* @param \Dxw\CIDR\IPv6Address $ipv6_address
|
|
||||||
* @return boolean
|
|
||||||
*/
|
*/
|
||||||
private static function ipV6IsPrivate(IPv6Address $ipv6_address): bool
|
private static function ipV6IsPrivate(IPv6Address $ipv6_address): bool
|
||||||
{
|
{
|
||||||
return \collect(self::$private_ip_v6_cidr_list)
|
return \collect(self::$private_ip_v6_cidr_list)
|
||||||
->concat([self::$private_ip_v6_loopback_cidr])
|
->concat([self::$private_ip_v6_loopback_cidr])
|
||||||
->map(fn (string $ipv6_cidr) => IPv6Range::Make($ipv6_cidr)->unwrap())
|
->map(fn (string $ipv6_cidr) => IPv6Range::Make($ipv6_cidr)->unwrap())
|
||||||
->reduce(fn (bool|null $initial, IPv6Range $ipv6_range) =>
|
->reduce(fn (?bool $initial, IPv6Range $ipv6_range) => $initial || $ipv6_range->containsAddress($ipv6_address));
|
||||||
$initial || $ipv6_range->containsAddress($ipv6_address));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate ip list
|
* Get Admin secure options.
|
||||||
*
|
|
||||||
* @param array $ip_list
|
|
||||||
* @return void
|
|
||||||
* @throws \LDC\WebAdminSecureLaravel\Exceptions\AdminSecureInvalidAdressException If an IP is invalid.
|
|
||||||
*/
|
|
||||||
private static function validateIpList(array $ip_list): void
|
|
||||||
{
|
|
||||||
\collect($ip_list)->each(function ($ip) {
|
|
||||||
if (!\is_object($ip) or !\in_array(\get_class($ip), [IPv4Address::class, IPv6Address::class])) {
|
|
||||||
throw new AdminSecureInvalidAdressException('Invalid adresse ' . \strval(\json_encode($ip)));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse adresses
|
|
||||||
*
|
|
||||||
* @param \Illuminate\Http\Client\Response $response
|
|
||||||
* @return array<\Dxw\CIDR\IPAddress>
|
|
||||||
*/
|
|
||||||
private static function parseAdresses(Response $response): array
|
|
||||||
{
|
|
||||||
return \collect($response->json())
|
|
||||||
->map(fn (string $ip) => IPAddress::Make($ip)->unwrap())->all();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Admin secure options
|
|
||||||
*
|
|
||||||
* @return \LDC\WebAdminSecureLaravel\Options
|
|
||||||
*/
|
*/
|
||||||
public static function getOptions(): Options
|
public static function getOptions(): Options
|
||||||
{
|
{
|
||||||
if (!self::$options) {
|
if (! self::$options) {
|
||||||
self::$options = new Options(\config('admin-secure'));
|
self::$options = new Options(\config('admin-secure'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::$options;
|
return self::$options;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace LDC\WebAdminSecureLaravel;
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Uwil\LaravelAdminSecure;
|
||||||
|
|
||||||
use Illuminate\Console\Scheduling\Schedule;
|
|
||||||
use Illuminate\Contracts\Foundation\Application;
|
use Illuminate\Contracts\Foundation\Application;
|
||||||
use Illuminate\Support\ServiceProvider;
|
|
||||||
use Illuminate\Routing\Router;
|
use Illuminate\Routing\Router;
|
||||||
use LDC\WebAdminSecureLaravel\Console\SyncFromLDCWeb;
|
use Illuminate\Support\ServiceProvider;
|
||||||
use LDC\WebAdminSecureLaravel\Http\Middleware\AdminSecureMiddleware;
|
use Uwil\LaravelAdminSecure\Middlewares\AdminSecureMiddleware;
|
||||||
|
|
||||||
class AdminSecureServiceProvider extends ServiceProvider
|
class AdminSecureServiceProvider extends ServiceProvider
|
||||||
{
|
{
|
||||||
|
|
@ -22,20 +22,8 @@ class AdminSecureServiceProvider extends ServiceProvider
|
||||||
__DIR__ . '/../config' => config_path(),
|
__DIR__ . '/../config' => config_path(),
|
||||||
], 'config');
|
], 'config');
|
||||||
|
|
||||||
// * Register the command if we are using the application via the CLI .
|
// * Set filter condition.
|
||||||
$this->commands([SyncFromLDCWeb::class]);
|
$this->app->singleton('hasToFilterIp', fn (Application $app) => $app->environment('production', 'staging'));
|
||||||
|
|
||||||
// * Set filter condition
|
|
||||||
$this->app->singleton('hasToFilterIp', fn (Application $app) => $app->environment('production'));
|
|
||||||
|
|
||||||
// * Cron Report everyday
|
|
||||||
$this->app->booted(function () {
|
|
||||||
if ($this->app->make('hasToFilterIp')) {
|
|
||||||
/** @var \Illuminate\Console\Scheduling\Schedule */
|
|
||||||
$schedule = $this->app->make(Schedule::class);
|
|
||||||
$schedule->command('ldcweb:admin-secure-sync')->daily();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/** @var \Illuminate\Routing\Router */
|
/** @var \Illuminate\Routing\Router */
|
||||||
$router = $this->app->make(Router::class);
|
$router = $this->app->make(Router::class);
|
||||||
|
|
@ -47,6 +35,7 @@ class AdminSecureServiceProvider extends ServiceProvider
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
|
#[\Override]
|
||||||
public function register()
|
public function register()
|
||||||
{
|
{
|
||||||
$this->mergeConfigFrom(
|
$this->mergeConfigFrom(
|
||||||
|
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace LDC\WebAdminSecureLaravel\Console;
|
|
||||||
|
|
||||||
use Illuminate\Console\Command;
|
|
||||||
use LDC\WebAdminSecureLaravel\AdminSecure;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send Report Status To LDC Web.
|
|
||||||
*
|
|
||||||
* @author Vincent BRIDIER <vincent.bridier@ldc.fr>
|
|
||||||
*/
|
|
||||||
class SyncFromLDCWeb extends Command
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* The name and signature of the console command.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $signature = 'ldcweb:admin-secure-sync';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The console command description.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $description = 'Sync IP list from LDC Web';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute the console command.
|
|
||||||
*
|
|
||||||
* @return integer
|
|
||||||
* @throws \LDC\WebAdminSecureLaravel\Exceptions\AdminSecureException If missing LDC_WEB_API_KEY key.
|
|
||||||
*/
|
|
||||||
public function handle(): int
|
|
||||||
{
|
|
||||||
$this->info($this->description);
|
|
||||||
AdminSecure::setCacheList(AdminSecure::fetchIpList());
|
|
||||||
$this->info('Done.');
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace LDC\WebAdminSecureLaravel\Exceptions;
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Uwil\LaravelAdminSecure\Exceptions;
|
||||||
|
|
||||||
class AdminSecureException extends \Exception
|
class AdminSecureException extends \Exception
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace LDC\WebAdminSecureLaravel\Exceptions;
|
|
||||||
|
|
||||||
class AdminSecureInvalidAdressException extends AdminSecureException
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
@ -1,43 +1,39 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace LDC\WebAdminSecureLaravel\Http\Middleware;
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Uwil\LaravelAdminSecure\Middlewares;
|
||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
use Dxw\CIDR\IP;
|
|
||||||
use Dxw\CIDR\IPv4Address;
|
|
||||||
use Dxw\CIDR\IPv4Range;
|
use Dxw\CIDR\IPv4Range;
|
||||||
use Dxw\CIDR\IPv6Address;
|
|
||||||
use Dxw\CIDR\IPv6Range;
|
use Dxw\CIDR\IPv6Range;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use LDC\WebAdminSecureLaravel\AdminSecure;
|
use Uwil\LaravelAdminSecure\AdminSecure;
|
||||||
|
|
||||||
class AdminSecureMiddleware
|
class AdminSecureMiddleware
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Handle an incoming request.
|
* Handle an incoming request.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Http\Request $request
|
|
||||||
* @param \Closure $next
|
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function handle(Request $request, Closure $next)
|
public function handle(Request $request, Closure $next)
|
||||||
{
|
{
|
||||||
if (!\app()->make('hasToFilterIp')) {
|
if (! \app()->make('hasToFilterIp')) {
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
$client_ip = AdminSecure::fetchClientIp();
|
$client_ip = AdminSecure::fetchClientIp();
|
||||||
$ip_is_allowed = \collect(AdminSecure::getCacheList())
|
|
||||||
->reduce(fn (bool|null $initial, IPv4Address|IPv6Address $ip_address) => $initial || IP::contains(
|
$ip_is_allowed = \collect(AdminSecure::getOptions()->getCidrList())
|
||||||
$ip_address,
|
->reduce(fn (?bool $initial, IPv4Range | IPv6Range $ip_range) => $initial || $ip_range->containsAddress(
|
||||||
$client_ip
|
$client_ip
|
||||||
)->unwrap());
|
));
|
||||||
|
|
||||||
$ip_is_allowed_by_config = \collect(AdminSecure::getOptions()->getCidrAllowedList())
|
$ip_is_allowed_by_config = \collect(AdminSecure::getOptions()->getCidrAllowedList())
|
||||||
->reduce(fn (bool|null $initial, IPv4Range|IPv6Range $ip_range) => $initial || IP::contains(
|
->reduce(fn (?bool $initial, IPv4Range | IPv6Range $ip_range) => $initial || $ip_range->containsAddress(
|
||||||
$ip_range,
|
|
||||||
$client_ip
|
$client_ip
|
||||||
)->unwrap());
|
));
|
||||||
|
|
||||||
if ($ip_is_allowed or $ip_is_allowed_by_config or AdminSecure::ipIsPrivate($client_ip)) {
|
if ($ip_is_allowed or $ip_is_allowed_by_config or AdminSecure::ipIsPrivate($client_ip)) {
|
||||||
return $next($request);
|
return $next($request);
|
||||||
150
src/Options.php
150
src/Options.php
|
|
@ -2,40 +2,32 @@
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace LDC\WebAdminSecureLaravel;
|
namespace Uwil\LaravelAdminSecure;
|
||||||
|
|
||||||
use Dxw\CIDR\IPv4Range;
|
use Dxw\CIDR\IPv4Range;
|
||||||
use Dxw\CIDR\IPv6Range;
|
use Dxw\CIDR\IPv6Range;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
use LDC\WebAdminSecureLaravel\Exceptions\AdminSecureException;
|
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
use Uwil\LaravelAdminSecure\Exceptions\AdminSecureException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration
|
* Configuration
|
||||||
*/
|
*/
|
||||||
final class Options
|
final class Options
|
||||||
{
|
{
|
||||||
/**
|
/** @var array<string, mixed> The configuration options. */
|
||||||
* @var array<string, mixed> The configuration options
|
|
||||||
*/
|
|
||||||
private $options;
|
private $options;
|
||||||
|
|
||||||
/**
|
/** @var \Symfony\Component\OptionsResolver\OptionsResolver The options resolver. */
|
||||||
* @var \Symfony\Component\OptionsResolver\OptionsResolver The options resolver
|
|
||||||
*/
|
|
||||||
private $resolver;
|
private $resolver;
|
||||||
|
|
||||||
/**
|
/** @var string The cache key where to store config cidr list. */
|
||||||
* The cache key where to store config cidr list.
|
private static string $cache_config_key = 'uwil_ip_cidr_config_list';
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private static string $cache_config_key = 'ldcweb_ip_cidr_config_list';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class constructor.
|
* Class constructor.
|
||||||
*
|
*
|
||||||
* @param array<string, mixed> $options The configuration options.
|
* @param array<string, mixed> $options The configuration options.
|
||||||
*/
|
*/
|
||||||
public function __construct(array $options = [])
|
public function __construct(array $options = [])
|
||||||
{
|
{
|
||||||
|
|
@ -47,73 +39,46 @@ final class Options
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get end point url
|
* Get cidr list.
|
||||||
*
|
*
|
||||||
* @return string
|
* @return array<\Dxw\CIDR\IPv4Range|\Dxw\CIDR\IPv6Range>
|
||||||
*/
|
*/
|
||||||
public function getEndpoint(): string
|
public function getCidrList(): array
|
||||||
{
|
{
|
||||||
return $this->options['endpoint'];
|
return $this->options['cidrList'];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get api key
|
* Get cidr project allowed list.
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getApiKey(): string
|
|
||||||
{
|
|
||||||
return $this->options['apiKey'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get cidr allowed list
|
|
||||||
*
|
*
|
||||||
* @return array<\Dxw\CIDR\IPv4Range|\Dxw\CIDR\IPv6Range>
|
* @return array<\Dxw\CIDR\IPv4Range|\Dxw\CIDR\IPv6Range>
|
||||||
*/
|
*/
|
||||||
public function getCidrAllowedList(): array
|
public function getCidrAllowedList(): array
|
||||||
{
|
{
|
||||||
return $this->options['cidrManualAllowedList'];
|
return $this->options['cidrProjectAllowedList'];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the options of the client.
|
* Configures the options of the client.
|
||||||
*
|
*
|
||||||
* @param \Symfony\Component\OptionsResolver\OptionsResolver $resolver The resolver for the options.
|
* @param \Symfony\Component\OptionsResolver\OptionsResolver $resolver The resolver for the options.
|
||||||
* @return void
|
|
||||||
*/
|
*/
|
||||||
private function configureOptions(OptionsResolver $resolver): void
|
private function configureOptions(OptionsResolver $resolver): void
|
||||||
{
|
{
|
||||||
$resolver->setDefaults([
|
$resolver->setDefaults([
|
||||||
'endpoint' => '',
|
'cidrList' => [],
|
||||||
'apiKey' => '',
|
'cidrProjectAllowedList' => [],
|
||||||
'cidrManualAllowedList' => []
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$resolver->setAllowedTypes('endpoint', [
|
$resolver->setNormalizer('cidrList', $this->normalizeCidrList(...));
|
||||||
'string', \Closure::fromCallable([$this, 'validateEndpoint'])
|
$resolver->setNormalizer('cidrProjectAllowedList', $this->normalizeCidrProjectList(...));
|
||||||
]);
|
|
||||||
$resolver->setAllowedTypes('apiKey', 'string');
|
|
||||||
$resolver->setNormalizer('cidrManualAllowedList', \Closure::fromCallable([$this, 'normalizeCidrList']));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate endpoint
|
* Normalise Cidr list for cidrList option.
|
||||||
*
|
*
|
||||||
* @param null|string $value
|
* @return array<\Dxw\CIDR\IPv4Range|\Dxw\CIDR\IPv6Range>
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
private function validateEndpoint(?string $value): bool
|
|
||||||
{
|
|
||||||
return !(!$value or !\filter_var($value, \FILTER_VALIDATE_URL));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Normalise Cidr list
|
|
||||||
*
|
*
|
||||||
* @param \Symfony\Component\OptionsResolver\Options $options
|
|
||||||
* @param string $value
|
|
||||||
* @return array
|
|
||||||
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
|
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
|
||||||
*/
|
*/
|
||||||
private function normalizeCidrList(
|
private function normalizeCidrList(
|
||||||
|
|
@ -121,33 +86,64 @@ final class Options
|
||||||
?string $value
|
?string $value
|
||||||
): array {
|
): array {
|
||||||
// phpcs:enable
|
// phpcs:enable
|
||||||
|
return $this->doNormalizeCidrList($value, 'cidrList');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalise Cidr list for cidrProjectAllowedList option.
|
||||||
|
*
|
||||||
|
* @return array<\Dxw\CIDR\IPv4Range|\Dxw\CIDR\IPv6Range>
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
* @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 = collect(explode(',', strval($value)))->filter();
|
||||||
$allowed_cidr_config_list_hash = \md5($allowed_cidr_config_list->implode(','));
|
$allowed_cidr_config_list_hash = \md5($allowed_cidr_config_list->implode(','));
|
||||||
/** @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 AdminSecureException(\trans(
|
|
||||||
'LDC_WEB_CIDR_MANUAL_ALLOWED_LIST not valid (ipv4 or ipv6 cidr) :cidr',
|
|
||||||
[
|
|
||||||
'cidr' => $cidr
|
|
||||||
]
|
|
||||||
));
|
|
||||||
}
|
|
||||||
return $ip_range->unwrap();
|
|
||||||
})->all();
|
|
||||||
|
|
||||||
// * Flush cache if hash config hash changed
|
/** @var array{list: array<\Dxw\CIDR\IPv4Range|\Dxw\CIDR\IPv6Range>, hash: string}|null $cached */
|
||||||
if ($allowed_cidr_config_list_hash !== \collect(Cache::get(self::$cache_config_key))->get('hash')) {
|
$cached = Cache::get($cacheConfigKey);
|
||||||
Cache::flush(self::$cache_config_key);
|
|
||||||
|
// Flush cache if config hash changed
|
||||||
|
if ($cached === null || $cached['hash'] !== $allowed_cidr_config_list_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 AdminSecureException(\trans(
|
||||||
|
'CIDR LIST not valid (ipv4 or ipv6 cidr) :cidr',
|
||||||
|
['cidr' => $cidr]
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ip_range->unwrap();
|
||||||
|
})->all();
|
||||||
|
|
||||||
|
Cache::forever($cacheConfigKey, [
|
||||||
|
'list' => $allowed_cidr_list,
|
||||||
|
'hash' => $allowed_cidr_config_list_hash,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $allowed_cidr_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var array<\Dxw\CIDR\IPv4Range|\Dxw\CIDR\IPv6Range> $allowed_cidr_list */
|
return $cached['list'];
|
||||||
return \collect(Cache::rememberForever(self::$cache_config_key, fn () => [
|
|
||||||
'list' => $allowed_cidr_list,
|
|
||||||
'hash' => $allowed_cidr_config_list_hash
|
|
||||||
]))->get('list');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue