diff --git a/java/google/registry/rdap/RdapIcannStandardInformation.java b/java/google/registry/rdap/RdapIcannStandardInformation.java index 976487b60..ba246193f 100644 --- a/java/google/registry/rdap/RdapIcannStandardInformation.java +++ b/java/google/registry/rdap/RdapIcannStandardInformation.java @@ -133,13 +133,27 @@ public class RdapIcannStandardInformation { "type", "object truncated due to unexplainable reasons"); - /** Included when requester is not logged in as the owner of the contact being returned. */ + /** + * Included when requester is not logged in as the owner of the contact being returned. Format + * required by ICANN RDAP Pilot Profile draft section 1.4.11. + */ static final ImmutableMap CONTACT_PERSONAL_DATA_HIDDEN_DATA_REMARK = ImmutableMap.of( "title", - "Contact Personal Data Hidden", + "Data Policy", "description", - ImmutableList.of("Contact personal data is visible only to the owning registrar."), + ImmutableList.of( + "Some of the data in this object has been removed.", + "Contact personal data is visible only to the owning registrar."), "type", - "object truncated due to unexplainable reasons"); + "object truncated due to authorization", + "links", + ImmutableList.of( + ImmutableMap.of( + "value", + "https://github.com/google/nomulus/blob/master/docs/rdap.md#authentication", + "rel", "alternate", + "href", + "https://github.com/google/nomulus/blob/master/docs/rdap.md#authentication", + "type", "text/html"))); } diff --git a/java/google/registry/rdap/RdapJsonFormatter.java b/java/google/registry/rdap/RdapJsonFormatter.java index 707e73656..5350980db 100644 --- a/java/google/registry/rdap/RdapJsonFormatter.java +++ b/java/google/registry/rdap/RdapJsonFormatter.java @@ -272,8 +272,8 @@ public class RdapJsonFormatter { private static final ImmutableList STATUS_LIST_ACTIVE = ImmutableList.of(RdapStatus.ACTIVE.rfc7483String); - private static final ImmutableList STATUS_LIST_REMOVED = - ImmutableList.of(RdapStatus.REMOVED.rfc7483String); + private static final ImmutableList STATUS_LIST_INACTIVE = + ImmutableList.of(RdapStatus.INACTIVE.rfc7483String); private static final ImmutableMap> PHONE_TYPE_VOICE = ImmutableMap.of("type", ImmutableList.of("voice")); private static final ImmutableMap> PHONE_TYPE_FAX = @@ -496,7 +496,9 @@ public class RdapJsonFormatter { jsonBuilder.put( "status", makeStatusValueList( - domainResource.getStatusValues(), domainResource.getDeletionTime().isBefore(now))); + domainResource.getStatusValues(), + false, // isRedacted + domainResource.getDeletionTime().isBefore(now))); jsonBuilder.put("links", ImmutableList.of( makeLink("domain", domainResource.getFullyQualifiedDomainName(), linkBase))); boolean displayContacts = @@ -612,7 +614,10 @@ public class RdapJsonFormatter { } jsonBuilder.put( "status", - makeStatusValueList(statuses.build(), hostResource.getDeletionTime().isBefore(now))); + makeStatusValueList( + statuses.build(), + false, // isRedacted + hostResource.getDeletionTime().isBefore(now))); jsonBuilder.put("links", ImmutableList.of( makeLink("nameserver", hostResource.getFullyQualifiedHostName(), linkBase))); List> remarks; @@ -691,6 +696,8 @@ public class RdapJsonFormatter { DateTime now, OutputDataType outputDataType, RdapAuthorization authorization) { + boolean isAuthorized = + authorization.isAuthorizedForClientId(contactResource.getCurrentSponsorClientId()); ImmutableMap.Builder jsonBuilder = new ImmutableMap.Builder<>(); ImmutableList.Builder> remarksBuilder = new ImmutableList.Builder<>(); @@ -702,13 +709,14 @@ public class RdapJsonFormatter { isLinked(Key.create(contactResource), now) ? union(contactResource.getStatusValues(), StatusValue.LINKED) : contactResource.getStatusValues(), + !isAuthorized, contactResource.getDeletionTime().isBefore(now))); contactType.ifPresent( type -> jsonBuilder.put("roles", ImmutableList.of(convertContactTypeToRdapRole(type)))); jsonBuilder.put("links", ImmutableList.of(makeLink("entity", contactResource.getRepoId(), linkBase))); // If we are logged in as the owner of this contact, create the vCard. - if (authorization.isAuthorizedForClientId(contactResource.getCurrentSponsorClientId())) { + if (isAuthorized) { ImmutableList.Builder vcardBuilder = new ImmutableList.Builder<>(); vcardBuilder.add(VCARD_ENTRY_VERSION); PostalInfo postalInfo = contactResource.getInternationalizedPostalInfo(); @@ -794,7 +802,7 @@ public class RdapJsonFormatter { jsonBuilder.put("objectClassName", "entity"); Long ianaIdentifier = registrar.getIanaIdentifier(); jsonBuilder.put("handle", (ianaIdentifier == null) ? "(none)" : ianaIdentifier.toString()); - jsonBuilder.put("status", registrar.isLive() ? STATUS_LIST_ACTIVE : STATUS_LIST_REMOVED); + jsonBuilder.put("status", registrar.isLive() ? STATUS_LIST_ACTIVE : STATUS_LIST_INACTIVE); jsonBuilder.put("roles", ImmutableList.of(RdapEntityRole.REGISTRAR.rfc7483String)); if (ianaIdentifier != null) { jsonBuilder.put("links", @@ -1086,20 +1094,24 @@ public class RdapJsonFormatter { /** * Creates a string array of status values. * - *

The spec indicates that OK should be listed as "active". We use the "removed" status to - * indicate deleted objects. + *

The spec indicates that OK should be listed as "active". We use the "inactive" status to + * indicate deleted objects, and as directed by the profile, the "removed" status to indicate + * redacted objects. */ private static ImmutableList makeStatusValueList( - ImmutableSet statusValues, boolean isDeleted) { + ImmutableSet statusValues, boolean isRedacted, boolean isDeleted) { Stream stream = statusValues .stream() .map(status -> statusToRdapStatusMap.getOrDefault(status, RdapStatus.OBSCURED)); + if (isRedacted) { + stream = Streams.concat(stream, Stream.of(RdapStatus.REMOVED)); + } if (isDeleted) { stream = Streams.concat( stream.filter(rdapStatus -> !Objects.equals(rdapStatus, RdapStatus.ACTIVE)), - Stream.of(RdapStatus.REMOVED)); + Stream.of(RdapStatus.INACTIVE)); } return stream .map(RdapStatus::getDisplayName) diff --git a/javatests/google/registry/rdap/RdapEntityActionTest.java b/javatests/google/registry/rdap/RdapEntityActionTest.java index eebdcc8f7..82c7273bf 100644 --- a/javatests/google/registry/rdap/RdapEntityActionTest.java +++ b/javatests/google/registry/rdap/RdapEntityActionTest.java @@ -409,7 +409,7 @@ public class RdapEntityActionTest { runSuccessfulTest( deletedContact.getRepoId(), "", - "removed", + "inactive", "", false, "rdap_contact_deleted.json"); @@ -422,7 +422,7 @@ public class RdapEntityActionTest { runSuccessfulTest( deletedContact.getRepoId(), "", - "removed", + "inactive", "", false, "rdap_contact_deleted.json"); @@ -471,7 +471,7 @@ public class RdapEntityActionTest { login("deletedregistrar"); action.includeDeletedParam = Optional.of(true); runSuccessfulTest( - "104", "Yes Virginia