ldc-web-admin-secure-laravel/src/Options.php

154 lines
4.3 KiB
PHP
Raw Normal View History

<?php
declare(strict_types=1);
namespace LDC\WebAdminSecureLaravel;
use Dxw\CIDR\IPv4Range;
use Dxw\CIDR\IPv6Range;
use Illuminate\Support\Facades\Cache;
use LDC\WebAdminSecureLaravel\Exceptions\AdminSecureException;
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 string $cache_config_key = 'ldcweb_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 end point url
*
* @return string
*/
public function getEndpoint(): string
{
return $this->options['endpoint'];
}
/**
* Get api key
*
* @return string
*/
public function getApiKey(): string
{
return $this->options['apiKey'];
}
/**
* Get cidr allowed list
*
* @return array<\Dxw\CIDR\IPv4Range|\Dxw\CIDR\IPv6Range>
*/
public function getCidrAllowedList(): array
{
return $this->options['cidrManualAllowedList'];
}
/**
* 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([
'endpoint' => '',
'apiKey' => '',
'cidrManualAllowedList' => []
]);
$resolver->setAllowedTypes('endpoint', [
'string', \Closure::fromCallable([$this, 'validateEndpoint'])
]);
$resolver->setAllowedTypes('apiKey', 'string');
$resolver->setNormalizer('cidrManualAllowedList', \Closure::fromCallable([$this, 'normalizeCidrList']));
}
/**
* Validate endpoint
*
* @param null|string $value
* @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
*/
private function normalizeCidrList(
\Symfony\Component\OptionsResolver\Options $options,
?string $value
): array {
// phpcs:enable
$allowed_cidr_config_list = collect(explode(',', strval($value)))->filter();
$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
if ($allowed_cidr_config_list_hash !== \collect(Cache::get(self::$cache_config_key))->get('hash')) {
2024-04-04 15:08:22 +02:00
Cache::forget(self::$cache_config_key);
}
/** @var array<\Dxw\CIDR\IPv4Range|\Dxw\CIDR\IPv6Range> $allowed_cidr_list */
return \collect(Cache::rememberForever(self::$cache_config_key, fn () => [
'list' => $allowed_cidr_list,
'hash' => $allowed_cidr_config_list_hash
]))->get('list');
}
}