diff --git a/migrations/Version20251213142040.php b/migrations/Version20251213142040.php new file mode 100644 index 0000000..f105c54 --- /dev/null +++ b/migrations/Version20251213142040.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE entity ADD privacy_protection BOOLEAN NOT NULL DEFAULT FALSE'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE entity DROP privacy_protection'); + } +} diff --git a/src/Command/BatchRegisterDomainCommand.php b/src/Command/BatchRegisterDomainCommand.php index 51d2e34..b0dfe25 100644 --- a/src/Command/BatchRegisterDomainCommand.php +++ b/src/Command/BatchRegisterDomainCommand.php @@ -15,7 +15,7 @@ use Symfony\Component\Messenger\MessageBusInterface; use Symfony\Component\Messenger\Stamp\TransportNamesStamp; #[AsCommand( - name: 'app:batch-register-domains', + name: 'app:domains:import', description: 'Register a domain list', )] class BatchRegisterDomainCommand extends Command diff --git a/src/Command/EntityPrivacyCommand.php b/src/Command/EntityPrivacyCommand.php new file mode 100644 index 0000000..0170e3f --- /dev/null +++ b/src/Command/EntityPrivacyCommand.php @@ -0,0 +1,83 @@ +addArgument('handle', InputArgument::REQUIRED, 'Entity handle') + ->addArgument('tld', InputArgument::REQUIRED, 'Entity TLD') + ->addOption('enable', 'ep', InputOption::VALUE_NEGATABLE, 'Enable or disable privacy protection', true); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + $entity = $this->entityRepository->findOneBy(['handle' => $input->getArgument('handle'), 'tld' => $input->getArgument('tld')]); + $enable = $input->getOption('enable'); + + if (null === $entity) { + $io->error('Entity not found in the database.'); + + return Command::FAILURE; + } + + if ($entity->isPrivacyProtection() && $enable || !$entity->isPrivacyProtection() && !$enable) { + $io->warning('Privacy protection is already in the requested state.'); + + return Command::INVALID; + } + + $entity->setPrivacyProtection($enable); + + if ($enable) { + $entity->setJCard([]); + $entity->setRemarks([]); + } else { + $domainEntity = $entity->getDomainEntities()->findFirst(fn (int $key, DomainEntity $de) => null === $de->getDeletedAt() && !$de->getDomain()->getDeleted()); + if (null !== $domainEntity) { + try { + $this->RDAPService->registerDomain($domainEntity->getDomain()->getLdhName()); + } catch (\Exception) { + $io->warning('Failed to update the jCard using a linked domain.'); + } + } + } + + $this->em->flush(); + + $io->success(sprintf( + 'Privacy protection %s for entity %s (%s).', + $enable ? 'enabled' : 'disabled', + $entity->getHandle(), + $entity->getTld()->getTld() + )); + + return Command::SUCCESS; + } +} diff --git a/src/Command/ProcessWatchlistCommand.php b/src/Command/ProcessWatchlistCommand.php index a923f13..5da0990 100644 --- a/src/Command/ProcessWatchlistCommand.php +++ b/src/Command/ProcessWatchlistCommand.php @@ -12,7 +12,7 @@ use Symfony\Component\Messenger\Exception\ExceptionInterface; use Symfony\Component\Messenger\MessageBusInterface; #[AsCommand( - name: 'app:process-watchlist', + name: 'app:watchlist:process', description: 'Process watchlist and send emails if necessary', )] class ProcessWatchlistCommand extends Command diff --git a/src/Command/RegisterDomainCommand.php b/src/Command/RegisterDomainCommand.php index 9a611d1..a352136 100644 --- a/src/Command/RegisterDomainCommand.php +++ b/src/Command/RegisterDomainCommand.php @@ -17,7 +17,7 @@ use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Messenger\MessageBusInterface; #[AsCommand( - name: 'app:register-domain', + name: 'app:domain:register', description: 'Register a domain name in the database', )] class RegisterDomainCommand extends Command diff --git a/src/Command/UpdateRdapServersCommand.php b/src/Command/UpdateRdapServersCommand.php index 9cb8c74..a3709f9 100644 --- a/src/Command/UpdateRdapServersCommand.php +++ b/src/Command/UpdateRdapServersCommand.php @@ -12,7 +12,7 @@ use Symfony\Component\Messenger\Exception\ExceptionInterface; use Symfony\Component\Messenger\MessageBusInterface; #[AsCommand( - name: 'app:update-rdap-servers', + name: 'app:rdap-server:update', description: 'Updates the RDAP servers cache (requires MQ to be running)', )] class UpdateRdapServersCommand extends Command diff --git a/src/Entity/Entity.php b/src/Entity/Entity.php index 3a66d27..f009c96 100644 --- a/src/Entity/Entity.php +++ b/src/Entity/Entity.php @@ -67,15 +67,17 @@ class Entity #[ORM\Column( type: 'string', + nullable: true, insertable: false, updatable: false, columnDefinition: "VARCHAR(255) GENERATED ALWAYS AS (UPPER(jsonb_path_query_first(j_card, '$[1]?(@[0] == \"fn\")[3]') #>> '{}')) STORED", - generated: 'ALWAYS', + generated: 'ALWAYS' )] private ?string $jCardFn; #[ORM\Column( type: 'string', + nullable: true, insertable: false, updatable: false, columnDefinition: "VARCHAR(255) GENERATED ALWAYS AS (UPPER(jsonb_path_query_first(j_card, '$[1]?(@[0] == \"org\")[3]') #>> '{}')) STORED", @@ -91,6 +93,10 @@ class Entity #[Groups(['entity:list', 'entity:item', 'domain:item'])] private ?IcannAccreditation $icannAccreditation = null; + #[ORM\Column] + #[Groups(['entity:item', 'domain:item', 'watchlist:item'])] + private ?bool $privacyProtection = null; + public function __construct() { $this->domainEntities = new ArrayCollection(); @@ -283,4 +289,16 @@ class Entity return $this; } + + public function isPrivacyProtection(): ?bool + { + return $this->privacyProtection; + } + + public function setPrivacyProtection(bool $privacyProtection): static + { + $this->privacyProtection = $privacyProtection; + + return $this; + } } diff --git a/src/Service/RDAPService.php b/src/Service/RDAPService.php index 6a96f2c..971c864 100644 --- a/src/Service/RDAPService.php +++ b/src/Service/RDAPService.php @@ -588,11 +588,11 @@ class RDAPService $entity->setHandle($rdapEntity['handle'])->setIcannAccreditation($icannAccreditation); - if (isset($rdapEntity['remarks']) && is_array($rdapEntity['remarks'])) { + if (isset($rdapEntity['remarks']) && is_array($rdapEntity['remarks']) && !$entity->isPrivacyProtection()) { $entity->setRemarks($rdapEntity['remarks']); } - if (isset($rdapEntity['vcardArray'])) { + if (isset($rdapEntity['vcardArray']) && !$entity->isPrivacyProtection()) { if (empty($entity->getJCard())) { if (!array_key_exists('elements', $rdapEntity['vcardArray'])) { $entity->setJCard($rdapEntity['vcardArray']);