diff --git a/core/src/main/java/google/registry/rdap/RdapJsonFormatter.java b/core/src/main/java/google/registry/rdap/RdapJsonFormatter.java index 60d0a04cd..7b0426025 100644 --- a/core/src/main/java/google/registry/rdap/RdapJsonFormatter.java +++ b/core/src/main/java/google/registry/rdap/RdapJsonFormatter.java @@ -31,18 +31,21 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSetMultimap; import com.google.common.collect.Maps; import com.google.common.collect.Ordering; +import com.google.common.collect.Sets; import com.google.common.collect.Streams; import com.google.common.flogger.FluentLogger; import com.google.common.net.InetAddresses; import com.google.gson.JsonArray; import google.registry.config.RegistryConfig.Config; import google.registry.model.EppResource; +import google.registry.model.adapters.EnumToAttributeAdapter.EppEnum; import google.registry.model.contact.Contact; import google.registry.model.contact.ContactPhoneNumber; import google.registry.model.contact.PostalInfo; import google.registry.model.domain.DesignatedContact; import google.registry.model.domain.DesignatedContact.Type; import google.registry.model.domain.Domain; +import google.registry.model.domain.rgp.GracePeriodStatus; import google.registry.model.eppcommon.Address; import google.registry.model.eppcommon.StatusValue; import google.registry.model.host.Host; @@ -175,10 +178,8 @@ public class RdapJsonFormatter { + " repoId = '%repoIdValue%' and type is not null group by type)"; /** Map of EPP status values to the RDAP equivalents. */ - private static final ImmutableMap STATUS_TO_RDAP_STATUS_MAP = - new ImmutableMap.Builder() - // RdapStatus.ADD_PERIOD not defined in our system - // RdapStatus.AUTO_RENEW_PERIOD not defined in our system + private static final ImmutableMap STATUS_TO_RDAP_STATUS_MAP = + new ImmutableMap.Builder() .put(StatusValue.CLIENT_DELETE_PROHIBITED, RdapStatus.CLIENT_DELETE_PROHIBITED) .put(StatusValue.CLIENT_HOLD, RdapStatus.CLIENT_HOLD) .put(StatusValue.CLIENT_RENEW_PROHIBITED, RdapStatus.CLIENT_RENEW_PROHIBITED) @@ -190,17 +191,21 @@ public class RdapJsonFormatter { .put(StatusValue.PENDING_CREATE, RdapStatus.PENDING_CREATE) .put(StatusValue.PENDING_DELETE, RdapStatus.PENDING_DELETE) // RdapStatus.PENDING_RENEW not defined in our system - // RdapStatus.PENDING_RESTORE not defined in our system .put(StatusValue.PENDING_TRANSFER, RdapStatus.PENDING_TRANSFER) .put(StatusValue.PENDING_UPDATE, RdapStatus.PENDING_UPDATE) - // RdapStatus.REDEMPTION_PERIOD not defined in our system - // RdapStatus.RENEW_PERIOD not defined in our system .put(StatusValue.SERVER_DELETE_PROHIBITED, RdapStatus.SERVER_DELETE_PROHIBITED) .put(StatusValue.SERVER_HOLD, RdapStatus.SERVER_HOLD) .put(StatusValue.SERVER_RENEW_PROHIBITED, RdapStatus.SERVER_RENEW_PROHIBITED) .put(StatusValue.SERVER_TRANSFER_PROHIBITED, RdapStatus.SERVER_TRANSFER_PROHIBITED) .put(StatusValue.SERVER_UPDATE_PROHIBITED, RdapStatus.SERVER_UPDATE_PROHIBITED) - // RdapStatus.TRANSFER_PERIOD not defined in our system + .put(GracePeriodStatus.ADD, RdapStatus.ADD_PERIOD) + .put(GracePeriodStatus.AUTO_RENEW, RdapStatus.AUTO_RENEW_PERIOD) + .put(GracePeriodStatus.REDEMPTION, RdapStatus.REDEMPTION_PERIOD) + .put(GracePeriodStatus.RENEW, RdapStatus.RENEW_PERIOD) + .put(GracePeriodStatus.PENDING_DELETE, RdapStatus.PENDING_DELETE) + // In practice, PENDING_RESTORE is unused. We just perform the restore immediately + .put(GracePeriodStatus.PENDING_RESTORE, RdapStatus.PENDING_RESTORE) + .put(GracePeriodStatus.TRANSFER, RdapStatus.TRANSFER_PERIOD) .build(); /** @@ -348,9 +353,11 @@ public class RdapJsonFormatter { } // 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". + Set allStatusValues = + Sets.union(domain.getStatusValues(), domain.getGracePeriodStatuses()); ImmutableSet status = makeStatusValueList( - domain.getStatusValues(), + allStatusValues, false, // isRedacted domain.getDeletionTime().isBefore(getRequestTime())); builder.statusBuilder().addAll(status); @@ -1045,7 +1052,7 @@ public class RdapJsonFormatter { * redacted objects. */ private static ImmutableSet makeStatusValueList( - ImmutableSet statusValues, boolean isRedacted, boolean isDeleted) { + Set statusValues, boolean isRedacted, boolean isDeleted) { Stream stream = statusValues.stream() .map(status -> STATUS_TO_RDAP_STATUS_MAP.getOrDefault(status, RdapStatus.OBSCURED)); diff --git a/core/src/main/java/google/registry/rdap/RdapObjectClasses.java b/core/src/main/java/google/registry/rdap/RdapObjectClasses.java index cd3d7350e..6936f61dc 100644 --- a/core/src/main/java/google/registry/rdap/RdapObjectClasses.java +++ b/core/src/main/java/google/registry/rdap/RdapObjectClasses.java @@ -51,7 +51,7 @@ final class RdapObjectClasses { */ @RestrictJsonNames({}) @AutoValue - abstract static class Vcard implements Jsonable { + public abstract static class Vcard implements Jsonable { abstract String property(); abstract ImmutableMap> parameters(); abstract String valueType(); @@ -94,7 +94,7 @@ final class RdapObjectClasses { @RestrictJsonNames("vcardArray") @AutoValue - abstract static class VcardArray implements Jsonable { + public abstract static class VcardArray implements Jsonable { private static final String VCARD_VERSION_NUMBER = "4.0"; private static final Vcard VCARD_ENTRY_VERSION = @@ -148,7 +148,7 @@ final class RdapObjectClasses { * *

All Actions need to return an object of this type. */ - abstract static class ReplyPayloadBase extends AbstractJsonableObject { + public abstract static class ReplyPayloadBase extends AbstractJsonableObject { final BoilerplateType boilerplateType; ReplyPayloadBase(BoilerplateType boilerplateType) { @@ -165,7 +165,7 @@ final class RdapObjectClasses { */ @AutoValue @RestrictJsonNames({}) - abstract static class TopLevelReplyObject extends AbstractJsonableObject { + public abstract static class TopLevelReplyObject extends AbstractJsonableObject { @JsonableElement("rdapConformance") static final RdapConformance RDAP_CONFORMANCE = RdapConformance.INSTANCE; @@ -257,7 +257,7 @@ final class RdapObjectClasses { *

We're missing the "autnums" and "networks" fields */ @RestrictJsonNames({"entities[]", "entitySearchResults[]"}) - abstract static class RdapEntity extends RdapObjectBase { + public abstract static class RdapEntity extends RdapObjectBase { /** Role values specified in RFC 9083 ยง 10.2.4. */ @RestrictJsonNames("roles[]") @@ -311,7 +311,7 @@ final class RdapObjectClasses { * for each one for type safety. */ @AutoValue - abstract static class RdapRegistrarEntity extends RdapEntity { + public abstract static class RdapRegistrarEntity extends RdapEntity { static Builder builder() { return new AutoValue_RdapObjectClasses_RdapRegistrarEntity.Builder(); @@ -330,7 +330,7 @@ final class RdapObjectClasses { * for each one for type safety. */ @AutoValue - abstract static class RdapContactEntity extends RdapEntity { + public abstract static class RdapContactEntity extends RdapEntity { static Builder builder() { return new AutoValue_RdapObjectClasses_RdapContactEntity.Builder(); @@ -387,7 +387,7 @@ final class RdapObjectClasses { /** The Nameserver Object Class defined in 5.2 of RFC 9083. */ @RestrictJsonNames({"nameservers[]", "nameserverSearchResults[]"}) @AutoValue - abstract static class RdapNameserver extends RdapNamedObjectBase { + public abstract static class RdapNameserver extends RdapNamedObjectBase { @JsonableElement Optional ipAddresses() { if (ipv6().isEmpty() && ipv4().isEmpty()) { @@ -429,7 +429,7 @@ final class RdapObjectClasses { /** Object defined in RFC 9083 section 5.3, only used for RdapDomain. */ @RestrictJsonNames("secureDNS") @AutoValue - abstract static class SecureDns extends AbstractJsonableObject { + public abstract static class SecureDns extends AbstractJsonableObject { @RestrictJsonNames("dsData[]") @AutoValue abstract static class DsData extends AbstractJsonableObject { @@ -507,7 +507,7 @@ final class RdapObjectClasses { */ @RestrictJsonNames("domainSearchResults[]") @AutoValue - abstract static class RdapDomain extends RdapNamedObjectBase { + public abstract static class RdapDomain extends RdapNamedObjectBase { @JsonableElement abstract ImmutableList nameservers(); @@ -535,7 +535,7 @@ final class RdapObjectClasses { /** Error Response Body defined in 6 of RFC 9083. */ @RestrictJsonNames({}) @AutoValue - abstract static class ErrorResponse extends ReplyPayloadBase { + public abstract static class ErrorResponse extends ReplyPayloadBase { @JsonableElement final LanguageIdentifier lang = LanguageIdentifier.EN; @@ -561,7 +561,7 @@ final class RdapObjectClasses { */ @RestrictJsonNames({}) @AutoValue - abstract static class HelpResponse extends ReplyPayloadBase { + public abstract static class HelpResponse extends ReplyPayloadBase { @JsonableElement("notices[]") abstract Optional helpNotice(); HelpResponse() { diff --git a/core/src/test/java/google/registry/rdap/RdapActionBaseTestCase.java b/core/src/test/java/google/registry/rdap/RdapActionBaseTestCase.java index 72d896ba6..b36095718 100644 --- a/core/src/test/java/google/registry/rdap/RdapActionBaseTestCase.java +++ b/core/src/test/java/google/registry/rdap/RdapActionBaseTestCase.java @@ -42,9 +42,11 @@ import org.junit.jupiter.api.extension.RegisterExtension; /** Common unit test code for actions inheriting {@link RdapActionBase}. */ abstract class RdapActionBaseTestCase { + protected final FakeClock clock = new FakeClock(DateTime.parse("2000-01-01TZ")); + @RegisterExtension final JpaIntegrationTestExtension jpa = - new JpaTestExtensions.Builder().buildIntegrationTestExtension(); + new JpaTestExtensions.Builder().withClock(clock).buildIntegrationTestExtension(); protected static final AuthResult AUTH_RESULT = AuthResult.createUser( @@ -61,7 +63,6 @@ abstract class RdapActionBaseTestCase { .build()); protected FakeResponse response = new FakeResponse(); - protected final FakeClock clock = new FakeClock(DateTime.parse("2000-01-01TZ")); final RdapMetrics rdapMetrics = mock(RdapMetrics.class); RdapAuthorization.Role metricRole = PUBLIC; diff --git a/core/src/test/java/google/registry/rdap/RdapDomainActionTest.java b/core/src/test/java/google/registry/rdap/RdapDomainActionTest.java index 7ad0f350f..957713ff2 100644 --- a/core/src/test/java/google/registry/rdap/RdapDomainActionTest.java +++ b/core/src/test/java/google/registry/rdap/RdapDomainActionTest.java @@ -17,6 +17,8 @@ package google.registry.rdap; import static com.google.common.truth.Truth.assertThat; import static google.registry.model.EppResourceUtils.loadByForeignKey; import static google.registry.testing.DatabaseHelper.createTld; +import static google.registry.testing.DatabaseHelper.persistActiveDomain; +import static google.registry.testing.DatabaseHelper.persistDomainWithDependentResources; import static google.registry.testing.DatabaseHelper.persistResource; import static google.registry.testing.DatabaseHelper.persistSimpleResources; import static google.registry.testing.FullFieldsTestEntityHelper.makeAndPersistHost; @@ -31,7 +33,10 @@ import com.google.common.collect.ImmutableSet; import com.google.gson.JsonObject; import google.registry.model.contact.Contact; import google.registry.model.domain.Domain; +import google.registry.model.domain.GracePeriod; import google.registry.model.domain.Period; +import google.registry.model.domain.rgp.GracePeriodStatus; +import google.registry.model.eppcommon.StatusValue; import google.registry.model.host.Host; import google.registry.model.registrar.Registrar; import google.registry.model.reporting.HistoryEntry; @@ -43,6 +48,7 @@ import google.registry.rdap.RdapSearchResults.IncompletenessWarningType; import google.registry.request.Action; import google.registry.testing.FullFieldsTestEntityHelper; import java.util.Optional; +import org.joda.time.DateTime; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -59,6 +65,9 @@ class RdapDomainActionTest extends RdapActionBaseTestCase { super(RdapDomainAction.class); } + private Contact registrantLol; + private Host host1; + @BeforeEach void beforeEach() { // lol @@ -66,7 +75,7 @@ class RdapDomainActionTest extends RdapActionBaseTestCase { Registrar registrarLol = persistResource(makeRegistrar( "evilregistrar", "Yes Virginia