mirror of
https://github.com/google/nomulus.git
synced 2025-05-15 00:47:11 +02:00
Conform to RDAP Response Profile 15feb19
This is only about the Response Profile, not the Technical Implementation guide. The Response Profile can be found at https://www.icann.org/en/system/files/files/rdap-response-profile-15feb19-en.pdf ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=250277559
This commit is contained in:
parent
b34a828b71
commit
c79e0ea670
89 changed files with 4102 additions and 5815 deletions
|
@ -32,6 +32,8 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
|||
@XmlType(name = "dsData")
|
||||
public class DelegationSignerData extends ImmutableObject {
|
||||
|
||||
private DelegationSignerData() {}
|
||||
|
||||
/** The identifier for this particular key in the domain. */
|
||||
int keyTag;
|
||||
|
||||
|
@ -74,6 +76,10 @@ public class DelegationSignerData extends ImmutableObject {
|
|||
return digest;
|
||||
}
|
||||
|
||||
public String getDigestAsString() {
|
||||
return digest == null ? "" : DatatypeConverter.printHexBinary(digest);
|
||||
}
|
||||
|
||||
public static DelegationSignerData create(
|
||||
int keyTag, int algorithm, int digestType, byte[] digest) {
|
||||
DelegationSignerData instance = new DelegationSignerData();
|
||||
|
@ -84,6 +90,11 @@ public class DelegationSignerData extends ImmutableObject {
|
|||
return instance;
|
||||
}
|
||||
|
||||
public static DelegationSignerData create(
|
||||
int keyTag, int algorithm, int digestType, String digestAsHex) {
|
||||
return create(keyTag, algorithm, digestType, DatatypeConverter.parseHexBinary(digestAsHex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the presentation format of this DS record.
|
||||
*
|
||||
|
|
|
@ -14,6 +14,7 @@ java_library(
|
|||
"//java/google/registry/request",
|
||||
"//java/google/registry/request/auth",
|
||||
"//java/google/registry/util",
|
||||
"//third_party/jaxb",
|
||||
"//third_party/objectify:objectify-v4_1",
|
||||
"@com_google_auto_value",
|
||||
"@com_google_code_findbugs_jsr305",
|
||||
|
|
|
@ -162,8 +162,10 @@ public abstract class RdapActionBase implements Runnable {
|
|||
setPayload(replyObject);
|
||||
metricInformationBuilder.setStatusCode(SC_OK);
|
||||
} catch (HttpException e) {
|
||||
logger.atInfo().withCause(e).log("Error in RDAP");
|
||||
setError(e.getResponseCode(), e.getResponseCodeString(), e.getMessage());
|
||||
} catch (URISyntaxException | IllegalArgumentException e) {
|
||||
logger.atInfo().withCause(e).log("Bad request in RDAP");
|
||||
setError(SC_BAD_REQUEST, "Bad Request", "Not a valid " + getHumanReadableObjectTypeName());
|
||||
} catch (RuntimeException e) {
|
||||
setError(SC_INTERNAL_SERVER_ERROR, "Internal Server Error", "An error was encountered");
|
||||
|
@ -240,18 +242,17 @@ public abstract class RdapActionBase implements Runnable {
|
|||
*/
|
||||
boolean isAuthorized(EppResource eppResource) {
|
||||
return getRequestTime().isBefore(eppResource.getDeletionTime())
|
||||
|| (shouldIncludeDeleted()
|
||||
&& rdapAuthorization
|
||||
.isAuthorizedForClientId(eppResource.getPersistedCurrentSponsorClientId()));
|
||||
|| (shouldIncludeDeleted()
|
||||
&& rdapAuthorization.isAuthorizedForClientId(
|
||||
eppResource.getPersistedCurrentSponsorClientId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the EPP resource should be visible.
|
||||
*
|
||||
* <p>This is true iff:
|
||||
* 1. The resource is not deleted, or the request wants to see deleted items, and is authorized to
|
||||
* do so, and:
|
||||
* 2. The request did not specify a registrar to filter on, or the registrar matches.
|
||||
* <p>This is true iff: 1. The resource is not deleted, or the request wants to see deleted items,
|
||||
* and is authorized to do so, and: 2. The request did not specify a registrar to filter on, or
|
||||
* the registrar matches.
|
||||
*/
|
||||
boolean shouldBeVisible(EppResource eppResource) {
|
||||
return isAuthorized(eppResource)
|
||||
|
@ -262,10 +263,9 @@ public abstract class RdapActionBase implements Runnable {
|
|||
/**
|
||||
* Returns true if the EPP resource should be visible.
|
||||
*
|
||||
* <p>This is true iff:
|
||||
* 1. The passed in resource exists and is not deleted (deleted ones will have been projected
|
||||
* forward in time to empty),
|
||||
* 2. The request did not specify a registrar to filter on, or the registrar matches.
|
||||
* <p>This is true iff: 1. The passed in resource exists and is not deleted (deleted ones will
|
||||
* have been projected forward in time to empty), 2. The request did not specify a registrar to
|
||||
* filter on, or the registrar matches.
|
||||
*/
|
||||
boolean shouldBeVisible(Optional<? extends EppResource> eppResource) {
|
||||
return eppResource.isPresent() && shouldBeVisible(eppResource.get());
|
||||
|
@ -463,19 +463,19 @@ public abstract class RdapActionBase implements Runnable {
|
|||
* Runs the given query, and checks for permissioning if necessary.
|
||||
*
|
||||
* @param query an already-defined query to be run; a filter on currentSponsorClientId will be
|
||||
* added if appropriate
|
||||
* added if appropriate
|
||||
* @param checkForVisibility true if the results should be checked to make sure they are visible;
|
||||
* normally this should be equal to the shouldIncludeDeleted setting, but in cases where
|
||||
* the query could not check deletion status (due to Datastore limitations such as the
|
||||
* limit of one field queried for inequality, for instance), it may need to be set to true
|
||||
* even when not including deleted records
|
||||
* normally this should be equal to the shouldIncludeDeleted setting, but in cases where the
|
||||
* query could not check deletion status (due to Datastore limitations such as the limit of
|
||||
* one field queried for inequality, for instance), it may need to be set to true even when
|
||||
* not including deleted records
|
||||
* @param querySizeLimit the maximum number of items the query is expected to return, usually
|
||||
* because the limit has been set
|
||||
* @return an {@link RdapResultSet} object containing the list of
|
||||
* resources and an incompleteness warning flag, which is set to MIGHT_BE_INCOMPLETE iff
|
||||
* any resources were excluded due to lack of visibility, and the resulting list of
|
||||
* resources is less than the maximum allowable, and the number of items returned by the
|
||||
* query is greater than or equal to the maximum number we might have expected
|
||||
* because the limit has been set
|
||||
* @return an {@link RdapResultSet} object containing the list of resources and an incompleteness
|
||||
* warning flag, which is set to MIGHT_BE_INCOMPLETE iff any resources were excluded due to
|
||||
* lack of visibility, and the resulting list of resources is less than the maximum allowable,
|
||||
* and the number of items returned by the query is greater than or equal to the maximum
|
||||
* number we might have expected
|
||||
*/
|
||||
<T extends EppResource> RdapResultSet<T> getMatchingResources(
|
||||
Query<T> query, boolean checkForVisibility, int querySizeLimit) {
|
||||
|
|
|
@ -43,9 +43,7 @@ final class RdapDataStructures {
|
|||
public JsonArray toJson() {
|
||||
JsonArray jsonArray = new JsonArray();
|
||||
// Conformance to RFC7483
|
||||
// TODO(b/127490882) check if we need to Add back the rdap_level_0 string, as I think that
|
||||
// just means we conform to the RFC, which we do
|
||||
// jsonArray.add("rdap_level_0");
|
||||
jsonArray.add("rdap_level_0");
|
||||
|
||||
// Conformance to the RDAP Response Profile V2.1
|
||||
// (see section 1.3)
|
||||
|
|
|
@ -65,8 +65,6 @@ public class RdapDomainAction extends RdapActionBase {
|
|||
if (!shouldBeVisible(domainBase)) {
|
||||
throw new NotFoundException(pathSearchString + " not found");
|
||||
}
|
||||
return rdapJsonFormatter.makeRdapJsonForDomain(
|
||||
domainBase.get(),
|
||||
OutputDataType.FULL);
|
||||
return rdapJsonFormatter.createRdapDomain(domainBase.get(), OutputDataType.FULL);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -122,8 +122,9 @@ public class RdapDomainSearchAction extends RdapSearchActionBase {
|
|||
if (!LDH_PATTERN.matcher(nsLdhNameParam.get()).matches()) {
|
||||
throw new BadRequestException("Invalid value of nsLdhName parameter");
|
||||
}
|
||||
results = searchByNameserverLdhName(
|
||||
recordWildcardType(RdapSearchPattern.create(nsLdhNameParam.get(), true)));
|
||||
results =
|
||||
searchByNameserverLdhName(
|
||||
recordWildcardType(RdapSearchPattern.create(nsLdhNameParam.get(), true)));
|
||||
} else {
|
||||
metricInformationBuilder.setSearchType(SearchType.BY_NAMESERVER_ADDRESS);
|
||||
metricInformationBuilder.setWildcardType(WildcardType.NO_WILDCARD);
|
||||
|
@ -182,9 +183,7 @@ public class RdapDomainSearchAction extends RdapSearchActionBase {
|
|||
return searchByDomainNameByTld(partialStringQuery.getSuffix());
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for domains by domain name without a wildcard or interest in deleted entries.
|
||||
*/
|
||||
/** Searches for domains by domain name without a wildcard or interest in deleted entries. */
|
||||
private DomainSearchResponse searchByDomainNameWithoutWildcard(
|
||||
final RdapSearchPattern partialStringQuery) {
|
||||
Optional<DomainBase> domainBase =
|
||||
|
@ -388,15 +387,14 @@ public class RdapDomainSearchAction extends RdapSearchActionBase {
|
|||
* <p>In theory, we could have any number of hosts using the same IP address. To make sure we get
|
||||
* all the associated domains, we have to retrieve all of them, and use them to look up domains.
|
||||
* This could open us up to a kind of DoS attack if huge number of hosts are defined on a single
|
||||
* IP. To avoid this, fetch only the first {@link #maxNameserversInFirstStage} nameservers. In
|
||||
* all normal circumstances, this should be orders of magnitude more than there actually are. But
|
||||
* it could result in us missing some domains.
|
||||
* IP. To avoid this, fetch only the first {@link #maxNameserversInFirstStage} nameservers. In all
|
||||
* normal circumstances, this should be orders of magnitude more than there actually are. But it
|
||||
* could result in us missing some domains.
|
||||
*
|
||||
* <p>The includeDeleted parameter does NOT cause deleted nameservers to be searched, only deleted
|
||||
* domains which used to be connected to an undeleted nameserver.
|
||||
*/
|
||||
private DomainSearchResponse searchByNameserverIp(
|
||||
final InetAddress inetAddress) {
|
||||
private DomainSearchResponse searchByNameserverIp(final InetAddress inetAddress) {
|
||||
Query<HostResource> query =
|
||||
queryItems(
|
||||
HostResource.class,
|
||||
|
@ -419,8 +417,7 @@ public class RdapDomainSearchAction extends RdapSearchActionBase {
|
|||
* <p>This method is called by {@link #searchByNameserverLdhName} and {@link
|
||||
* #searchByNameserverIp} after they assemble the relevant host keys.
|
||||
*/
|
||||
private DomainSearchResponse searchByNameserverRefs(
|
||||
final Iterable<Key<HostResource>> hostKeys) {
|
||||
private DomainSearchResponse searchByNameserverRefs(final Iterable<Key<HostResource>> hostKeys) {
|
||||
// We must break the query up into chunks, because the in operator is limited to 30 subqueries.
|
||||
// Since it is possible for the same domain to show up more than once in our result list (if
|
||||
// we do a wildcard nameserver search that returns multiple nameservers used by the same
|
||||
|
@ -459,8 +456,8 @@ public class RdapDomainSearchAction extends RdapSearchActionBase {
|
|||
return makeSearchResults(
|
||||
domains,
|
||||
(numHostKeysSearched >= maxNameserversInFirstStage)
|
||||
? IncompletenessWarningType.MIGHT_BE_INCOMPLETE
|
||||
: IncompletenessWarningType.COMPLETE,
|
||||
? IncompletenessWarningType.MIGHT_BE_INCOMPLETE
|
||||
: IncompletenessWarningType.COMPLETE,
|
||||
(numHostKeysSearched > 0) ? Optional.of((long) domains.size()) : Optional.empty());
|
||||
}
|
||||
|
||||
|
@ -471,8 +468,7 @@ public class RdapDomainSearchAction extends RdapSearchActionBase {
|
|||
}
|
||||
|
||||
/** Output JSON from data in an {@link RdapResultSet} object. */
|
||||
private DomainSearchResponse makeSearchResults(
|
||||
RdapResultSet<DomainBase> resultSet) {
|
||||
private DomainSearchResponse makeSearchResults(RdapResultSet<DomainBase> resultSet) {
|
||||
return makeSearchResults(
|
||||
resultSet.resources(),
|
||||
resultSet.incompletenessWarningType(),
|
||||
|
@ -501,7 +497,7 @@ public class RdapDomainSearchAction extends RdapSearchActionBase {
|
|||
newCursor = Optional.of(domain.getFullyQualifiedDomainName());
|
||||
builder
|
||||
.domainSearchResultsBuilder()
|
||||
.add(rdapJsonFormatter.makeRdapJsonForDomain(domain, outputDataType));
|
||||
.add(rdapJsonFormatter.createRdapDomain(domain, outputDataType));
|
||||
}
|
||||
if (rdapResultSetMaxSize < domains.size()) {
|
||||
builder.setNextPageUri(createNavigationUri(newCursor.get()));
|
||||
|
|
|
@ -19,6 +19,7 @@ import static google.registry.rdap.RdapUtils.getRegistrarByIanaIdentifier;
|
|||
import static google.registry.request.Action.Method.GET;
|
||||
import static google.registry.request.Action.Method.HEAD;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.primitives.Longs;
|
||||
import com.google.re2j.Pattern;
|
||||
import com.googlecode.objectify.Key;
|
||||
|
@ -72,10 +73,8 @@ public class RdapEntityAction extends RdapActionBase {
|
|||
// As per Andy Newton on the regext mailing list, contacts by themselves have no role, since
|
||||
// they are global, and might have different roles for different domains.
|
||||
if ((contactResource != null) && shouldBeVisible(contactResource)) {
|
||||
return rdapJsonFormatter.makeRdapJsonForContact(
|
||||
contactResource,
|
||||
Optional.empty(),
|
||||
OutputDataType.FULL);
|
||||
return rdapJsonFormatter.createRdapContactEntity(
|
||||
contactResource, ImmutableSet.of(), OutputDataType.FULL);
|
||||
}
|
||||
}
|
||||
Long ianaIdentifier = Longs.tryParse(pathSearchString);
|
||||
|
@ -83,8 +82,7 @@ public class RdapEntityAction extends RdapActionBase {
|
|||
wasValidKey = true;
|
||||
Optional<Registrar> registrar = getRegistrarByIanaIdentifier(ianaIdentifier);
|
||||
if (registrar.isPresent() && shouldBeVisible(registrar.get())) {
|
||||
return rdapJsonFormatter.makeRdapJsonForRegistrar(
|
||||
registrar.get(), OutputDataType.FULL);
|
||||
return rdapJsonFormatter.createRdapRegistrarEntity(registrar.get(), OutputDataType.FULL);
|
||||
}
|
||||
}
|
||||
// At this point, we have failed to find either a contact or a registrar.
|
||||
|
|
|
@ -21,6 +21,7 @@ import static google.registry.request.Action.Method.GET;
|
|||
import static google.registry.request.Action.Method.HEAD;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.common.primitives.Booleans;
|
||||
|
@ -380,10 +381,7 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
|
|||
shouldIncludeDeleted(),
|
||||
querySizeLimit);
|
||||
}
|
||||
return makeSearchResults(
|
||||
contactResultSet,
|
||||
registrars,
|
||||
QueryType.HANDLE);
|
||||
return makeSearchResults(contactResultSet, registrars, QueryType.HANDLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -406,9 +404,7 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
|
|||
* properties of the {@link RdapResultSet} structure and passes them as separate arguments.
|
||||
*/
|
||||
private EntitySearchResponse makeSearchResults(
|
||||
RdapResultSet<ContactResource> resultSet,
|
||||
List<Registrar> registrars,
|
||||
QueryType queryType) {
|
||||
RdapResultSet<ContactResource> resultSet, List<Registrar> registrars, QueryType queryType) {
|
||||
return makeSearchResults(
|
||||
resultSet.resources(),
|
||||
resultSet.incompletenessWarningType(),
|
||||
|
@ -424,10 +420,10 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
|
|||
*
|
||||
* @param contacts the list of contacts which can be returned
|
||||
* @param incompletenessWarningType MIGHT_BE_INCOMPLETE if the list of contacts might be
|
||||
* incomplete; this only matters if the total count of contacts and registrars combined is
|
||||
* less than a full result set's worth
|
||||
* incomplete; this only matters if the total count of contacts and registrars combined is
|
||||
* less than a full result set's worth
|
||||
* @param numContactsRetrieved the number of contacts retrieved in the process of generating the
|
||||
* results
|
||||
* results
|
||||
* @param registrars the list of registrars which can be returned
|
||||
* @param queryType whether the query was by full name or by handle
|
||||
* @return an {@link RdapSearchResults} object
|
||||
|
@ -460,10 +456,11 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
|
|||
for (ContactResource contact : Iterables.limit(contacts, rdapResultSetMaxSize)) {
|
||||
// As per Andy Newton on the regext mailing list, contacts by themselves have no role, since
|
||||
// they are global, and might have different roles for different domains.
|
||||
builder.entitySearchResultsBuilder().add(rdapJsonFormatter.makeRdapJsonForContact(
|
||||
contact,
|
||||
Optional.empty(),
|
||||
outputDataType));
|
||||
builder
|
||||
.entitySearchResultsBuilder()
|
||||
.add(
|
||||
rdapJsonFormatter.createRdapContactEntity(
|
||||
contact, ImmutableSet.of(), outputDataType));
|
||||
newCursor =
|
||||
Optional.of(
|
||||
CONTACT_CURSOR_PREFIX
|
||||
|
@ -476,9 +473,7 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
|
|||
Iterables.limit(registrars, rdapResultSetMaxSize - contacts.size())) {
|
||||
builder
|
||||
.entitySearchResultsBuilder()
|
||||
.add(
|
||||
rdapJsonFormatter.makeRdapJsonForRegistrar(
|
||||
registrar, outputDataType));
|
||||
.add(rdapJsonFormatter.createRdapRegistrarEntity(registrar, outputDataType));
|
||||
newCursor = Optional.of(REGISTRAR_CURSOR_PREFIX + registrar.getRegistrarName());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,11 +51,12 @@ public class RdapIcannStandardInformation {
|
|||
.build())
|
||||
.build();
|
||||
|
||||
/** Required by ICANN RDAP Profile section 1.5.20. */
|
||||
/** Required by ICANN RDAP Response Profile section 2.11. */
|
||||
private static final Notice INACCURACY_COMPLAINT_FORM_NOTICE =
|
||||
Notice.builder()
|
||||
.setTitle("RDDS Inaccuracy Complaint Form")
|
||||
.setDescription(
|
||||
"URL of the ICANN Whois Inaccuracy Complaint Form: https://www.icann.org/wicf")
|
||||
"URL of the ICANN RDDS Inaccuracy Complaint Form: https://www.icann.org/wicf")
|
||||
.addLink(
|
||||
Link.builder()
|
||||
.setValue("https://www.icann.org/wicf")
|
||||
|
@ -71,6 +72,7 @@ public class RdapIcannStandardInformation {
|
|||
CONFORMANCE_NOTICE,
|
||||
// RDAP Response Profile 2.6.3
|
||||
DOMAIN_STATUS_CODES_NOTICE,
|
||||
// RDAP Response Profile 2.11
|
||||
INACCURACY_COMPLAINT_FORM_NOTICE);
|
||||
|
||||
/** Boilerplate remarks required by nameserver and entity responses. */
|
||||
|
@ -125,21 +127,14 @@ public class RdapIcannStandardInformation {
|
|||
static final ImmutableList<Notice> POSSIBLY_INCOMPLETE_NOTICES =
|
||||
ImmutableList.of(POSSIBLY_INCOMPLETE_RESULT_SET_NOTICE);
|
||||
|
||||
/** Included when the requester is not logged in as the owner of the domain being returned. */
|
||||
static final Remark DOMAIN_CONTACTS_HIDDEN_DATA_REMARK =
|
||||
Remark.builder()
|
||||
.setTitle("Contacts Hidden")
|
||||
.setDescription("Domain contacts are visible only to the owning registrar.")
|
||||
.setType(Remark.Type.OBJECT_TRUNCATED_UNEXPLAINABLE)
|
||||
.build();
|
||||
|
||||
/**
|
||||
* Included when requester is not logged in as the owner of the contact being returned. Format
|
||||
* required by ICANN RDAP Response Profile 15feb19 section 2.7.4.3.
|
||||
* Included when requester is not logged in as the owner of the contact being returned.
|
||||
*
|
||||
* <p>Format required by ICANN RDAP Response Profile 15feb19 section 2.7.4.3.
|
||||
*/
|
||||
static final Remark CONTACT_PERSONAL_DATA_HIDDEN_DATA_REMARK =
|
||||
Remark.builder()
|
||||
.setTitle("Redacted for Privacy")
|
||||
.setTitle("REDACTED FOR PRIVACY")
|
||||
.setDescription(
|
||||
"Some of the data in this object has been removed.",
|
||||
"Contact personal data is visible only to the owning registrar.")
|
||||
|
@ -154,4 +149,30 @@ public class RdapIcannStandardInformation {
|
|||
.setType("text/html")
|
||||
.build())
|
||||
.build();
|
||||
|
||||
/**
|
||||
* String that replaces GDPR redacted values.
|
||||
*
|
||||
* <p>GTLD Registration Data Temp Spec 17may18, Appendix A, 2.2: Fields required to be "redacted"
|
||||
* MUST privide in the value section text similar to "REDACTED FOR PRIVACY"
|
||||
*/
|
||||
static final String CONTACT_REDACTED_VALUE = "REDACTED FOR PRIVACY";
|
||||
|
||||
/**
|
||||
* Included in ALL contact responses, even if the user is authorized.
|
||||
*
|
||||
* <p>Format required by ICANN RDAP Response Profile 15feb19 section 2.7.5.3.
|
||||
*
|
||||
* <p>NOTE that unlike other redacted fields, there's no allowance to give the email to authorized
|
||||
* users or allow for registrar consent.
|
||||
*/
|
||||
static final Remark CONTACT_EMAIL_REDACTED_FOR_DOMAIN =
|
||||
Remark.builder()
|
||||
.setTitle("EMAIL REDACTED FOR PRIVACY")
|
||||
.setDescription(
|
||||
"Please query the RDDS service of the Registrar of Record identifies in this output"
|
||||
+ " for information on how to contact the Registrant of the queried domain"
|
||||
+ " name.")
|
||||
.setType(Remark.Type.OBJECT_REDACTED_AUTHORIZATION)
|
||||
.build();
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -67,6 +67,6 @@ public class RdapNameserverAction extends RdapActionBase {
|
|||
if (!shouldBeVisible(hostResource)) {
|
||||
throw new NotFoundException(pathSearchString + " not found");
|
||||
}
|
||||
return rdapJsonFormatter.makeRdapJsonForHost(hostResource.get(), OutputDataType.FULL);
|
||||
return rdapJsonFormatter.createRdapNameserver(hostResource.get(), OutputDataType.FULL);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -167,10 +167,9 @@ public class RdapNameserverSearchAction extends RdapSearchActionBase {
|
|||
NameserverSearchResponse.Builder builder =
|
||||
NameserverSearchResponse.builder()
|
||||
.setIncompletenessWarningType(IncompletenessWarningType.COMPLETE);
|
||||
builder.nameserverSearchResultsBuilder().add(
|
||||
rdapJsonFormatter.makeRdapJsonForHost(
|
||||
hostResource.get(),
|
||||
OutputDataType.FULL));
|
||||
builder
|
||||
.nameserverSearchResultsBuilder()
|
||||
.add(rdapJsonFormatter.createRdapNameserver(hostResource.get(), OutputDataType.FULL));
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
|
@ -230,8 +229,7 @@ public class RdapNameserverSearchAction extends RdapSearchActionBase {
|
|||
getDeletedItemHandling(),
|
||||
querySizeLimit);
|
||||
return makeSearchResults(
|
||||
getMatchingResources(query, shouldIncludeDeleted(), querySizeLimit),
|
||||
CursorType.NAME);
|
||||
getMatchingResources(query, shouldIncludeDeleted(), querySizeLimit), CursorType.NAME);
|
||||
}
|
||||
|
||||
/** Searches for nameservers by IP address, returning a JSON array of nameserver info maps. */
|
||||
|
@ -248,8 +246,7 @@ public class RdapNameserverSearchAction extends RdapSearchActionBase {
|
|||
getDeletedItemHandling(),
|
||||
querySizeLimit);
|
||||
return makeSearchResults(
|
||||
getMatchingResources(query, shouldIncludeDeleted(), querySizeLimit),
|
||||
CursorType.ADDRESS);
|
||||
getMatchingResources(query, shouldIncludeDeleted(), querySizeLimit), CursorType.ADDRESS);
|
||||
}
|
||||
|
||||
/** Output JSON for a lists of hosts contained in an {@link RdapResultSet}. */
|
||||
|
@ -282,7 +279,7 @@ public class RdapNameserverSearchAction extends RdapSearchActionBase {
|
|||
: host.getRepoId());
|
||||
builder
|
||||
.nameserverSearchResultsBuilder()
|
||||
.add(rdapJsonFormatter.makeRdapJsonForHost(host, outputDataType));
|
||||
.add(rdapJsonFormatter.createRdapNameserver(host, outputDataType));
|
||||
}
|
||||
if (rdapResultSetMaxSize < hosts.size()) {
|
||||
builder.setNextPageUri(createNavigationUri(newCursor.get()));
|
||||
|
|
|
@ -25,6 +25,7 @@ import com.google.gson.Gson;
|
|||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import google.registry.model.domain.secdns.DelegationSignerData;
|
||||
import google.registry.rdap.AbstractJsonableObject.RestrictJsonNames;
|
||||
import google.registry.rdap.RdapDataStructures.Event;
|
||||
import google.registry.rdap.RdapDataStructures.EventWithoutActor;
|
||||
|
@ -149,7 +150,6 @@ final class RdapObjectClasses {
|
|||
*
|
||||
* All Actions need to return an object of this type.
|
||||
*/
|
||||
@RestrictJsonNames("*")
|
||||
abstract static class ReplyPayloadBase extends AbstractJsonableObject {
|
||||
final BoilerplateType boilerplateType;
|
||||
|
||||
|
@ -207,6 +207,18 @@ final class RdapObjectClasses {
|
|||
@JsonableElement abstract ImmutableList<Link> links();
|
||||
@JsonableElement abstract ImmutableList<Event> events();
|
||||
|
||||
/**
|
||||
* Required event for all response objects, but not for internal objects.
|
||||
*
|
||||
* <p>Meaning it's required in, e.g., an RdapNameserver object that is a response to a
|
||||
* Nameserver query, but not to an RdapNameserver that's part of an RdapDomain response to a
|
||||
* Domain query.
|
||||
*
|
||||
* <p>RDAP Response Profile 2.3.1.3, 3.3, 4.4
|
||||
*/
|
||||
@JsonableElement("events[]")
|
||||
abstract Optional<Event> lastUpdateOfRdapDatabaseEvent();
|
||||
|
||||
/**
|
||||
* WHOIS server displayed in RDAP query responses.
|
||||
*
|
||||
|
@ -232,16 +244,20 @@ final class RdapObjectClasses {
|
|||
abstract ImmutableList.Builder<Link> linksBuilder();
|
||||
abstract B setPort43(Port43WhoisServer port43);
|
||||
abstract ImmutableList.Builder<Event> eventsBuilder();
|
||||
|
||||
abstract B setLastUpdateOfRdapDatabaseEvent(Event event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The Entity Object Class defined in 5.1 of RFC7483.
|
||||
*
|
||||
* <p>Entities are used both for Contacts and for Registrars. We will create different subobjects
|
||||
* for each one for type safety.
|
||||
*
|
||||
* <p>We're missing the "autnums" and "networks" fields
|
||||
*/
|
||||
@RestrictJsonNames({"entities[]", "entitySearchResults[]"})
|
||||
@AutoValue
|
||||
abstract static class RdapEntity extends RdapObjectBase {
|
||||
|
||||
/** Role values specified in RFC 7483 § 10.2.4. */
|
||||
|
@ -280,17 +296,50 @@ final class RdapObjectClasses {
|
|||
@JsonableElement abstract ImmutableSet<Role> roles();
|
||||
@JsonableElement abstract ImmutableList<EventWithoutActor> asEventActor();
|
||||
|
||||
private abstract static class Builder<B extends Builder<B>> extends RdapObjectBase.Builder<B> {
|
||||
abstract B setVcardArray(VcardArray vcardArray);
|
||||
|
||||
abstract ImmutableSet.Builder<Role> rolesBuilder();
|
||||
|
||||
abstract ImmutableList.Builder<EventWithoutActor> asEventActorBuilder();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registrar version of the Entity Object Class defined in 5.1 of RFC7483.
|
||||
*
|
||||
* <p>Entities are used both for Contacts and for Registrars. We will create different subobjects
|
||||
* for each one for type safety.
|
||||
*/
|
||||
@AutoValue
|
||||
abstract static class RdapRegistrarEntity extends RdapEntity {
|
||||
|
||||
static Builder builder() {
|
||||
return new AutoValue_RdapObjectClasses_RdapEntity.Builder();
|
||||
return new AutoValue_RdapObjectClasses_RdapRegistrarEntity.Builder();
|
||||
}
|
||||
|
||||
@AutoValue.Builder
|
||||
abstract static class Builder extends RdapObjectBase.Builder<Builder> {
|
||||
abstract Builder setVcardArray(VcardArray vcardArray);
|
||||
abstract ImmutableSet.Builder<Role> rolesBuilder();
|
||||
abstract ImmutableList.Builder<EventWithoutActor> asEventActorBuilder();
|
||||
abstract static class Builder extends RdapEntity.Builder<Builder> {
|
||||
abstract RdapRegistrarEntity build();
|
||||
}
|
||||
}
|
||||
|
||||
abstract RdapEntity build();
|
||||
/**
|
||||
* Contact version of the Entity Object Class defined in 5.1 of RFC7483.
|
||||
*
|
||||
* <p>Entities are used both for Contacts and for Registrars. We will create different subobjects
|
||||
* for each one for type safety.
|
||||
*/
|
||||
@AutoValue
|
||||
abstract static class RdapContactEntity extends RdapEntity {
|
||||
|
||||
static Builder builder() {
|
||||
return new AutoValue_RdapObjectClasses_RdapContactEntity.Builder();
|
||||
}
|
||||
|
||||
@AutoValue.Builder
|
||||
abstract static class Builder extends RdapEntity.Builder<Builder> {
|
||||
abstract RdapContactEntity build();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -301,6 +350,10 @@ final class RdapObjectClasses {
|
|||
*
|
||||
* <p>See RDAP Response Profile 15feb19 sections 2.1 and 4.1.
|
||||
*
|
||||
* <p>Note the ldhName field is only required for non-IDN names or IDN names when the query was an
|
||||
* A-label. It is optional for IDN names when the query was a U-label. Because we don't want to
|
||||
* remember the query when building the results, we always show it.
|
||||
*
|
||||
* <p>Not part of the spec, but seems convenient.
|
||||
*/
|
||||
private abstract static class RdapNamedObjectBase extends RdapObjectBase {
|
||||
|
@ -374,7 +427,80 @@ final class RdapObjectClasses {
|
|||
|
||||
abstract RdapNameserver build();
|
||||
}
|
||||
}
|
||||
|
||||
/** Object defined in RFC7483 section 5.3, only used for RdapDomain. */
|
||||
@RestrictJsonNames("secureDNS")
|
||||
@AutoValue
|
||||
abstract static class SecureDns extends AbstractJsonableObject {
|
||||
@RestrictJsonNames("dsData[]")
|
||||
@AutoValue
|
||||
abstract static class DsData extends AbstractJsonableObject {
|
||||
@JsonableElement
|
||||
abstract int keyTag();
|
||||
|
||||
@JsonableElement
|
||||
abstract int algorithm();
|
||||
|
||||
@JsonableElement
|
||||
abstract String digest();
|
||||
|
||||
@JsonableElement
|
||||
abstract int digestType();
|
||||
|
||||
static DsData create(DelegationSignerData dsData) {
|
||||
return new AutoValue_RdapObjectClasses_SecureDns_DsData(
|
||||
dsData.getKeyTag(),
|
||||
dsData.getAlgorithm(),
|
||||
dsData.getDigestAsString(),
|
||||
dsData.getDigestType());
|
||||
}
|
||||
}
|
||||
|
||||
/** true if the zone has been signed, false otherwise. */
|
||||
@JsonableElement
|
||||
abstract boolean zoneSigned();
|
||||
|
||||
/** true if there are DS records in the parent, false otherwise. */
|
||||
@JsonableElement
|
||||
boolean delegationSigned() {
|
||||
return !dsData().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* an integer representing the signature lifetime in seconds to be used when creating the RRSIG
|
||||
* DS record in the parent zone [RFC5910].
|
||||
*
|
||||
* <p>Note that although it isn't given as optional in RFC7483, in RFC5910 it's mentioned as
|
||||
* optional. Also, our code doesn't support it at all - so it's set to always be empty.
|
||||
*/
|
||||
@JsonableElement
|
||||
Optional<Integer> maxSigLife() {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@JsonableElement
|
||||
abstract ImmutableList<DsData> dsData();
|
||||
|
||||
static Builder builder() {
|
||||
return new AutoValue_RdapObjectClasses_SecureDns.Builder();
|
||||
}
|
||||
|
||||
abstract Builder toBuilder();
|
||||
|
||||
@AutoValue.Builder
|
||||
abstract static class Builder {
|
||||
abstract Builder setZoneSigned(boolean zoneSigned);
|
||||
|
||||
abstract ImmutableList.Builder<DsData> dsDataBuilder();
|
||||
|
||||
Builder addDsData(DelegationSignerData dsData) {
|
||||
dsDataBuilder().add(DsData.create(dsData));
|
||||
return this;
|
||||
}
|
||||
|
||||
abstract SecureDns build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -388,6 +514,9 @@ final class RdapObjectClasses {
|
|||
|
||||
@JsonableElement abstract ImmutableList<RdapNameserver> nameservers();
|
||||
|
||||
@JsonableElement("secureDNS")
|
||||
abstract Optional<SecureDns> secureDns();
|
||||
|
||||
RdapDomain() {
|
||||
super(BoilerplateType.DOMAIN, ObjectClassName.DOMAIN);
|
||||
}
|
||||
|
@ -400,6 +529,8 @@ final class RdapObjectClasses {
|
|||
abstract static class Builder extends RdapNamedObjectBase.Builder<Builder> {
|
||||
abstract ImmutableList.Builder<RdapNameserver> nameserversBuilder();
|
||||
|
||||
abstract Builder setSecureDns(SecureDns secureDns);
|
||||
|
||||
abstract RdapDomain build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,8 +49,7 @@ public final class RequestModule {
|
|||
private final AuthResult authResult;
|
||||
|
||||
@VisibleForTesting
|
||||
public RequestModule(
|
||||
HttpServletRequest req, HttpServletResponse rsp) {
|
||||
public RequestModule(HttpServletRequest req, HttpServletResponse rsp) {
|
||||
this(req, rsp, AuthResult.NOT_AUTHENTICATED);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue