diff --git a/docs/flows.md b/docs/flows.md index 71a78c2fa..34ebda932 100644 --- a/docs/flows.md +++ b/docs/flows.md @@ -956,6 +956,7 @@ the domain to convert to a normal create and be billed for accordingly. is not free. * Admin contact is required. * Technical contact is required. + * Registrant is required. * 2004 * The specified status value cannot be set by clients. * The fees passed in the transform command do not match the fees that will diff --git a/java/google/registry/flows/domain/DomainUpdateFlow.java b/java/google/registry/flows/domain/DomainUpdateFlow.java index 70feded16..39270021e 100644 --- a/java/google/registry/flows/domain/DomainUpdateFlow.java +++ b/java/google/registry/flows/domain/DomainUpdateFlow.java @@ -59,6 +59,7 @@ import google.registry.flows.custom.DomainUpdateFlowCustomLogic; import google.registry.flows.custom.DomainUpdateFlowCustomLogic.AfterValidationParameters; import google.registry.flows.custom.DomainUpdateFlowCustomLogic.BeforeSaveParameters; import google.registry.flows.custom.EntityChanges; +import google.registry.flows.domain.DomainFlowUtils.MissingRegistrantException; import google.registry.model.ImmutableObject; import google.registry.model.billing.BillingEvent; import google.registry.model.billing.BillingEvent.Reason; @@ -117,6 +118,7 @@ import org.joda.time.DateTime; * @error {@link DomainFlowUtils.MissingAdminContactException} * @error {@link DomainFlowUtils.MissingContactTypeException} * @error {@link DomainFlowUtils.MissingTechnicalContactException} + * @error {@link DomainFlowUtils.MissingRegistrantException} * @error {@link DomainFlowUtils.NameserversNotAllowedForTldException} * @error {@link DomainFlowUtils.NameserversNotSpecifiedForTldWithNameserverWhitelistException} * @error {@link DomainFlowUtils.NameserversNotAllowedForDomainException} @@ -258,6 +260,7 @@ public final class DomainUpdateFlow implements TransactionalFlow { checkSameValuesNotAddedAndRemoved(add.getContacts(), remove.getContacts()); checkSameValuesNotAddedAndRemoved(add.getStatusValues(), remove.getStatusValues()); Change change = command.getInnerChange(); + validateRegistrantIsntBeingRemoved(change); Optional secDnsUpdate = eppInput.getSingleExtension(SecDnsUpdateExtension.class); DomainResource.Builder domainBuilder = @@ -330,6 +333,12 @@ public final class DomainUpdateFlow implements TransactionalFlow { .build(); } + private void validateRegistrantIsntBeingRemoved(Change change) throws EppException { + if (change.getRegistrantContactId() != null && change.getRegistrantContactId().isEmpty()) { + throw new MissingRegistrantException(); + } + } + private void validateNewState(DomainResource newDomain) throws EppException { validateNoDuplicateContacts(newDomain.getContacts()); validateRequiredContactsPresent(newDomain.getRegistrant(), newDomain.getContacts()); diff --git a/java/google/registry/model/domain/DomainCommand.java b/java/google/registry/model/domain/DomainCommand.java index 181ded544..47632377d 100644 --- a/java/google/registry/model/domain/DomainCommand.java +++ b/java/google/registry/model/domain/DomainCommand.java @@ -27,6 +27,7 @@ import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy; import static google.registry.util.CollectionUtils.union; import com.google.common.base.MoreObjects; +import com.google.common.base.Strings; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.googlecode.objectify.Key; @@ -387,7 +388,7 @@ public class DomainCommand { /** Creates a copy of this {@link Change} with hard links to hosts and contacts. */ Change cloneAndLinkReferences(DateTime now) throws InvalidReferencesException { Change clone = clone(this); - clone.registrant = clone.registrantContactId == null + clone.registrant = Strings.isNullOrEmpty(clone.registrantContactId) ? null : getOnlyElement( loadByForeignKeys( diff --git a/javatests/google/registry/flows/domain/DomainUpdateFlowTest.java b/javatests/google/registry/flows/domain/DomainUpdateFlowTest.java index d072e1bc2..3d649b38c 100644 --- a/javatests/google/registry/flows/domain/DomainUpdateFlowTest.java +++ b/javatests/google/registry/flows/domain/DomainUpdateFlowTest.java @@ -63,6 +63,7 @@ import google.registry.flows.domain.DomainFlowUtils.LinkedResourcesDoNotExistExc import google.registry.flows.domain.DomainFlowUtils.MaxSigLifeChangeNotSupportedException; import google.registry.flows.domain.DomainFlowUtils.MissingAdminContactException; import google.registry.flows.domain.DomainFlowUtils.MissingContactTypeException; +import google.registry.flows.domain.DomainFlowUtils.MissingRegistrantException; import google.registry.flows.domain.DomainFlowUtils.MissingTechnicalContactException; import google.registry.flows.domain.DomainFlowUtils.NameserversNotAllowedForDomainException; import google.registry.flows.domain.DomainFlowUtils.NameserversNotAllowedForTldException; @@ -185,6 +186,16 @@ public class DomainUpdateFlowTest extends ResourceFlowTestCase + + + + example.tld + + + ns2.example.foo + + mak21 + Payment overdue. + + + + ns1.example.foo + + sh8013 + + + + + + 2BARfoo + + + + + ABC-12345 + +