mirror of
https://github.com/google/nomulus.git
synced 2025-05-14 00:17:20 +02:00
Link the Registrar's RDAP server from RDAP domain replies
To do this we add a field of "rdapServers" in the Registrar object. Currently, we can only set this field manually, but a subsequent CL will add a cron-job to read these values from the ICANN servers. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=252438618
This commit is contained in:
parent
7c64992c73
commit
4110cae814
14 changed files with 186 additions and 30 deletions
|
@ -242,6 +242,9 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
|
|||
/** Host name of WHOIS server. */
|
||||
String whoisServer;
|
||||
|
||||
/** Base URLs for the registrar's RDAP servers. */
|
||||
Set<String> rdapBaseUrls;
|
||||
|
||||
/**
|
||||
* Whether registration of premium names should be blocked over EPP. If this is set to true, then
|
||||
* the only way to register premium names is with the superuser flag.
|
||||
|
@ -526,6 +529,10 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
|
|||
return firstNonNull(whoisServer, getDefaultRegistrarWhoisServer());
|
||||
}
|
||||
|
||||
public ImmutableSet<String> getRdapBaseUrls() {
|
||||
return nullToEmptyImmutableSortedCopy(rdapBaseUrls);
|
||||
}
|
||||
|
||||
public boolean getBlockPremiumNames() {
|
||||
return blockPremiumNames;
|
||||
}
|
||||
|
@ -603,6 +610,7 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
|
|||
.put("faxNumber", faxNumber)
|
||||
.put("emailAddress", emailAddress)
|
||||
.put("whoisServer", getWhoisServer())
|
||||
.putListOfStrings("rdapBaseUrls", getRdapBaseUrls())
|
||||
.put("blockPremiumNames", blockPremiumNames)
|
||||
.put("url", url)
|
||||
.put("icannReferralEmail", getIcannReferralEmail())
|
||||
|
@ -837,6 +845,11 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder setRdapBaseUrls(Set<String> rdapBaseUrls) {
|
||||
getInstance().rdapBaseUrls = ImmutableSet.copyOf(rdapBaseUrls);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setBlockPremiumNames(boolean blockPremiumNames) {
|
||||
getInstance().blockPremiumNames = blockPremiumNames;
|
||||
return this;
|
||||
|
@ -908,9 +921,24 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable
|
|||
ofy().load().type(Registrar.class).parent(getCrossTldKey()).id(clientId).now());
|
||||
}
|
||||
|
||||
/** Loads and returns a registrar entity by its client id using an in-memory cache. */
|
||||
/**
|
||||
* Loads and returns a registrar entity by its client id using an in-memory cache.
|
||||
*
|
||||
* <p>Returns empty if the registrar isn't found.
|
||||
*/
|
||||
public static Optional<Registrar> loadByClientIdCached(String clientId) {
|
||||
checkArgument(!Strings.isNullOrEmpty(clientId), "clientId must be specified");
|
||||
return Optional.ofNullable(CACHE_BY_CLIENT_ID.get().get(clientId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads and returns a registrar entity by its client id using an in-memory cache.
|
||||
*
|
||||
* <p>Throws if the registrar isn't found.
|
||||
*/
|
||||
public static Registrar loadRequiredRegistrarCached(String clientId) {
|
||||
Optional<Registrar> registrar = loadByClientIdCached(clientId);
|
||||
checkArgument(registrar.isPresent(), "couldn't find registrar '%s'", clientId);
|
||||
return registrar.get();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,7 +66,6 @@ import google.registry.rdap.RdapObjectClasses.SecureDns;
|
|||
import google.registry.rdap.RdapObjectClasses.Vcard;
|
||||
import google.registry.rdap.RdapObjectClasses.VcardArray;
|
||||
import google.registry.request.FullServletPath;
|
||||
import google.registry.request.HttpException.InternalServerErrorException;
|
||||
import google.registry.util.Clock;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
|
@ -301,11 +300,25 @@ public class RdapJsonFormatter {
|
|||
// The domain object in the RDAP response MUST contain an entity with the Registrar role.
|
||||
//
|
||||
// See {@link createRdapRegistrarEntity} for details of section 2.4 conformance
|
||||
builder
|
||||
.entitiesBuilder()
|
||||
.add(
|
||||
createRdapRegistrarEntity(
|
||||
domainBase.getCurrentSponsorClientId(), OutputDataType.INTERNAL));
|
||||
Registrar registrar =
|
||||
Registrar.loadRequiredRegistrarCached(domainBase.getCurrentSponsorClientId());
|
||||
builder.entitiesBuilder().add(createRdapRegistrarEntity(registrar, OutputDataType.INTERNAL));
|
||||
// RDAP Technical Implementation Guide 3.2: must have link to the registrar's RDAP URL for this
|
||||
// domain, with rel=related.
|
||||
for (String registrarRdapBase : registrar.getRdapBaseUrls()) {
|
||||
String href =
|
||||
makeServerRelativeUrl(
|
||||
registrarRdapBase, "domain", domainBase.getFullyQualifiedDomainName());
|
||||
builder
|
||||
.linksBuilder()
|
||||
.add(
|
||||
Link.builder()
|
||||
.setHref(href)
|
||||
.setValue(href)
|
||||
.setRel("related")
|
||||
.setType("application/rdap+json")
|
||||
.build());
|
||||
}
|
||||
// RDAP Response Profile 2.6.1: must have at least one status member
|
||||
// makeStatusValueList should in theory always contain one of either "active" or "inactive".
|
||||
ImmutableSet<RdapStatus> status =
|
||||
|
@ -443,11 +456,9 @@ public class RdapJsonFormatter {
|
|||
|
||||
// RDAP Response Profile 4.3 - Registrar member is optional, so we only set it for FULL
|
||||
if (outputDataType == OutputDataType.FULL) {
|
||||
builder
|
||||
.entitiesBuilder()
|
||||
.add(
|
||||
createRdapRegistrarEntity(
|
||||
hostResource.getPersistedCurrentSponsorClientId(), OutputDataType.INTERNAL));
|
||||
Registrar registrar =
|
||||
Registrar.loadRequiredRegistrarCached(hostResource.getPersistedCurrentSponsorClientId());
|
||||
builder.entitiesBuilder().add(createRdapRegistrarEntity(registrar, OutputDataType.INTERNAL));
|
||||
}
|
||||
if (outputDataType != OutputDataType.INTERNAL) {
|
||||
// Rdap Response Profile 4.4, must have "last update of RDAP database" response. But this is
|
||||
|
@ -747,21 +758,6 @@ public class RdapJsonFormatter {
|
|||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JSON object for the desired registrar to an existing list of JSON objects.
|
||||
*
|
||||
* @param clientId the registrar client ID
|
||||
* @param outputDataType whether to generate FULL, SUMMARY, or INTERNAL data.
|
||||
*/
|
||||
RdapRegistrarEntity createRdapRegistrarEntity(String clientId, OutputDataType outputDataType) {
|
||||
Optional<Registrar> registrar = Registrar.loadByClientIdCached(clientId);
|
||||
if (!registrar.isPresent()) {
|
||||
throw new InternalServerErrorException(
|
||||
String.format("Couldn't find registrar '%s'", clientId));
|
||||
}
|
||||
return createRdapRegistrarEntity(registrar.get(), outputDataType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JSON object for a {@link RegistrarContact}.
|
||||
*
|
||||
|
@ -1059,11 +1055,18 @@ public class RdapJsonFormatter {
|
|||
* Create a link relative to the RDAP server endpoint.
|
||||
*/
|
||||
String makeRdapServletRelativeUrl(String part, String... moreParts) {
|
||||
return makeServerRelativeUrl(fullServletPath, part, moreParts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a link relative to some base server
|
||||
*/
|
||||
static String makeServerRelativeUrl(String baseServer, String part, String... moreParts) {
|
||||
String relativePath = Paths.get(part, moreParts).toString();
|
||||
if (fullServletPath.endsWith("/")) {
|
||||
return fullServletPath + relativePath;
|
||||
if (baseServer.endsWith("/")) {
|
||||
return baseServer + relativePath;
|
||||
}
|
||||
return fullServletPath + "/" + relativePath;
|
||||
return baseServer + "/" + relativePath;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -254,6 +254,11 @@ abstract class CreateOrUpdateRegistrarCommand extends MutatingCommand {
|
|||
description = "Hostname of registrar WHOIS server. (Default: whois.nic.google)")
|
||||
String whoisServer;
|
||||
|
||||
@Parameter(
|
||||
names = "--rdap_servers",
|
||||
description = "Comma-delimited list of RDAP servers. An empty argument clears the list")
|
||||
List<String> rdapServers = new ArrayList<>();
|
||||
|
||||
/** Returns the existing registrar (for update) or null (for creates). */
|
||||
@Nullable
|
||||
abstract Registrar getOldRegistrar(String clientId);
|
||||
|
@ -389,6 +394,15 @@ abstract class CreateOrUpdateRegistrarCommand extends MutatingCommand {
|
|||
Optional.ofNullable(icannReferralEmail).ifPresent(builder::setIcannReferralEmail);
|
||||
Optional.ofNullable(whoisServer).ifPresent(builder::setWhoisServer);
|
||||
|
||||
if (!rdapServers.isEmpty()) {
|
||||
// If we only have empty strings, then remove all the RDAP servers
|
||||
// This is to differentiate between "I didn't set the rdapServers because I don't want to
|
||||
// change them" and "I set the RDAP servers to an empty string because I want no RDAP
|
||||
// servers".
|
||||
builder.setRdapBaseUrls(
|
||||
rdapServers.stream().filter(server -> !server.isEmpty()).collect(toImmutableSet()));
|
||||
}
|
||||
|
||||
// If the registrarName is being set, verify that it is either null or it normalizes uniquely.
|
||||
String oldRegistrarName = (oldRegistrar == null) ? null : oldRegistrar.getRegistrarName();
|
||||
if (registrarName != null && !registrarName.equals(oldRegistrarName)) {
|
||||
|
|
|
@ -436,6 +436,7 @@ class google.registry.model.registrar.Registrar {
|
|||
java.util.List<google.registry.util.CidrAddressBlock> ipAddressWhitelist;
|
||||
java.util.Map<org.joda.money.CurrencyUnit, google.registry.model.registrar.Registrar$BillingAccountEntry> billingAccountMap;
|
||||
java.util.Set<java.lang.String> allowedTlds;
|
||||
java.util.Set<java.lang.String> rdapBaseUrls;
|
||||
org.joda.time.DateTime lastCertificateUpdateTime;
|
||||
}
|
||||
class google.registry.model.registrar.Registrar$BillingAccountEntry {
|
||||
|
|
|
@ -19,6 +19,18 @@
|
|||
"type": "application/rdap+json",
|
||||
"rel": "self",
|
||||
"value": "https://example.tld/rdap/domain/%DOMAIN_PUNYCODE_NAME_1%"
|
||||
},
|
||||
{
|
||||
"href": "https://rdap.example.com/withSlash/domain/%DOMAIN_PUNYCODE_NAME_1%",
|
||||
"type": "application/rdap+json",
|
||||
"rel": "related",
|
||||
"value": "https://rdap.example.com/withSlash/domain/%DOMAIN_PUNYCODE_NAME_1%"
|
||||
},
|
||||
{
|
||||
"href": "https://rdap.example.com/withoutSlash/domain/%DOMAIN_PUNYCODE_NAME_1%",
|
||||
"type": "application/rdap+json",
|
||||
"rel": "related",
|
||||
"value": "https://rdap.example.com/withoutSlash/domain/%DOMAIN_PUNYCODE_NAME_1%"
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
|
|
|
@ -19,6 +19,18 @@
|
|||
"type": "application/rdap+json",
|
||||
"rel": "self",
|
||||
"value": "https://example.tld/rdap/domain/%DOMAIN_PUNYCODE_NAME_1%"
|
||||
},
|
||||
{
|
||||
"href": "https://rdap.example.com/withSlash/domain/%DOMAIN_PUNYCODE_NAME_1%",
|
||||
"type": "application/rdap+json",
|
||||
"rel": "related",
|
||||
"value": "https://rdap.example.com/withSlash/domain/%DOMAIN_PUNYCODE_NAME_1%"
|
||||
},
|
||||
{
|
||||
"href": "https://rdap.example.com/withoutSlash/domain/%DOMAIN_PUNYCODE_NAME_1%",
|
||||
"type": "application/rdap+json",
|
||||
"rel": "related",
|
||||
"value": "https://rdap.example.com/withoutSlash/domain/%DOMAIN_PUNYCODE_NAME_1%"
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
|
|
|
@ -20,6 +20,18 @@
|
|||
"type": "application/rdap+json",
|
||||
"rel": "self",
|
||||
"value": "https://example.tld/rdap/domain/%DOMAIN_PUNYCODE_NAME_1%"
|
||||
},
|
||||
{
|
||||
"href": "https://rdap.example.com/withSlash/domain/%DOMAIN_PUNYCODE_NAME_1%",
|
||||
"type": "application/rdap+json",
|
||||
"rel": "related",
|
||||
"value": "https://rdap.example.com/withSlash/domain/%DOMAIN_PUNYCODE_NAME_1%"
|
||||
},
|
||||
{
|
||||
"href": "https://rdap.example.com/withoutSlash/domain/%DOMAIN_PUNYCODE_NAME_1%",
|
||||
"type": "application/rdap+json",
|
||||
"rel": "related",
|
||||
"value": "https://rdap.example.com/withoutSlash/domain/%DOMAIN_PUNYCODE_NAME_1%"
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
|
|
|
@ -19,6 +19,18 @@
|
|||
"type": "application/rdap+json",
|
||||
"rel": "self",
|
||||
"value": "https://example.tld/rdap/domain/%DOMAIN_PUNYCODE_NAME_1%"
|
||||
},
|
||||
{
|
||||
"href": "https://rdap.example.com/withSlash/domain/%DOMAIN_PUNYCODE_NAME_1%",
|
||||
"type": "application/rdap+json",
|
||||
"rel": "related",
|
||||
"value": "https://rdap.example.com/withSlash/domain/%DOMAIN_PUNYCODE_NAME_1%"
|
||||
},
|
||||
{
|
||||
"href": "https://rdap.example.com/withoutSlash/domain/%DOMAIN_PUNYCODE_NAME_1%",
|
||||
"type": "application/rdap+json",
|
||||
"rel": "related",
|
||||
"value": "https://rdap.example.com/withoutSlash/domain/%DOMAIN_PUNYCODE_NAME_1%"
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
|
|
|
@ -20,6 +20,18 @@
|
|||
"type": "application/rdap+json",
|
||||
"rel": "self",
|
||||
"value": "https://example.tld/rdap/domain/%DOMAIN_PUNYCODE_NAME_1%"
|
||||
},
|
||||
{
|
||||
"href": "https://rdap.example.com/withSlash/domain/%DOMAIN_PUNYCODE_NAME_1%",
|
||||
"type": "application/rdap+json",
|
||||
"rel": "related",
|
||||
"value": "https://rdap.example.com/withSlash/domain/%DOMAIN_PUNYCODE_NAME_1%"
|
||||
},
|
||||
{
|
||||
"href": "https://rdap.example.com/withoutSlash/domain/%DOMAIN_PUNYCODE_NAME_1%",
|
||||
"type": "application/rdap+json",
|
||||
"rel": "related",
|
||||
"value": "https://rdap.example.com/withoutSlash/domain/%DOMAIN_PUNYCODE_NAME_1%"
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
|
|
|
@ -20,6 +20,18 @@
|
|||
"type": "application/rdap+json",
|
||||
"rel": "self",
|
||||
"value": "https://example.tld/rdap/domain/%DOMAIN_PUNYCODE_NAME_1%"
|
||||
},
|
||||
{
|
||||
"href": "https://rdap.example.com/withSlash/domain/%DOMAIN_PUNYCODE_NAME_1%",
|
||||
"type": "application/rdap+json",
|
||||
"rel": "related",
|
||||
"value": "https://rdap.example.com/withSlash/domain/%DOMAIN_PUNYCODE_NAME_1%"
|
||||
},
|
||||
{
|
||||
"href": "https://rdap.example.com/withoutSlash/domain/%DOMAIN_PUNYCODE_NAME_1%",
|
||||
"type": "application/rdap+json",
|
||||
"rel": "related",
|
||||
"value": "https://rdap.example.com/withoutSlash/domain/%DOMAIN_PUNYCODE_NAME_1%"
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
|
|
|
@ -17,6 +17,18 @@
|
|||
"rel" : "self",
|
||||
"href" : "https://example.tld/rdap/domain/cat.xn--q9jyb4c",
|
||||
"type" : "application/rdap+json"
|
||||
},
|
||||
{
|
||||
"value" : "https://rdap.example.com/withSlash/domain/cat.xn--q9jyb4c",
|
||||
"rel" : "related",
|
||||
"href" : "https://rdap.example.com/withSlash/domain/cat.xn--q9jyb4c",
|
||||
"type" : "application/rdap+json"
|
||||
},
|
||||
{
|
||||
"value" : "https://rdap.example.com/withoutSlash/domain/cat.xn--q9jyb4c",
|
||||
"rel" : "related",
|
||||
"href" : "https://rdap.example.com/withoutSlash/domain/cat.xn--q9jyb4c",
|
||||
"type" : "application/rdap+json"
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
|
|
|
@ -17,6 +17,18 @@
|
|||
"rel": "self",
|
||||
"href": "https://example.tld/rdap/domain/cat.xn--q9jyb4c",
|
||||
"type": "application/rdap+json"
|
||||
},
|
||||
{
|
||||
"href": "https://rdap.example.com/withSlash/domain/cat.xn--q9jyb4c",
|
||||
"type": "application/rdap+json",
|
||||
"rel": "related",
|
||||
"value": "https://rdap.example.com/withSlash/domain/cat.xn--q9jyb4c"
|
||||
},
|
||||
{
|
||||
"href": "https://rdap.example.com/withoutSlash/domain/cat.xn--q9jyb4c",
|
||||
"type": "application/rdap+json",
|
||||
"rel": "related",
|
||||
"value": "https://rdap.example.com/withoutSlash/domain/cat.xn--q9jyb4c"
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
|
|
|
@ -18,6 +18,18 @@
|
|||
"rel": "self",
|
||||
"href": "https://example.tld/rdap/domain/fish.xn--q9jyb4c",
|
||||
"type": "application/rdap+json"
|
||||
},
|
||||
{
|
||||
"href": "https://rdap.example.com/withSlash/domain/fish.xn--q9jyb4c",
|
||||
"type": "application/rdap+json",
|
||||
"rel": "related",
|
||||
"value": "https://rdap.example.com/withSlash/domain/fish.xn--q9jyb4c"
|
||||
},
|
||||
{
|
||||
"href": "https://rdap.example.com/withoutSlash/domain/fish.xn--q9jyb4c",
|
||||
"type": "application/rdap+json",
|
||||
"rel": "related",
|
||||
"value": "https://rdap.example.com/withoutSlash/domain/fish.xn--q9jyb4c"
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
|
|
|
@ -80,6 +80,8 @@ public final class FullFieldsTestEntityHelper {
|
|||
.setFaxNumber("+1.2125551213")
|
||||
.setEmailAddress("contact-us@example.com")
|
||||
.setWhoisServer("whois.example.com")
|
||||
.setRdapBaseUrls(ImmutableSet.of(
|
||||
"https://rdap.example.com/withSlash/", "https://rdap.example.com/withoutSlash"))
|
||||
.setUrl("http://my.fake.url")
|
||||
.build();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue