feat: user can force domain refresh

This commit is contained in:
Maël Gangloff
2025-01-01 14:10:23 +01:00
parent 30f6ee3575
commit 3605f88a7c
5 changed files with 28 additions and 23 deletions

View File

@@ -1,19 +1,22 @@
import {Form, Input} from 'antd' import {Form, Input} from 'antd'
import {t} from 'ttag' import {t} from 'ttag'
import {SearchOutlined} from '@ant-design/icons' import {SearchOutlined} from '@ant-design/icons'
import React from 'react' import React, {useState} from 'react'
export interface FieldType { export interface FieldType {
ldhName: string ldhName: string
isRefreshForced: boolean
} }
export function DomainSearchBar({onFinish, initialValue}: { export function DomainSearchBar({onFinish, initialValue}: {
onFinish: (values: FieldType) => void, onFinish: (values: FieldType) => void,
initialValue?: string initialValue?: string
}) { }) {
const [isRefreshForced, setRefreshForced] = useState(false)
return ( return (
<Form <Form
onFinish={onFinish} onFinish={({ldhName}: FieldType) => onFinish({ldhName, isRefreshForced})}
autoComplete='off' autoComplete='off'
style={{width: '100%'}} style={{width: '100%'}}
> >
@@ -33,6 +36,8 @@ export function DomainSearchBar({onFinish, initialValue}: {
<Input <Input
style={{textAlign: 'center'}} style={{textAlign: 'center'}}
size='large' size='large'
onKeyDown={e => setRefreshForced(e.shiftKey)}
onKeyUp={e => setRefreshForced(e.shiftKey)}
prefix={<SearchOutlined/>} prefix={<SearchOutlined/>}
placeholder='example.com' placeholder='example.com'
autoComplete='off' autoComplete='off'

View File

@@ -1,4 +1,4 @@
import {Col, List, Tag, Tooltip, Typography} from 'antd' import {List, Tag, Tooltip, Typography} from 'antd'
import React from 'react' import React from 'react'
import type {Domain} from '../../utils/api' import type {Domain} from '../../utils/api'
import {rdapRoleDetailTranslation, rdapRoleTranslation} from '../../utils/functions/rdapTranslation' import {rdapRoleDetailTranslation, rdapRoleTranslation} from '../../utils/functions/rdapTranslation'
@@ -29,19 +29,15 @@ export function EntitiesList({domain}: { domain: Domain }) {
const details = extractDetailsFromJCard(e) const details = extractDetailsFromJCard(e)
return <List.Item> return <List.Item>
<Col span={14}> <List.Item.Meta
<List.Item.Meta avatar={roleToAvatar(e)}
avatar={roleToAvatar(e)} title={<Typography.Text code>{e.entity.handle}</Typography.Text>}
title={<Typography.Text code>{e.entity.handle}</Typography.Text>} description={<>
description={<> {details.fn && <div>👤 {details.fn}</div>}
{details.fn && <div>👤 {details.fn}</div>} {details.organization && <div>🏢 {details.organization}</div>}
{details.organization && <div>🏢 {details.organization}</div>} </>}
</>} />
/> {e.roles.map(roleToTag)}
</Col>
<Col span={10} flex='none'>
{e.roles.map(roleToTag)}
</Col>
</List.Item> </List.Item>
}} }}
/> />

View File

@@ -19,13 +19,15 @@ export default function DomainSearchPage() {
const [messageApi, contextHolder] = message.useMessage() const [messageApi, contextHolder] = message.useMessage()
const navigate = useNavigate() const navigate = useNavigate()
const onFinish: FormProps<FieldType>['onFinish'] = (values) => { const onFinish: FormProps<FieldType>['onFinish'] = (values) => {
navigate('/search/domain/' + values.ldhName) navigate('/search/domain/' + values.ldhName)
if (loading) return if (loading) return
setLoading(true) setLoading(true)
setDomain(null) setDomain(null)
getDomain(values.ldhName).then(d => { getDomain(values.ldhName, values.isRefreshForced).then(d => {
setDomain(d) setDomain(d)
messageApi.success(t`Found !`) messageApi.success(t`Found !`)
}).catch((e: AxiosError) => { }).catch((e: AxiosError) => {
@@ -36,7 +38,7 @@ export default function DomainSearchPage() {
useEffect(() => { useEffect(() => {
if (query === undefined) return if (query === undefined) return
onFinish({ldhName: query}) onFinish({ldhName: query, isRefreshForced: false})
}, []) }, [])
return ( return (

View File

@@ -1,9 +1,10 @@
import type {Domain} from '.' import type {Domain} from '.'
import { request} from '.' import {request} from '.'
export async function getDomain(ldhName: string): Promise<Domain> { export async function getDomain(ldhName: string, forced = false): Promise<Domain> {
const response = await request<Domain>({ const response = await request<Domain>({
url: 'domains/' + ldhName url: 'domains/' + ldhName,
params: {forced}
}) })
return response.data return response.data
} }

View File

@@ -10,6 +10,7 @@ use App\Service\RDAPService;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Random\Randomizer; use Random\Randomizer;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException; use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException;
use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Messenger\Exception\ExceptionInterface; use Symfony\Component\Messenger\Exception\ExceptionInterface;
@@ -37,7 +38,7 @@ class DomainRefreshController extends AbstractController
* @throws HttpExceptionInterface * @throws HttpExceptionInterface
* @throws \Throwable * @throws \Throwable
*/ */
public function __invoke(string $ldhName, KernelInterface $kernel): Domain public function __invoke(string $ldhName, KernelInterface $kernel, Request $request): Domain
{ {
$idnDomain = strtolower(idn_to_ascii($ldhName)); $idnDomain = strtolower(idn_to_ascii($ldhName));
$userId = $this->getUser()->getUserIdentifier(); $userId = $this->getUser()->getUserIdentifier();
@@ -49,12 +50,12 @@ class DomainRefreshController extends AbstractController
/** @var ?Domain $domain */ /** @var ?Domain $domain */
$domain = $this->domainRepository->findOneBy(['ldhName' => $idnDomain]); $domain = $this->domainRepository->findOneBy(['ldhName' => $idnDomain]);
// If the domain name exists in the database, recently updated and not important, we return the stored Domain // If the domain name exists in the database, recently updated and not important, we return the stored Domain
if (null !== $domain if (null !== $domain
&& !$domain->getDeleted() && !$domain->getDeleted()
&& !$domain->isToBeUpdated() && !$domain->isToBeUpdated()
&& !$this->kernel->isDebug() && !$this->kernel->isDebug()
&& true !== filter_var($request->get('forced', false), FILTER_VALIDATE_BOOLEAN)
) { ) {
$this->logger->info('It is not necessary to update the information of the domain name {idnDomain} with the RDAP protocol.', [ $this->logger->info('It is not necessary to update the information of the domain name {idnDomain} with the RDAP protocol.', [
'idnDomain' => $idnDomain, 'idnDomain' => $idnDomain,