mirror of
https://github.com/maelgangloff/domain-watchdog.git
synced 2025-12-29 16:15:04 +00:00
chore: merge master
This commit is contained in:
47
assets/components/search/DomainDiagram.tsx
Normal file
47
assets/components/search/DomainDiagram.tsx
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import React, {useEffect} from "react";
|
||||||
|
import {Background, Controls, MiniMap, ReactFlow, useEdgesState, useNodesState} from "@xyflow/react";
|
||||||
|
import {Flex} from "antd";
|
||||||
|
import {Domain} from "../../utils/api";
|
||||||
|
import {getLayoutedElements} from "../tracking/watchlist/diagram/getLayoutedElements";
|
||||||
|
import {domainEntitiesToNode, domainToNode, nsToNode, tldToNode} from "../tracking/watchlist/diagram/watchlistToNodes";
|
||||||
|
import {domainEntitiesToEdges, domainNSToEdges, tldToEdge} from "../tracking/watchlist/diagram/watchlistToEdges";
|
||||||
|
|
||||||
|
export function DomainDiagram({domain}: { domain: Domain }) {
|
||||||
|
const [nodes, setNodes, onNodesChange] = useNodesState([])
|
||||||
|
const [edges, setEdges, onEdgesChange] = useEdgesState([])
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const e = getLayoutedElements([
|
||||||
|
domainToNode(domain),
|
||||||
|
...domainEntitiesToNode(domain),
|
||||||
|
tldToNode(domain.tld),
|
||||||
|
...domain.nameservers.map(nsToNode)
|
||||||
|
].flat(), [
|
||||||
|
domainEntitiesToEdges(domain),
|
||||||
|
tldToEdge(domain),
|
||||||
|
...domainNSToEdges(domain)
|
||||||
|
].flat())
|
||||||
|
|
||||||
|
setNodes(e.nodes)
|
||||||
|
setEdges(e.edges)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return <Flex style={{width: '80vw', height: '80vh'}}>
|
||||||
|
<ReactFlow
|
||||||
|
fitView
|
||||||
|
colorMode='system'
|
||||||
|
nodesConnectable={false}
|
||||||
|
edgesReconnectable={false}
|
||||||
|
nodes={nodes}
|
||||||
|
edges={edges}
|
||||||
|
onNodesChange={onNodesChange}
|
||||||
|
onEdgesChange={onEdgesChange}
|
||||||
|
style={{width: '100%', height: '100%'}}
|
||||||
|
>
|
||||||
|
<MiniMap/>
|
||||||
|
<Controls/>
|
||||||
|
<Background/>
|
||||||
|
</ReactFlow>
|
||||||
|
</Flex>
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ import punycode from "punycode/punycode";
|
|||||||
import {Connector} from "../../../utils/api/connectors";
|
import {Connector} from "../../../utils/api/connectors";
|
||||||
import {UpdateWatchlistButton} from "./UpdateWatchlistButton";
|
import {UpdateWatchlistButton} from "./UpdateWatchlistButton";
|
||||||
import {DeleteWatchlistButton} from "./DeleteWatchlistButton";
|
import {DeleteWatchlistButton} from "./DeleteWatchlistButton";
|
||||||
import {ViewDiagramWatchlistButton} from "../diagram/ViewDiagramWatchlistButton";
|
import {ViewDiagramWatchlistButton} from "./diagram/ViewDiagramWatchlistButton";
|
||||||
|
|
||||||
export function WatchlistsList({watchlists, onDelete, onUpdateWatchlist, connectors}: {
|
export function WatchlistsList({watchlists, onDelete, onUpdateWatchlist, connectors}: {
|
||||||
watchlists: Watchlist[],
|
watchlists: Watchlist[],
|
||||||
|
|||||||
@@ -2,72 +2,26 @@ import {Button, Flex, Modal, Space, Typography} from "antd"
|
|||||||
import {t} from "ttag"
|
import {t} from "ttag"
|
||||||
import React, {useEffect, useState} from "react"
|
import React, {useEffect, useState} from "react"
|
||||||
import {ApartmentOutlined} from "@ant-design/icons"
|
import {ApartmentOutlined} from "@ant-design/icons"
|
||||||
import vCard from "vcf";
|
|
||||||
|
|
||||||
import '@xyflow/react/dist/style.css'
|
import '@xyflow/react/dist/style.css'
|
||||||
import {Background, Controls, MiniMap, ReactFlow, useEdgesState, useNodesState} from "@xyflow/react";
|
import {Background, Controls, MiniMap, ReactFlow, useEdgesState, useNodesState} from "@xyflow/react";
|
||||||
import {getWatchlist, Watchlist} from "../../../utils/api";
|
import {getWatchlist} from "../../../../utils/api";
|
||||||
import {translateRoles} from "../../search/EntitiesList";
|
|
||||||
import {getLayoutedElements} from "./getLayoutedElements";
|
import {getLayoutedElements} from "./getLayoutedElements";
|
||||||
|
import {watchlistToNodes} from "./watchlistToNodes";
|
||||||
|
import {watchlistToEdges} from "./watchlistToEdges";
|
||||||
|
|
||||||
|
export type DiagramConfig = {
|
||||||
function watchlistToNodes(watchlist: Watchlist) {
|
tld?: boolean
|
||||||
const domains = watchlist.domains.map(d => ({
|
nameserver?: boolean
|
||||||
id: d.ldhName,
|
entities?: boolean
|
||||||
data: {label: <b>{d.ldhName}</b>},
|
|
||||||
style: {
|
|
||||||
width: 200
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
const entities = [...new Set(watchlist.domains
|
|
||||||
.map(d => d.entities
|
|
||||||
.filter(e => !e.roles.includes('registrar'))
|
|
||||||
.map(e => e.entity
|
|
||||||
)
|
|
||||||
).flat())].map(e => {
|
|
||||||
const jCard = vCard.fromJSON(e.jCard)
|
|
||||||
let label = e.handle
|
|
||||||
if (jCard.data.fn !== undefined && !Array.isArray(jCard.data.fn)) label = jCard.data.fn.valueOf()
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: e.handle,
|
|
||||||
data: {label},
|
|
||||||
style: {
|
|
||||||
width: 200
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return [...domains, ...entities]
|
|
||||||
}
|
|
||||||
|
|
||||||
const rolesToColor = (roles: string[]) => roles.includes('registrant') ? 'green' :
|
|
||||||
roles.includes('administrative') ? 'blue' :
|
|
||||||
roles.includes('technical') ? 'orange' : 'violet'
|
|
||||||
|
|
||||||
function watchlistToEdges(watchlist: Watchlist) {
|
|
||||||
const domainRole = translateRoles()
|
|
||||||
|
|
||||||
return watchlist.domains
|
|
||||||
.map(d => d.entities
|
|
||||||
.filter(e => !e.roles.includes('registrar'))
|
|
||||||
.map(e => ({
|
|
||||||
id: `${d.ldhName}-${e.entity.handle}`,
|
|
||||||
source: e.roles.includes('technical') ? d.ldhName : e.entity.handle,
|
|
||||||
target: e.roles.includes('technical') ? e.entity.handle : d.ldhName,
|
|
||||||
style: {stroke: rolesToColor(e.roles), strokeWidth: 3},
|
|
||||||
label: e.roles.map(r => Object.keys(domainRole).includes(r) ? domainRole[r as keyof typeof domainRole] : r).join(', '),
|
|
||||||
animated: e.roles.includes('registrant'),
|
|
||||||
}))
|
|
||||||
).flat(2)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ViewDiagramWatchlistButton({token}: { token: string }) {
|
export function ViewDiagramWatchlistButton({token}: { token: string }) {
|
||||||
const [open, setOpen] = useState(false)
|
|
||||||
|
|
||||||
|
const [open, setOpen] = useState(false)
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
const [nodes, setNodes, onNodesChange] = useNodesState([]);
|
const [nodes, setNodes, onNodesChange] = useNodesState([])
|
||||||
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
|
const [edges, setEdges, onEdgesChange] = useEdgesState([])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!open) return
|
if (!open) return
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import {Domain, Watchlist} from "../../../../utils/api";
|
||||||
|
import {translateRoles} from "../../../search/EntitiesList";
|
||||||
|
import {t} from "ttag";
|
||||||
|
|
||||||
|
const rolesToColor = (roles: string[]) => roles.includes('registrant') ? 'green' :
|
||||||
|
roles.includes('administrative') ? 'blue' :
|
||||||
|
roles.includes('technical') ? 'orange' : 'violet'
|
||||||
|
|
||||||
|
export function domainEntitiesToEdges(d: Domain) {
|
||||||
|
const domainRole = translateRoles()
|
||||||
|
return d.entities
|
||||||
|
.filter(e => !e.roles.includes('registrar')) //
|
||||||
|
.map(e => ({
|
||||||
|
id: `e-${d.ldhName}-${e.entity.handle}`,
|
||||||
|
source: e.roles.includes('registrant') ? e.entity.handle : d.ldhName,
|
||||||
|
target: e.roles.includes('registrant') ? d.ldhName : e.entity.handle,
|
||||||
|
style: {stroke: rolesToColor(e.roles), strokeWidth: 3},
|
||||||
|
label: e.roles
|
||||||
|
.map(r => Object.keys(domainRole).includes(r) ? domainRole[r as keyof typeof domainRole] : r)
|
||||||
|
.join(', '),
|
||||||
|
animated: e.roles.includes('registrant'),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
export const domainNSToEdges = (d: Domain) => d.nameservers
|
||||||
|
.map(ns => ({
|
||||||
|
id: `ns-${d.ldhName}-${ns.ldhName}`,
|
||||||
|
source: d.ldhName,
|
||||||
|
target: ns.ldhName,
|
||||||
|
style: {stroke: 'grey', strokeWidth: 3},
|
||||||
|
label: 'DNS'
|
||||||
|
}))
|
||||||
|
|
||||||
|
export const tldToEdge = (d: Domain) => ({
|
||||||
|
id: `tld-${d.ldhName}-${d.tld.tld}`,
|
||||||
|
source: d.tld.tld,
|
||||||
|
target: d.ldhName,
|
||||||
|
style: {stroke: 'yellow', strokeWidth: 3},
|
||||||
|
label: t`Registry`
|
||||||
|
})
|
||||||
|
|
||||||
|
export function watchlistToEdges(watchlist: Watchlist) {
|
||||||
|
const entitiesEdges = watchlist.domains.map(domainEntitiesToEdges).flat()
|
||||||
|
const nameserversEdges = watchlist.domains.map(domainNSToEdges).flat()
|
||||||
|
|
||||||
|
return [...entitiesEdges, ...nameserversEdges]
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
import {Domain, Nameserver, Tld, Watchlist} from "../../../../utils/api";
|
||||||
|
import vCard from "vcf";
|
||||||
|
import React from "react";
|
||||||
|
import {t} from 'ttag'
|
||||||
|
|
||||||
|
export const domainToNode = (d: Domain) => ({
|
||||||
|
id: d.ldhName,
|
||||||
|
data: {label: <b>{d.ldhName}</b>},
|
||||||
|
style: {
|
||||||
|
width: 200
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export const domainEntitiesToNode = (d: Domain) => d.entities
|
||||||
|
.filter(e => !e.roles.includes('registrar')) //
|
||||||
|
.map(e => {
|
||||||
|
const jCard = vCard.fromJSON(e.entity.jCard)
|
||||||
|
let label = e.entity.handle
|
||||||
|
if (jCard.data.fn !== undefined && !Array.isArray(jCard.data.fn)) label = jCard.data.fn.valueOf()
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: e.entity.handle,
|
||||||
|
data: {label},
|
||||||
|
style: {
|
||||||
|
width: 200
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export const tldToNode = (tld: Tld) => ({
|
||||||
|
id: tld.tld,
|
||||||
|
data: {label: t`.${tld.tld} Registry`},
|
||||||
|
style: {
|
||||||
|
width: 200
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export const nsToNode = (ns: Nameserver) => ({
|
||||||
|
id: ns.ldhName,
|
||||||
|
data: {label: ns.ldhName},
|
||||||
|
style: {
|
||||||
|
width: 200
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export function watchlistToNodes(watchlist: Watchlist) {
|
||||||
|
|
||||||
|
const domains = watchlist.domains.map(domainToNode)
|
||||||
|
const entities = [...new Set(watchlist.domains.map(domainEntitiesToNode).flat())]
|
||||||
|
const tlds = [...new Set(watchlist.domains.map(d => d.tld))].map(tldToNode)
|
||||||
|
const nameservers = [...new Set(watchlist.domains.map(d => d.nameservers))].flat().map(nsToNode)
|
||||||
|
|
||||||
|
return [...domains, ...entities, ...nameservers]
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ import {DomainSearchBar, FieldType} from "../../components/search/DomainSearchBa
|
|||||||
import {EventTimeline} from "../../components/search/EventTimeline";
|
import {EventTimeline} from "../../components/search/EventTimeline";
|
||||||
import {EntitiesList} from "../../components/search/EntitiesList";
|
import {EntitiesList} from "../../components/search/EntitiesList";
|
||||||
import {showErrorAPI} from "../../utils";
|
import {showErrorAPI} from "../../utils";
|
||||||
|
import {DomainDiagram} from "../../components/search/DomainDiagram";
|
||||||
|
|
||||||
const {Text} = Typography;
|
const {Text} = Typography;
|
||||||
|
|
||||||
@@ -68,6 +69,7 @@ export default function DomainSearchPage() {
|
|||||||
}
|
}
|
||||||
</Card>
|
</Card>
|
||||||
</Badge.Ribbon>
|
</Badge.Ribbon>
|
||||||
|
<DomainDiagram domain={domain}/>
|
||||||
</Space>
|
</Space>
|
||||||
: <Empty
|
: <Empty
|
||||||
description={t`Although the domain exists in my database, it has been deleted from the WHOIS by its registrar.`}/>)
|
description={t`Although the domain exists in my database, it has been deleted from the WHOIS by its registrar.`}/>)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, {useEffect, useState} from "react";
|
import React, {useEffect, useState} from "react";
|
||||||
import {Card, Divider, Flex, Form, message} from "antd";
|
import {Card, Divider, Flex, Form, message} from "antd";
|
||||||
import {EventAction, getWatchlists, putWatchlist, postWatchlist} from "../../utils/api";
|
import {EventAction, getWatchlists, postWatchlist, putWatchlist} from "../../utils/api";
|
||||||
import {AxiosError} from "axios";
|
import {AxiosError} from "axios";
|
||||||
import {t} from 'ttag'
|
import {t} from 'ttag'
|
||||||
import {WatchlistForm} from "../../components/tracking/watchlist/WatchlistForm";
|
import {WatchlistForm} from "../../components/tracking/watchlist/WatchlistForm";
|
||||||
@@ -37,9 +37,12 @@ export default function WatchlistPage() {
|
|||||||
connector?: string,
|
connector?: string,
|
||||||
dsn?: string[]
|
dsn?: string[]
|
||||||
}) => {
|
}) => {
|
||||||
const domainsURI = values.domains.map(d => '/api/domains/' + d)
|
const domainsURI = values.domains.map(d => '/api/domains/' + d.toLowerCase())
|
||||||
let triggers = values.triggers.map(t => ({event: t, action: 'email'}))
|
let triggers = values.triggers.map(t => ({event: t, action: 'email'}))
|
||||||
if(values.dsn !== undefined) triggers = [...triggers, ...values.triggers.map(t => ({event: t, action: 'chat'}))]
|
if (values.dsn !== undefined) triggers = [...triggers, ...values.triggers.map(t => ({
|
||||||
|
event: t,
|
||||||
|
action: 'chat'
|
||||||
|
}))]
|
||||||
|
|
||||||
postWatchlist({
|
postWatchlist({
|
||||||
name: values.name,
|
name: values.name,
|
||||||
@@ -64,10 +67,12 @@ export default function WatchlistPage() {
|
|||||||
connector?: string,
|
connector?: string,
|
||||||
dsn?: string[]
|
dsn?: string[]
|
||||||
}) => {
|
}) => {
|
||||||
const domainsURI = values.domains.map(d => '/api/domains/' + d)
|
const domainsURI = values.domains.map(d => '/api/domains/' + d.toLowerCase())
|
||||||
let triggers = values.triggers.map(t => ({event: t, action: 'email'}))
|
let triggers = values.triggers.map(t => ({event: t, action: 'email'}))
|
||||||
if(values.dsn !== undefined) triggers = [...triggers, ...values.triggers.map(t => ({event: t, action: 'chat'}))]
|
if (values.dsn !== undefined) triggers = [...triggers, ...values.triggers.map(t => ({
|
||||||
|
event: t,
|
||||||
|
action: 'chat'
|
||||||
|
}))]
|
||||||
|
|
||||||
return putWatchlist({
|
return putWatchlist({
|
||||||
token: values.token,
|
token: values.token,
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ class JWTAuthenticator implements AuthenticationSuccessHandlerInterface
|
|||||||
new Cookie(
|
new Cookie(
|
||||||
'BEARER',
|
'BEARER',
|
||||||
$jwt,
|
$jwt,
|
||||||
time() + 7200, // expiration
|
time() + 604800, // expiration
|
||||||
'/',
|
'/',
|
||||||
null,
|
null,
|
||||||
true,
|
true,
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ class OAuthAuthenticator extends OAuth2Authenticator implements AuthenticationEn
|
|||||||
new Cookie(
|
new Cookie(
|
||||||
'BEARER',
|
'BEARER',
|
||||||
$token,
|
$token,
|
||||||
time() + 7200, // expiration
|
time() + 604800, // expiration
|
||||||
'/',
|
'/',
|
||||||
null,
|
null,
|
||||||
true,
|
true,
|
||||||
|
|||||||
@@ -278,6 +278,8 @@ readonly class RDAPService
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (array_key_exists('nameservers', $res) && is_array($res['nameservers'])) {
|
if (array_key_exists('nameservers', $res) && is_array($res['nameservers'])) {
|
||||||
|
$domain->getNameservers()->clear();
|
||||||
|
|
||||||
foreach ($res['nameservers'] as $rdapNameserver) {
|
foreach ($res['nameservers'] as $rdapNameserver) {
|
||||||
$nameserver = $this->nameserverRepository->findOneBy([
|
$nameserver = $this->nameserverRepository->findOneBy([
|
||||||
'ldhName' => strtolower($rdapNameserver['ldhName']),
|
'ldhName' => strtolower($rdapNameserver['ldhName']),
|
||||||
|
|||||||
@@ -246,11 +246,16 @@ msgstr "Ja"
|
|||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr "Nein"
|
msgstr "Nein"
|
||||||
|
|
||||||
#: assets/components/tracking/diagram/ViewDiagramWatchlistButton.tsx:86
|
#: assets/components/tracking/diagram/WatchlistToNodes.tsx:37
|
||||||
|
#, javascript-format
|
||||||
|
msgid ".${ tld.tld } Registry"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: assets/components/tracking/diagram/ViewDiagramWatchlistButton.tsx:40
|
||||||
msgid "View the Watchlist Entity Diagram"
|
msgid "View the Watchlist Entity Diagram"
|
||||||
msgstr "Sehen Sie sich das Watchlist-Entitätsdiagramm an"
|
msgstr "Sehen Sie sich das Watchlist-Entitätsdiagramm an"
|
||||||
|
|
||||||
#: assets/components/tracking/diagram/ViewDiagramWatchlistButton.tsx:91
|
#: assets/components/tracking/diagram/ViewDiagramWatchlistButton.tsx:45
|
||||||
msgid "Watchlist Entity Diagram"
|
msgid "Watchlist Entity Diagram"
|
||||||
msgstr "Watchlist-Entitäten Diagramm"
|
msgstr "Watchlist-Entitäten Diagramm"
|
||||||
|
|
||||||
|
|||||||
@@ -246,11 +246,16 @@ msgstr "Oui"
|
|||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr "Non"
|
msgstr "Non"
|
||||||
|
|
||||||
#: assets/components/tracking/diagram/ViewDiagramWatchlistButton.tsx:86
|
#: assets/components/tracking/diagram/WatchlistToNodes.tsx:37
|
||||||
|
#, javascript-format
|
||||||
|
msgid ".${ tld.tld } Registry"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: assets/components/tracking/diagram/ViewDiagramWatchlistButton.tsx:40
|
||||||
msgid "View the Watchlist Entity Diagram"
|
msgid "View the Watchlist Entity Diagram"
|
||||||
msgstr "Afficher le diagramme d'entités de la Watchlist"
|
msgstr "Afficher le diagramme d'entités de la Watchlist"
|
||||||
|
|
||||||
#: assets/components/tracking/diagram/ViewDiagramWatchlistButton.tsx:91
|
#: assets/components/tracking/diagram/ViewDiagramWatchlistButton.tsx:45
|
||||||
msgid "Watchlist Entity Diagram"
|
msgid "Watchlist Entity Diagram"
|
||||||
msgstr "Diagramme d'entités de la Watchlist"
|
msgstr "Diagramme d'entités de la Watchlist"
|
||||||
|
|
||||||
|
|||||||
@@ -236,14 +236,6 @@ msgstr ""
|
|||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/components/tracking/diagram/ViewDiagramWatchlistButton.tsx:86
|
|
||||||
msgid "View the Watchlist Entity Diagram"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assets/components/tracking/diagram/ViewDiagramWatchlistButton.tsx:91
|
|
||||||
msgid "Watchlist Entity Diagram"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assets/components/tracking/watchlist/WatchlistForm.tsx:66
|
#: assets/components/tracking/watchlist/WatchlistForm.tsx:66
|
||||||
msgid "Name"
|
msgid "Name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -329,6 +321,23 @@ msgstr ""
|
|||||||
msgid "Cancel"
|
msgid "Cancel"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: assets/components/tracking/watchlist/diagram/ViewDiagramWatchlistButton.tsx:40
|
||||||
|
msgid "View the Watchlist Entity Diagram"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: assets/components/tracking/watchlist/diagram/ViewDiagramWatchlistButton.tsx:45
|
||||||
|
msgid "Watchlist Entity Diagram"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: assets/components/tracking/watchlist/diagram/watchlistToEdges.tsx:39
|
||||||
|
msgid "Registry"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: assets/components/tracking/watchlist/diagram/watchlistToNodes.tsx:32
|
||||||
|
#, javascript-format
|
||||||
|
msgid ".${ tld.tld } Registry"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: assets/components/tracking/watchlist/DeleteWatchlistButton.tsx:12
|
#: assets/components/tracking/watchlist/DeleteWatchlistButton.tsx:12
|
||||||
#: assets/components/tracking/watchlist/DeleteWatchlistButton.tsx:19
|
#: assets/components/tracking/watchlist/DeleteWatchlistButton.tsx:19
|
||||||
msgid "Delete the Watchlist"
|
msgid "Delete the Watchlist"
|
||||||
@@ -427,27 +436,27 @@ msgstr ""
|
|||||||
msgid "Register"
|
msgid "Register"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/pages/search/DomainSearchPage.tsx:21
|
#: assets/pages/search/DomainSearchPage.tsx:22
|
||||||
msgid "Found !"
|
msgid "Found !"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/pages/search/DomainSearchPage.tsx:29
|
#: assets/pages/search/DomainSearchPage.tsx:30
|
||||||
msgid "Domain finder"
|
msgid "Domain finder"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/pages/search/DomainSearchPage.tsx:50
|
#: assets/pages/search/DomainSearchPage.tsx:51
|
||||||
msgid "EPP Status Codes"
|
msgid "EPP Status Codes"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/pages/search/DomainSearchPage.tsx:60
|
#: assets/pages/search/DomainSearchPage.tsx:61
|
||||||
msgid "Timeline"
|
msgid "Timeline"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/pages/search/DomainSearchPage.tsx:65
|
#: assets/pages/search/DomainSearchPage.tsx:66
|
||||||
msgid "Entities"
|
msgid "Entities"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/pages/search/DomainSearchPage.tsx:73
|
#: assets/pages/search/DomainSearchPage.tsx:75
|
||||||
msgid ""
|
msgid ""
|
||||||
"Although the domain exists in my database, it has been deleted from the "
|
"Although the domain exists in my database, it has been deleted from the "
|
||||||
"WHOIS by its registrar."
|
"WHOIS by its registrar."
|
||||||
|
|||||||
Reference in New Issue
Block a user