feat: allow unauthenticated users to perform domain name lookups

This commit is contained in:
Maël Gangloff
2025-12-08 18:18:33 +01:00
parent eddb267275
commit 5476ee7acc
16 changed files with 214 additions and 110 deletions

View File

@@ -15,7 +15,8 @@ class InstanceController extends AbstractController
->setLimitedFeatures($this->getParameter('limited_features') ?? false)
->setOauthEnabled($this->getParameter('oauth_enabled') ?? false)
->setRegisterEnabled($this->getParameter('registration_enabled') ?? false)
->setSsoAutoRedirect($this->getParameter('sso_auto_redirect') ?? false);
->setSsoAutoRedirect($this->getParameter('sso_auto_redirect') ?? false)
->setPublicRdapLookupEnabled($this->getParameter('public_rdap_lookup_enabled') ?? false);
return $instance;
}

View File

@@ -71,7 +71,7 @@ use Symfony\Component\Serializer\Attribute\SerializedName;
],
),
],
provider: AutoRegisterDomainProvider::class
provider: AutoRegisterDomainProvider::class,
)]
class Domain
{

View File

@@ -30,6 +30,8 @@ class Instance
private ?bool $ssoAutoRedirect = null;
private ?bool $publicRdapLookupEnabled = null;
public function isSsoLogin(): ?bool
{
return $this->oauthEnabled;
@@ -77,4 +79,16 @@ class Instance
return $this;
}
public function getPublicRdapLookupEnabled(): ?bool
{
return $this->publicRdapLookupEnabled;
}
public function setPublicRdapLookupEnabled(?bool $publicRdapLookupEnabled): static
{
$this->publicRdapLookupEnabled = $publicRdapLookupEnabled;
return $this;
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace App\Security\Voter;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
class RdapLookupVoter extends Voter
{
public const string ATTRIBUTE = 'CAN_RDAP_LOOKUP';
public function __construct(
private readonly ParameterBagInterface $parameterBag,
private readonly Security $security,
) {
}
protected function supports(string $attribute, mixed $subject): bool
{
return self::ATTRIBUTE === $attribute;
}
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
{
if ($this->security->isGranted('IS_AUTHENTICATED_FULLY')) {
return true;
}
return $this->parameterBag->get('public_rdap_lookup_enabled');
}
}

View File

@@ -41,6 +41,7 @@ readonly class AutoRegisterDomainProvider implements ProviderInterface
private KernelInterface $kernel,
private ParameterBagInterface $parameterBag,
private RateLimiterFactory $userRdapRequestsLimiter,
private RateLimiterFactory $publicRdapRequestsLimiter,
private Security $security,
private LoggerInterface $logger,
private DomainRepository $domainRepository,
@@ -68,14 +69,20 @@ readonly class AutoRegisterDomainProvider implements ProviderInterface
public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
{
$fromWatchlist = array_key_exists('root_operation', $context) && Watchlist::class === $context['root_operation']?->getClass();
$userId = $this->security->getUser()->getUserIdentifier();
$idnDomain = RDAPService::convertToIdn($uriVariables['ldhName']);
$this->logger->info('User wants to update a domain name', [
'username' => $userId,
'ldhName' => $idnDomain,
]);
$user = $this->security->getUser();
if (null !== $user) {
$this->logger->info('User wants to update a domain name', [
'username' => $user->getUserIdentifier(),
'ldhName' => $idnDomain,
]);
} else {
$this->logger->info('Anonymous wants to update a domain name', [
'ldhName' => $idnDomain,
]);
}
$request = $this->requestStack->getCurrentRequest();
@@ -96,7 +103,7 @@ readonly class AutoRegisterDomainProvider implements ProviderInterface
}
if (false === $this->kernel->isDebug() && true === $this->parameterBag->get('limited_features')) {
$limiter = $this->userRdapRequestsLimiter->create($userId);
$limiter = $user ? $this->userRdapRequestsLimiter->create($user->getUserIdentifier()) : $this->publicRdapRequestsLimiter->create($request->getClientIp());
$limit = $limiter->consume();
if (!$limit->isAccepted()) {