159 lines
4.9 KiB
PHP
159 lines
4.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Lib;
|
|
|
|
use Dxw\CIDR\IPv4Range;
|
|
use Dxw\CIDR\IPv6Range;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
|
|
|
/**
|
|
* Configuration
|
|
*/
|
|
final class Options
|
|
{
|
|
/**
|
|
* @var array<string, mixed> 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<string, mixed> $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');
|
|
}
|
|
}
|