mirror of
https://github.com/google/nomulus.git
synced 2025-06-27 06:44:51 +02:00
Replace command.applyTo() with inlined builder operations
These are much easier to understand. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=137446273
This commit is contained in:
parent
b84d7f1fb5
commit
1dbc5f6bb0
28 changed files with 489 additions and 426 deletions
|
@ -978,6 +978,7 @@ are enqueued to update DNS accordingly.
|
||||||
* Resource status prohibits this operation.
|
* Resource status prohibits this operation.
|
||||||
* Cannot remove all IP addresses from a subordinate host.
|
* Cannot remove all IP addresses from a subordinate host.
|
||||||
* 2306
|
* 2306
|
||||||
|
* Cannot add and remove the same value.
|
||||||
* Host names must be at least two levels below the public suffix.
|
* Host names must be at least two levels below the public suffix.
|
||||||
|
|
||||||
## HostInfoFlow
|
## HostInfoFlow
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
package google.registry.flows;
|
package google.registry.flows;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
|
import static com.google.common.collect.Sets.intersection;
|
||||||
import static google.registry.model.EppResourceUtils.loadByForeignKey;
|
import static google.registry.model.EppResourceUtils.loadByForeignKey;
|
||||||
import static google.registry.model.EppResourceUtils.queryDomainsUsingResource;
|
import static google.registry.model.EppResourceUtils.queryDomainsUsingResource;
|
||||||
import static google.registry.model.domain.DomainResource.extendRegistrationWithCap;
|
import static google.registry.model.domain.DomainResource.extendRegistrationWithCap;
|
||||||
|
@ -33,6 +34,8 @@ import com.googlecode.objectify.Work;
|
||||||
import google.registry.flows.EppException.AuthorizationErrorException;
|
import google.registry.flows.EppException.AuthorizationErrorException;
|
||||||
import google.registry.flows.EppException.InvalidAuthorizationInformationErrorException;
|
import google.registry.flows.EppException.InvalidAuthorizationInformationErrorException;
|
||||||
import google.registry.flows.EppException.ObjectDoesNotExistException;
|
import google.registry.flows.EppException.ObjectDoesNotExistException;
|
||||||
|
import google.registry.flows.EppException.ParameterValuePolicyErrorException;
|
||||||
|
import google.registry.flows.EppException.ParameterValueRangeErrorException;
|
||||||
import google.registry.flows.exceptions.MissingTransferRequestAuthInfoException;
|
import google.registry.flows.exceptions.MissingTransferRequestAuthInfoException;
|
||||||
import google.registry.flows.exceptions.NotPendingTransferException;
|
import google.registry.flows.exceptions.NotPendingTransferException;
|
||||||
import google.registry.flows.exceptions.NotTransferInitiatorException;
|
import google.registry.flows.exceptions.NotTransferInitiatorException;
|
||||||
|
@ -359,6 +362,25 @@ public final class ResourceFlowUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Check that the same values aren't being added and removed in an update command. */
|
||||||
|
public static void checkSameValuesNotAddedAndRemoved(
|
||||||
|
ImmutableSet<?> fieldsToAdd, ImmutableSet<?> fieldsToRemove)
|
||||||
|
throws AddRemoveSameValueException {
|
||||||
|
if (!intersection(fieldsToAdd, fieldsToRemove).isEmpty()) {
|
||||||
|
throw new AddRemoveSameValueException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check that all {@link StatusValue} objects in a set are client-settable. */
|
||||||
|
public static void verifyAllStatusesAreClientSettable(Set<StatusValue> statusValues)
|
||||||
|
throws StatusNotClientSettableException {
|
||||||
|
for (StatusValue statusValue : statusValues) {
|
||||||
|
if (!statusValue.isClientSettable()) {
|
||||||
|
throw new StatusNotClientSettableException(statusValue.getXmlName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Resource with this id does not exist. */
|
/** Resource with this id does not exist. */
|
||||||
public static class ResourceDoesNotExistException extends ObjectDoesNotExistException {
|
public static class ResourceDoesNotExistException extends ObjectDoesNotExistException {
|
||||||
public ResourceDoesNotExistException(Class<?> type, String targetId) {
|
public ResourceDoesNotExistException(Class<?> type, String targetId) {
|
||||||
|
@ -380,4 +402,18 @@ public final class ResourceFlowUtils {
|
||||||
super("Authorization information for accessing resource is invalid");
|
super("Authorization information for accessing resource is invalid");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Cannot add and remove the same value. */
|
||||||
|
public static class AddRemoveSameValueException extends ParameterValuePolicyErrorException {
|
||||||
|
public AddRemoveSameValueException() {
|
||||||
|
super("Cannot add and remove the same value");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The specified status value cannot be set by clients. */
|
||||||
|
public static class StatusNotClientSettableException extends ParameterValueRangeErrorException {
|
||||||
|
public StatusNotClientSettableException(String statusValue) {
|
||||||
|
super(String.format("Status value %s cannot be set by clients", statusValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,12 +65,18 @@ public final class ContactCreateFlow extends Flow implements TransactionalFlow {
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
Create command = (Create) resourceCommand;
|
Create command = (Create) resourceCommand;
|
||||||
verifyResourceDoesNotExist(ContactResource.class, targetId, now);
|
verifyResourceDoesNotExist(ContactResource.class, targetId, now);
|
||||||
Builder builder = new Builder();
|
ContactResource newContact = new Builder()
|
||||||
command.applyTo(builder);
|
.setContactId(targetId)
|
||||||
ContactResource newContact = builder
|
.setAuthInfo(command.getAuthInfo())
|
||||||
.setCreationClientId(clientId)
|
.setCreationClientId(clientId)
|
||||||
.setCurrentSponsorClientId(clientId)
|
.setCurrentSponsorClientId(clientId)
|
||||||
.setRepoId(createContactHostRoid(ObjectifyService.allocateId()))
|
.setRepoId(createContactHostRoid(ObjectifyService.allocateId()))
|
||||||
|
.setFaxNumber(command.getFax())
|
||||||
|
.setVoiceNumber(command.getVoice())
|
||||||
|
.setDisclose(command.getDisclose())
|
||||||
|
.setEmailAddress(command.getEmail())
|
||||||
|
.setInternationalizedPostalInfo(command.getInternationalizedPostalInfo())
|
||||||
|
.setLocalizedPostalInfo(command.getLocalizedPostalInfo())
|
||||||
.build();
|
.build();
|
||||||
validateAsciiPostalInfo(newContact.getInternationalizedPostalInfo());
|
validateAsciiPostalInfo(newContact.getInternationalizedPostalInfo());
|
||||||
validateContactAgainstPolicy(newContact);
|
validateContactAgainstPolicy(newContact);
|
||||||
|
|
|
@ -14,8 +14,11 @@
|
||||||
|
|
||||||
package google.registry.flows.contact;
|
package google.registry.flows.contact;
|
||||||
|
|
||||||
|
import static com.google.common.collect.Sets.union;
|
||||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||||
|
import static google.registry.flows.ResourceFlowUtils.checkSameValuesNotAddedAndRemoved;
|
||||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||||
|
import static google.registry.flows.ResourceFlowUtils.verifyAllStatusesAreClientSettable;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
|
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
|
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
|
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
|
||||||
|
@ -26,7 +29,6 @@ import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import com.googlecode.objectify.Key;
|
import com.googlecode.objectify.Key;
|
||||||
import google.registry.flows.EppException;
|
import google.registry.flows.EppException;
|
||||||
import google.registry.flows.ExtensionManager;
|
import google.registry.flows.ExtensionManager;
|
||||||
|
@ -34,30 +36,30 @@ import google.registry.flows.Flow;
|
||||||
import google.registry.flows.FlowModule.ClientId;
|
import google.registry.flows.FlowModule.ClientId;
|
||||||
import google.registry.flows.FlowModule.TargetId;
|
import google.registry.flows.FlowModule.TargetId;
|
||||||
import google.registry.flows.TransactionalFlow;
|
import google.registry.flows.TransactionalFlow;
|
||||||
import google.registry.flows.exceptions.AddRemoveSameValueEppException;
|
|
||||||
import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException;
|
import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException;
|
||||||
import google.registry.flows.exceptions.StatusNotClientSettableException;
|
|
||||||
import google.registry.model.contact.ContactCommand.Update;
|
import google.registry.model.contact.ContactCommand.Update;
|
||||||
|
import google.registry.model.contact.ContactCommand.Update.Change;
|
||||||
import google.registry.model.contact.ContactResource;
|
import google.registry.model.contact.ContactResource;
|
||||||
import google.registry.model.contact.ContactResource.Builder;
|
import google.registry.model.contact.ContactResource.Builder;
|
||||||
|
import google.registry.model.contact.PostalInfo;
|
||||||
import google.registry.model.domain.metadata.MetadataExtension;
|
import google.registry.model.domain.metadata.MetadataExtension;
|
||||||
import google.registry.model.eppcommon.AuthInfo;
|
import google.registry.model.eppcommon.AuthInfo;
|
||||||
import google.registry.model.eppcommon.StatusValue;
|
import google.registry.model.eppcommon.StatusValue;
|
||||||
import google.registry.model.eppinput.ResourceCommand;
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
import google.registry.model.eppinput.ResourceCommand.AddRemoveSameValueException;
|
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppOutput;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An EPP flow that updates a contact.
|
* An EPP flow that updates a contact.
|
||||||
*
|
*
|
||||||
|
* @error {@link google.registry.flows.ResourceFlowUtils.AddRemoveSameValueException}
|
||||||
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException}
|
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException}
|
||||||
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException}
|
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException}
|
||||||
* @error {@link google.registry.flows.exceptions.AddRemoveSameValueEppException}
|
* @error {@link google.registry.flows.ResourceFlowUtils.StatusNotClientSettableException}
|
||||||
* @error {@link google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException}
|
* @error {@link google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException}
|
||||||
* @error {@link google.registry.flows.exceptions.ResourceStatusProhibitsOperationException}
|
* @error {@link google.registry.flows.exceptions.ResourceStatusProhibitsOperationException}
|
||||||
* @error {@link google.registry.flows.exceptions.StatusNotClientSettableException}
|
|
||||||
* @error {@link ContactFlowUtils.BadInternationalizedPostalInfoException}
|
* @error {@link ContactFlowUtils.BadInternationalizedPostalInfoException}
|
||||||
* @error {@link ContactFlowUtils.DeclineContactDisclosureFieldDisallowedPolicyException}
|
* @error {@link ContactFlowUtils.DeclineContactDisclosureFieldDisallowedPolicyException}
|
||||||
*/
|
*/
|
||||||
|
@ -88,15 +90,11 @@ public final class ContactUpdateFlow extends Flow implements TransactionalFlow {
|
||||||
Update command = (Update) resourceCommand;
|
Update command = (Update) resourceCommand;
|
||||||
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
||||||
verifyOptionalAuthInfoForResource(authInfo, existingContact);
|
verifyOptionalAuthInfoForResource(authInfo, existingContact);
|
||||||
if (!isSuperuser) {
|
ImmutableSet<StatusValue> statusToRemove = command.getInnerRemove().getStatusValues();
|
||||||
|
ImmutableSet<StatusValue> statusesToAdd = command.getInnerAdd().getStatusValues();
|
||||||
|
if (!isSuperuser) { // The superuser can update any contact and set any status.
|
||||||
verifyResourceOwnership(clientId, existingContact);
|
verifyResourceOwnership(clientId, existingContact);
|
||||||
}
|
verifyAllStatusesAreClientSettable(union(statusesToAdd, statusToRemove));
|
||||||
for (StatusValue statusValue : Sets.union(
|
|
||||||
command.getInnerAdd().getStatusValues(),
|
|
||||||
command.getInnerRemove().getStatusValues())) {
|
|
||||||
if (!isSuperuser && !statusValue.isClientSettable()) { // The superuser can set any status.
|
|
||||||
throw new StatusNotClientSettableException(statusValue.getXmlName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
verifyNoDisallowedStatuses(existingContact, DISALLOWED_STATUSES);
|
verifyNoDisallowedStatuses(existingContact, DISALLOWED_STATUSES);
|
||||||
historyBuilder
|
historyBuilder
|
||||||
|
@ -104,15 +102,39 @@ public final class ContactUpdateFlow extends Flow implements TransactionalFlow {
|
||||||
.setModificationTime(now)
|
.setModificationTime(now)
|
||||||
.setXmlBytes(null) // We don't want to store contact details in the history entry.
|
.setXmlBytes(null) // We don't want to store contact details in the history entry.
|
||||||
.setParent(Key.create(existingContact));
|
.setParent(Key.create(existingContact));
|
||||||
|
checkSameValuesNotAddedAndRemoved(statusesToAdd, statusToRemove);
|
||||||
Builder builder = existingContact.asBuilder();
|
Builder builder = existingContact.asBuilder();
|
||||||
try {
|
Change change = command.getInnerChange();
|
||||||
command.applyTo(builder);
|
// The spec requires the following behaviors:
|
||||||
} catch (AddRemoveSameValueException e) {
|
// * If you update part of a postal info, the fields that you didn't update are unchanged.
|
||||||
throw new AddRemoveSameValueEppException();
|
// * If you update one postal info but not the other, the other is deleted.
|
||||||
|
// Therefore, if you want to preserve one postal info and update another you need to send the
|
||||||
|
// update and also something that technically updates the preserved one, even if it only
|
||||||
|
// "updates" it by setting just one field to the same value.
|
||||||
|
PostalInfo internationalized = change.getInternationalizedPostalInfo();
|
||||||
|
PostalInfo localized = change.getLocalizedPostalInfo();
|
||||||
|
if (internationalized != null) {
|
||||||
|
builder.overlayInternationalizedPostalInfo(internationalized);
|
||||||
|
if (localized == null) {
|
||||||
|
builder.setLocalizedPostalInfo(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (localized != null) {
|
||||||
|
builder.overlayLocalizedPostalInfo(localized);
|
||||||
|
if (internationalized == null) {
|
||||||
|
builder.setInternationalizedPostalInfo(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ContactResource newContact = builder
|
ContactResource newContact = builder
|
||||||
.setLastEppUpdateTime(now)
|
.setLastEppUpdateTime(now)
|
||||||
.setLastEppUpdateClientId(clientId)
|
.setLastEppUpdateClientId(clientId)
|
||||||
|
.setAuthInfo(preferFirst(change.getAuthInfo(), existingContact.getAuthInfo()))
|
||||||
|
.setDisclose(preferFirst(change.getDisclose(), existingContact.getDisclose()))
|
||||||
|
.setEmailAddress(preferFirst(change.getEmail(), existingContact.getEmailAddress()))
|
||||||
|
.setFaxNumber(preferFirst(change.getFax(), existingContact.getFaxNumber()))
|
||||||
|
.setVoiceNumber(preferFirst(change.getVoice(), existingContact.getVoiceNumber()))
|
||||||
|
.addStatusValues(statusesToAdd)
|
||||||
|
.removeStatusValues(statusToRemove)
|
||||||
.build();
|
.build();
|
||||||
// If the resource is marked with clientUpdateProhibited, and this update did not clear that
|
// If the resource is marked with clientUpdateProhibited, and this update did not clear that
|
||||||
// status, then the update must be disallowed (unless a superuser is requesting the change).
|
// status, then the update must be disallowed (unless a superuser is requesting the change).
|
||||||
|
@ -126,4 +148,10 @@ public final class ContactUpdateFlow extends Flow implements TransactionalFlow {
|
||||||
ofy().save().<Object>entities(newContact, historyBuilder.build());
|
ofy().save().<Object>entities(newContact, historyBuilder.build());
|
||||||
return createOutput(SUCCESS);
|
return createOutput(SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Return the first non-null param, or null if both are null. */
|
||||||
|
@Nullable
|
||||||
|
private static <T> T preferFirst(@Nullable T a, @Nullable T b) {
|
||||||
|
return a != null ? a : b;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,9 +146,7 @@ public class DomainAllocateFlow extends Flow implements TransactionalFlow {
|
||||||
domainName, application, historyEntry, isSunrushAddGracePeriod, registry, years);
|
domainName, application, historyEntry, isSunrushAddGracePeriod, registry, years);
|
||||||
entitiesToSave.addAll(billsAndPolls);
|
entitiesToSave.addAll(billsAndPolls);
|
||||||
DateTime registrationExpirationTime = leapSafeAddYears(now, years);
|
DateTime registrationExpirationTime = leapSafeAddYears(now, years);
|
||||||
DomainResource.Builder domainBuilder = new DomainResource.Builder();
|
DomainResource newDomain = new DomainResource.Builder()
|
||||||
command.applyTo(domainBuilder);
|
|
||||||
DomainResource newDomain = domainBuilder
|
|
||||||
.setCreationClientId(clientId)
|
.setCreationClientId(clientId)
|
||||||
.setCurrentSponsorClientId(clientId)
|
.setCurrentSponsorClientId(clientId)
|
||||||
.setRepoId(repoId)
|
.setRepoId(repoId)
|
||||||
|
@ -167,6 +165,11 @@ public class DomainAllocateFlow extends Flow implements TransactionalFlow {
|
||||||
.setStatusValues(ReservationType.NAME_COLLISION == getReservationType(domainName)
|
.setStatusValues(ReservationType.NAME_COLLISION == getReservationType(domainName)
|
||||||
? ImmutableSet.of(StatusValue.SERVER_HOLD)
|
? ImmutableSet.of(StatusValue.SERVER_HOLD)
|
||||||
: ImmutableSet.<StatusValue>of())
|
: ImmutableSet.<StatusValue>of())
|
||||||
|
.setRegistrant(command.getRegistrant())
|
||||||
|
.setAuthInfo(command.getAuthInfo())
|
||||||
|
.setFullyQualifiedDomainName(targetId)
|
||||||
|
.setNameservers(command.getNameservers())
|
||||||
|
.setContacts(command.getContacts())
|
||||||
.build();
|
.build();
|
||||||
entitiesToSave.add(
|
entitiesToSave.add(
|
||||||
newDomain,
|
newDomain,
|
||||||
|
|
|
@ -210,9 +210,7 @@ public final class DomainApplicationCreateFlow extends Flow implements Transacti
|
||||||
validateFeeChallenge(targetId, tld, now, feeCreate, commandOperations.getTotalCost());
|
validateFeeChallenge(targetId, tld, now, feeCreate, commandOperations.getTotalCost());
|
||||||
SecDnsCreateExtension secDnsCreate =
|
SecDnsCreateExtension secDnsCreate =
|
||||||
validateSecDnsExtension(eppInput.getSingleExtension(SecDnsCreateExtension.class));
|
validateSecDnsExtension(eppInput.getSingleExtension(SecDnsCreateExtension.class));
|
||||||
DomainApplication.Builder applicationBuilder = new DomainApplication.Builder();
|
DomainApplication newApplication = new DomainApplication.Builder()
|
||||||
command.applyTo(applicationBuilder);
|
|
||||||
applicationBuilder
|
|
||||||
.setCreationTrid(trid)
|
.setCreationTrid(trid)
|
||||||
.setCreationClientId(clientId)
|
.setCreationClientId(clientId)
|
||||||
.setCurrentSponsorClientId(clientId)
|
.setCurrentSponsorClientId(clientId)
|
||||||
|
@ -224,6 +222,11 @@ public final class DomainApplicationCreateFlow extends Flow implements Transacti
|
||||||
.setApplicationStatus(ApplicationStatus.VALIDATED)
|
.setApplicationStatus(ApplicationStatus.VALIDATED)
|
||||||
.addStatusValue(StatusValue.PENDING_CREATE)
|
.addStatusValue(StatusValue.PENDING_CREATE)
|
||||||
.setDsData(secDnsCreate == null ? null : secDnsCreate.getDsData())
|
.setDsData(secDnsCreate == null ? null : secDnsCreate.getDsData())
|
||||||
|
.setRegistrant(command.getRegistrant())
|
||||||
|
.setAuthInfo(command.getAuthInfo())
|
||||||
|
.setFullyQualifiedDomainName(targetId)
|
||||||
|
.setNameservers(command.getNameservers())
|
||||||
|
.setContacts(command.getContacts())
|
||||||
.setEncodedSignedMarks(FluentIterable
|
.setEncodedSignedMarks(FluentIterable
|
||||||
.from(launchCreate.getSignedMarks())
|
.from(launchCreate.getSignedMarks())
|
||||||
.transform(new Function<AbstractSignedMark, EncodedSignedMark>() {
|
.transform(new Function<AbstractSignedMark, EncodedSignedMark>() {
|
||||||
|
@ -231,8 +234,8 @@ public final class DomainApplicationCreateFlow extends Flow implements Transacti
|
||||||
public EncodedSignedMark apply(AbstractSignedMark abstractSignedMark) {
|
public EncodedSignedMark apply(AbstractSignedMark abstractSignedMark) {
|
||||||
return (EncodedSignedMark) abstractSignedMark;
|
return (EncodedSignedMark) abstractSignedMark;
|
||||||
}})
|
}})
|
||||||
.toList());
|
.toList())
|
||||||
DomainApplication newApplication = applicationBuilder.build();
|
.build();
|
||||||
HistoryEntry historyEntry = buildHistory(newApplication.getRepoId(), command.getPeriod());
|
HistoryEntry historyEntry = buildHistory(newApplication.getRepoId(), command.getPeriod());
|
||||||
ImmutableSet.Builder<ImmutableObject> entitiesToSave = new ImmutableSet.Builder<>();
|
ImmutableSet.Builder<ImmutableObject> entitiesToSave = new ImmutableSet.Builder<>();
|
||||||
handleExtraFlowLogic(
|
handleExtraFlowLogic(
|
||||||
|
|
|
@ -16,7 +16,11 @@ package google.registry.flows.domain;
|
||||||
|
|
||||||
import static com.google.common.base.CaseFormat.LOWER_CAMEL;
|
import static com.google.common.base.CaseFormat.LOWER_CAMEL;
|
||||||
import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
|
import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
|
||||||
|
import static com.google.common.base.MoreObjects.firstNonNull;
|
||||||
|
import static com.google.common.collect.Sets.union;
|
||||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||||
|
import static google.registry.flows.ResourceFlowUtils.checkSameValuesNotAddedAndRemoved;
|
||||||
|
import static google.registry.flows.ResourceFlowUtils.verifyAllStatusesAreClientSettable;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyExistence;
|
import static google.registry.flows.ResourceFlowUtils.verifyExistence;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
|
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
|
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
|
||||||
|
@ -34,7 +38,6 @@ import static google.registry.flows.domain.DomainFlowUtils.validateRequiredConta
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.verifyApplicationDomainMatchesTargetId;
|
import static google.registry.flows.domain.DomainFlowUtils.verifyApplicationDomainMatchesTargetId;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.verifyClientUpdateNotProhibited;
|
import static google.registry.flows.domain.DomainFlowUtils.verifyClientUpdateNotProhibited;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.verifyNotInPendingDelete;
|
import static google.registry.flows.domain.DomainFlowUtils.verifyNotInPendingDelete;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.verifyStatusChangesAreClientSettable;
|
|
||||||
import static google.registry.model.EppResourceUtils.loadDomainApplication;
|
import static google.registry.model.EppResourceUtils.loadDomainApplication;
|
||||||
import static google.registry.model.domain.fee.Fee.FEE_UPDATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER;
|
import static google.registry.model.domain.fee.Fee.FEE_UPDATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER;
|
||||||
import static google.registry.model.eppoutput.Result.Code.SUCCESS;
|
import static google.registry.model.eppoutput.Result.Code.SUCCESS;
|
||||||
|
@ -52,11 +55,11 @@ import google.registry.flows.FlowModule.ApplicationId;
|
||||||
import google.registry.flows.FlowModule.ClientId;
|
import google.registry.flows.FlowModule.ClientId;
|
||||||
import google.registry.flows.FlowModule.TargetId;
|
import google.registry.flows.FlowModule.TargetId;
|
||||||
import google.registry.flows.TransactionalFlow;
|
import google.registry.flows.TransactionalFlow;
|
||||||
import google.registry.flows.exceptions.AddRemoveSameValueEppException;
|
|
||||||
import google.registry.model.ImmutableObject;
|
import google.registry.model.ImmutableObject;
|
||||||
import google.registry.model.domain.DomainApplication;
|
import google.registry.model.domain.DomainApplication;
|
||||||
import google.registry.model.domain.DomainApplication.Builder;
|
|
||||||
import google.registry.model.domain.DomainCommand.Update;
|
import google.registry.model.domain.DomainCommand.Update;
|
||||||
|
import google.registry.model.domain.DomainCommand.Update.AddRemove;
|
||||||
|
import google.registry.model.domain.DomainCommand.Update.Change;
|
||||||
import google.registry.model.domain.launch.ApplicationStatus;
|
import google.registry.model.domain.launch.ApplicationStatus;
|
||||||
import google.registry.model.domain.launch.LaunchUpdateExtension;
|
import google.registry.model.domain.launch.LaunchUpdateExtension;
|
||||||
import google.registry.model.domain.metadata.MetadataExtension;
|
import google.registry.model.domain.metadata.MetadataExtension;
|
||||||
|
@ -64,7 +67,6 @@ import google.registry.model.domain.secdns.SecDnsUpdateExtension;
|
||||||
import google.registry.model.eppcommon.AuthInfo;
|
import google.registry.model.eppcommon.AuthInfo;
|
||||||
import google.registry.model.eppcommon.StatusValue;
|
import google.registry.model.eppcommon.StatusValue;
|
||||||
import google.registry.model.eppinput.ResourceCommand;
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
import google.registry.model.eppinput.ResourceCommand.AddRemoveSameValueException;
|
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppOutput;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -76,12 +78,12 @@ import javax.inject.Inject;
|
||||||
* cannot change the domain name that is being applied for.
|
* cannot change the domain name that is being applied for.
|
||||||
*
|
*
|
||||||
* @error {@link google.registry.flows.EppException.UnimplementedExtensionException}
|
* @error {@link google.registry.flows.EppException.UnimplementedExtensionException}
|
||||||
|
* @error {@link google.registry.flows.ResourceFlowUtils.AddRemoveSameValueException}
|
||||||
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException}
|
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException}
|
||||||
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException}
|
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException}
|
||||||
* @error {@link google.registry.flows.exceptions.AddRemoveSameValueEppException}
|
* @error {@link google.registry.flows.ResourceFlowUtils.StatusNotClientSettableException}
|
||||||
* @error {@link google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException}
|
* @error {@link google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException}
|
||||||
* @error {@link google.registry.flows.exceptions.ResourceStatusProhibitsOperationException}
|
* @error {@link google.registry.flows.exceptions.ResourceStatusProhibitsOperationException}
|
||||||
* @error {@link google.registry.flows.exceptions.StatusNotClientSettableException}
|
|
||||||
* @error {@link DomainFlowUtils.ApplicationDomainNameMismatchException}
|
* @error {@link DomainFlowUtils.ApplicationDomainNameMismatchException}
|
||||||
* @error {@link DomainFlowUtils.DuplicateContactForRoleException}
|
* @error {@link DomainFlowUtils.DuplicateContactForRoleException}
|
||||||
* @error {@link DomainFlowUtils.EmptySecDnsUpdateException}
|
* @error {@link DomainFlowUtils.EmptySecDnsUpdateException}
|
||||||
|
@ -151,10 +153,12 @@ public class DomainApplicationUpdateFlow extends Flow implements TransactionalFl
|
||||||
|
|
||||||
protected final void verifyUpdateAllowed(
|
protected final void verifyUpdateAllowed(
|
||||||
DomainApplication existingApplication, Update command) throws EppException {
|
DomainApplication existingApplication, Update command) throws EppException {
|
||||||
|
AddRemove add = command.getInnerAdd();
|
||||||
|
AddRemove remove = command.getInnerRemove();
|
||||||
if (!isSuperuser) {
|
if (!isSuperuser) {
|
||||||
verifyResourceOwnership(clientId, existingApplication);
|
verifyResourceOwnership(clientId, existingApplication);
|
||||||
verifyClientUpdateNotProhibited(command, existingApplication);
|
verifyClientUpdateNotProhibited(command, existingApplication);
|
||||||
verifyStatusChangesAreClientSettable(command);
|
verifyAllStatusesAreClientSettable(union(add.getStatusValues(), remove.getStatusValues()));
|
||||||
}
|
}
|
||||||
String tld = existingApplication.getTld();
|
String tld = existingApplication.getTld();
|
||||||
checkAllowedAccessToTld(clientId, tld);
|
checkAllowedAccessToTld(clientId, tld);
|
||||||
|
@ -164,14 +168,14 @@ public class DomainApplicationUpdateFlow extends Flow implements TransactionalFl
|
||||||
existingApplication.getApplicationStatus());
|
existingApplication.getApplicationStatus());
|
||||||
}
|
}
|
||||||
verifyNotInPendingDelete(
|
verifyNotInPendingDelete(
|
||||||
command.getInnerAdd().getContacts(),
|
add.getContacts(),
|
||||||
command.getInnerChange().getRegistrant(),
|
command.getInnerChange().getRegistrant(),
|
||||||
command.getInnerAdd().getNameservers());
|
add.getNameservers());
|
||||||
validateContactsHaveTypes(command.getInnerAdd().getContacts());
|
validateContactsHaveTypes(add.getContacts());
|
||||||
validateContactsHaveTypes(command.getInnerRemove().getContacts());
|
validateContactsHaveTypes(remove.getContacts());
|
||||||
validateRegistrantAllowedOnTld(tld, command.getInnerChange().getRegistrantContactId());
|
validateRegistrantAllowedOnTld(tld, command.getInnerChange().getRegistrantContactId());
|
||||||
validateNameserversAllowedOnTld(
|
validateNameserversAllowedOnTld(
|
||||||
tld, command.getInnerAdd().getNameserverFullyQualifiedHostNames());
|
tld, add.getNameserverFullyQualifiedHostNames());
|
||||||
}
|
}
|
||||||
|
|
||||||
private HistoryEntry buildHistory(DomainApplication existingApplication) {
|
private HistoryEntry buildHistory(DomainApplication existingApplication) {
|
||||||
|
@ -183,20 +187,30 @@ public class DomainApplicationUpdateFlow extends Flow implements TransactionalFl
|
||||||
}
|
}
|
||||||
|
|
||||||
private DomainApplication updateApplication(
|
private DomainApplication updateApplication(
|
||||||
DomainApplication existingApplication, Update command) throws EppException {
|
DomainApplication application, Update command) throws EppException {
|
||||||
Builder builder = existingApplication.asBuilder();
|
AddRemove add = command.getInnerAdd();
|
||||||
try {
|
AddRemove remove = command.getInnerRemove();
|
||||||
command.applyTo(builder);
|
checkSameValuesNotAddedAndRemoved(add.getNameservers(), remove.getNameservers());
|
||||||
} catch (AddRemoveSameValueException e) {
|
checkSameValuesNotAddedAndRemoved(add.getContacts(), remove.getContacts());
|
||||||
throw new AddRemoveSameValueEppException();
|
checkSameValuesNotAddedAndRemoved(add.getStatusValues(), remove.getStatusValues());
|
||||||
}
|
Change change = command.getInnerChange();
|
||||||
builder.setLastEppUpdateTime(now).setLastEppUpdateClientId(clientId);
|
|
||||||
// Handle the secDNS extension.
|
|
||||||
SecDnsUpdateExtension secDnsUpdate = eppInput.getSingleExtension(SecDnsUpdateExtension.class);
|
SecDnsUpdateExtension secDnsUpdate = eppInput.getSingleExtension(SecDnsUpdateExtension.class);
|
||||||
if (secDnsUpdate != null) {
|
return application.asBuilder()
|
||||||
builder.setDsData(updateDsData(existingApplication.getDsData(), secDnsUpdate));
|
// Handle the secDNS extension.
|
||||||
}
|
.setDsData(secDnsUpdate != null
|
||||||
return builder.build();
|
? updateDsData(application.getDsData(), secDnsUpdate)
|
||||||
|
: application.getDsData())
|
||||||
|
.setLastEppUpdateTime(now)
|
||||||
|
.setLastEppUpdateClientId(clientId)
|
||||||
|
.addStatusValues(add.getStatusValues())
|
||||||
|
.removeStatusValues(remove.getStatusValues())
|
||||||
|
.addNameservers(add.getNameservers())
|
||||||
|
.removeNameservers(remove.getNameservers())
|
||||||
|
.addContacts(add.getContacts())
|
||||||
|
.removeContacts(remove.getContacts())
|
||||||
|
.setRegistrant(firstNonNull(change.getRegistrant(), application.getRegistrant()))
|
||||||
|
.setAuthInfo(firstNonNull(change.getAuthInfo(), application.getAuthInfo()))
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateNewApplication(DomainApplication newApplication) throws EppException {
|
private void validateNewApplication(DomainApplication newApplication) throws EppException {
|
||||||
|
|
|
@ -245,9 +245,7 @@ public class DomainCreateFlow extends Flow implements TransactionalFlow {
|
||||||
if (!commandOperations.getEapCost().isZero()) {
|
if (!commandOperations.getEapCost().isZero()) {
|
||||||
entitiesToSave.add(createEapBillingEvent(commandOperations, createBillingEvent));
|
entitiesToSave.add(createEapBillingEvent(commandOperations, createBillingEvent));
|
||||||
}
|
}
|
||||||
DomainResource.Builder domainBuilder = new DomainResource.Builder();
|
DomainResource newDomain = new DomainResource.Builder()
|
||||||
command.applyTo(domainBuilder);
|
|
||||||
DomainResource newDomain = domainBuilder
|
|
||||||
.setCreationClientId(clientId)
|
.setCreationClientId(clientId)
|
||||||
.setCurrentSponsorClientId(clientId)
|
.setCurrentSponsorClientId(clientId)
|
||||||
.setRepoId(repoId)
|
.setRepoId(repoId)
|
||||||
|
@ -261,6 +259,11 @@ public class DomainCreateFlow extends Flow implements TransactionalFlow {
|
||||||
? verifySignedMarks(launchCreate.getSignedMarks(), domainLabel, now).getId()
|
? verifySignedMarks(launchCreate.getSignedMarks(), domainLabel, now).getId()
|
||||||
: null)
|
: null)
|
||||||
.setDsData(secDnsCreate == null ? null : secDnsCreate.getDsData())
|
.setDsData(secDnsCreate == null ? null : secDnsCreate.getDsData())
|
||||||
|
.setRegistrant(command.getRegistrant())
|
||||||
|
.setAuthInfo(command.getAuthInfo())
|
||||||
|
.setFullyQualifiedDomainName(targetId)
|
||||||
|
.setNameservers(command.getNameservers())
|
||||||
|
.setContacts(command.getContacts())
|
||||||
.addGracePeriod(GracePeriod.forBillingEvent(GracePeriodStatus.ADD, createBillingEvent))
|
.addGracePeriod(GracePeriod.forBillingEvent(GracePeriodStatus.ADD, createBillingEvent))
|
||||||
.build();
|
.build();
|
||||||
handleExtraFlowLogic(registry.getTldStr(), years, historyEntry, newDomain);
|
handleExtraFlowLogic(registry.getTldStr(), years, historyEntry, newDomain);
|
||||||
|
|
|
@ -59,7 +59,6 @@ import google.registry.flows.EppException.UnimplementedOptionException;
|
||||||
import google.registry.flows.domain.TldSpecificLogicProxy.EppCommandOperations;
|
import google.registry.flows.domain.TldSpecificLogicProxy.EppCommandOperations;
|
||||||
import google.registry.flows.exceptions.ResourceAlreadyExistsException;
|
import google.registry.flows.exceptions.ResourceAlreadyExistsException;
|
||||||
import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException;
|
import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException;
|
||||||
import google.registry.flows.exceptions.StatusNotClientSettableException;
|
|
||||||
import google.registry.model.EppResource;
|
import google.registry.model.EppResource;
|
||||||
import google.registry.model.billing.BillingEvent;
|
import google.registry.model.billing.BillingEvent;
|
||||||
import google.registry.model.billing.BillingEvent.Flag;
|
import google.registry.model.billing.BillingEvent.Flag;
|
||||||
|
@ -829,18 +828,6 @@ public class DomainFlowUtils {
|
||||||
return ImmutableSet.copyOf(union(difference(oldDsData, toRemove), toAdd));
|
return ImmutableSet.copyOf(union(difference(oldDsData, toRemove), toAdd));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Check that all of the status values added or removed in an update are client-settable. */
|
|
||||||
static void verifyStatusChangesAreClientSettable(Update command)
|
|
||||||
throws StatusNotClientSettableException {
|
|
||||||
for (StatusValue statusValue : union(
|
|
||||||
command.getInnerAdd().getStatusValues(),
|
|
||||||
command.getInnerRemove().getStatusValues())) {
|
|
||||||
if (!statusValue.isClientSettable()) {
|
|
||||||
throw new StatusNotClientSettableException(statusValue.getXmlName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** If a domain or application has "clientUpdateProhibited" set, updates must clear it or fail. */
|
/** If a domain or application has "clientUpdateProhibited" set, updates must clear it or fail. */
|
||||||
static void verifyClientUpdateNotProhibited(Update command, DomainBase existingResource)
|
static void verifyClientUpdateNotProhibited(Update command, DomainBase existingResource)
|
||||||
throws ResourceHasClientUpdateProhibitedException {
|
throws ResourceHasClientUpdateProhibitedException {
|
||||||
|
|
|
@ -14,9 +14,13 @@
|
||||||
|
|
||||||
package google.registry.flows.domain;
|
package google.registry.flows.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.MoreObjects.firstNonNull;
|
||||||
import static com.google.common.collect.Sets.symmetricDifference;
|
import static com.google.common.collect.Sets.symmetricDifference;
|
||||||
|
import static com.google.common.collect.Sets.union;
|
||||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||||
|
import static google.registry.flows.ResourceFlowUtils.checkSameValuesNotAddedAndRemoved;
|
||||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||||
|
import static google.registry.flows.ResourceFlowUtils.verifyAllStatusesAreClientSettable;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
|
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
|
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
|
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
|
||||||
|
@ -33,7 +37,6 @@ import static google.registry.flows.domain.DomainFlowUtils.validateRegistrantAll
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.validateRequiredContactsPresent;
|
import static google.registry.flows.domain.DomainFlowUtils.validateRequiredContactsPresent;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.verifyClientUpdateNotProhibited;
|
import static google.registry.flows.domain.DomainFlowUtils.verifyClientUpdateNotProhibited;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.verifyNotInPendingDelete;
|
import static google.registry.flows.domain.DomainFlowUtils.verifyNotInPendingDelete;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.verifyStatusChangesAreClientSettable;
|
|
||||||
import static google.registry.model.domain.fee.Fee.FEE_UPDATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER;
|
import static google.registry.model.domain.fee.Fee.FEE_UPDATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER;
|
||||||
import static google.registry.model.eppoutput.Result.Code.SUCCESS;
|
import static google.registry.model.eppoutput.Result.Code.SUCCESS;
|
||||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
|
@ -52,11 +55,12 @@ import google.registry.flows.FlowModule.TargetId;
|
||||||
import google.registry.flows.TransactionalFlow;
|
import google.registry.flows.TransactionalFlow;
|
||||||
import google.registry.flows.domain.DomainFlowUtils.FeesRequiredForNonFreeUpdateException;
|
import google.registry.flows.domain.DomainFlowUtils.FeesRequiredForNonFreeUpdateException;
|
||||||
import google.registry.flows.domain.TldSpecificLogicProxy.EppCommandOperations;
|
import google.registry.flows.domain.TldSpecificLogicProxy.EppCommandOperations;
|
||||||
import google.registry.flows.exceptions.AddRemoveSameValueEppException;
|
|
||||||
import google.registry.model.ImmutableObject;
|
import google.registry.model.ImmutableObject;
|
||||||
import google.registry.model.billing.BillingEvent;
|
import google.registry.model.billing.BillingEvent;
|
||||||
import google.registry.model.billing.BillingEvent.Reason;
|
import google.registry.model.billing.BillingEvent.Reason;
|
||||||
import google.registry.model.domain.DomainCommand.Update;
|
import google.registry.model.domain.DomainCommand.Update;
|
||||||
|
import google.registry.model.domain.DomainCommand.Update.AddRemove;
|
||||||
|
import google.registry.model.domain.DomainCommand.Update.Change;
|
||||||
import google.registry.model.domain.DomainResource;
|
import google.registry.model.domain.DomainResource;
|
||||||
import google.registry.model.domain.GracePeriod;
|
import google.registry.model.domain.GracePeriod;
|
||||||
import google.registry.model.domain.fee.FeeTransformCommandExtension;
|
import google.registry.model.domain.fee.FeeTransformCommandExtension;
|
||||||
|
@ -67,7 +71,6 @@ import google.registry.model.domain.secdns.SecDnsUpdateExtension;
|
||||||
import google.registry.model.eppcommon.AuthInfo;
|
import google.registry.model.eppcommon.AuthInfo;
|
||||||
import google.registry.model.eppcommon.StatusValue;
|
import google.registry.model.eppcommon.StatusValue;
|
||||||
import google.registry.model.eppinput.ResourceCommand;
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
import google.registry.model.eppinput.ResourceCommand.AddRemoveSameValueException;
|
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppOutput;
|
||||||
import google.registry.model.registry.Registry;
|
import google.registry.model.registry.Registry;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
|
@ -92,13 +95,13 @@ import org.joda.time.DateTime;
|
||||||
* accordingly.
|
* accordingly.
|
||||||
*
|
*
|
||||||
* @error {@link google.registry.flows.EppException.UnimplementedExtensionException}
|
* @error {@link google.registry.flows.EppException.UnimplementedExtensionException}
|
||||||
|
* @error {@link google.registry.flows.ResourceFlowUtils.AddRemoveSameValueException}
|
||||||
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException}
|
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException}
|
||||||
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException}
|
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException}
|
||||||
* @error {@link google.registry.flows.exceptions.AddRemoveSameValueEppException}
|
* @error {@link google.registry.flows.ResourceFlowUtils.StatusNotClientSettableException}
|
||||||
* @error {@link google.registry.flows.exceptions.OnlyToolCanPassMetadataException}
|
* @error {@link google.registry.flows.exceptions.OnlyToolCanPassMetadataException}
|
||||||
* @error {@link google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException}
|
* @error {@link google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException}
|
||||||
* @error {@link google.registry.flows.exceptions.ResourceStatusProhibitsOperationException}
|
* @error {@link google.registry.flows.exceptions.ResourceStatusProhibitsOperationException}
|
||||||
* @error {@link google.registry.flows.exceptions.StatusNotClientSettableException}
|
|
||||||
* @error {@link DomainFlowUtils.DuplicateContactForRoleException}
|
* @error {@link DomainFlowUtils.DuplicateContactForRoleException}
|
||||||
* @error {@link DomainFlowUtils.EmptySecDnsUpdateException}
|
* @error {@link DomainFlowUtils.EmptySecDnsUpdateException}
|
||||||
* @error {@link DomainFlowUtils.FeesMismatchException}
|
* @error {@link DomainFlowUtils.FeesMismatchException}
|
||||||
|
@ -181,10 +184,12 @@ public final class DomainUpdateFlow extends Flow implements TransactionalFlow {
|
||||||
throws EppException {
|
throws EppException {
|
||||||
verifyNoDisallowedStatuses(existingDomain, UPDATE_DISALLOWED_STATUSES);
|
verifyNoDisallowedStatuses(existingDomain, UPDATE_DISALLOWED_STATUSES);
|
||||||
verifyOptionalAuthInfoForResource(authInfo, existingDomain);
|
verifyOptionalAuthInfoForResource(authInfo, existingDomain);
|
||||||
|
AddRemove add = command.getInnerAdd();
|
||||||
|
AddRemove remove = command.getInnerRemove();
|
||||||
if (!isSuperuser) {
|
if (!isSuperuser) {
|
||||||
verifyResourceOwnership(clientId, existingDomain);
|
verifyResourceOwnership(clientId, existingDomain);
|
||||||
verifyClientUpdateNotProhibited(command, existingDomain);
|
verifyClientUpdateNotProhibited(command, existingDomain);
|
||||||
verifyStatusChangesAreClientSettable(command);
|
verifyAllStatusesAreClientSettable(union(add.getStatusValues(), remove.getStatusValues()));
|
||||||
}
|
}
|
||||||
String tld = existingDomain.getTld();
|
String tld = existingDomain.getTld();
|
||||||
checkAllowedAccessToTld(clientId, tld);
|
checkAllowedAccessToTld(clientId, tld);
|
||||||
|
@ -204,14 +209,14 @@ public final class DomainUpdateFlow extends Flow implements TransactionalFlow {
|
||||||
throw new FeesRequiredForNonFreeUpdateException();
|
throw new FeesRequiredForNonFreeUpdateException();
|
||||||
}
|
}
|
||||||
verifyNotInPendingDelete(
|
verifyNotInPendingDelete(
|
||||||
command.getInnerAdd().getContacts(),
|
add.getContacts(),
|
||||||
command.getInnerChange().getRegistrant(),
|
command.getInnerChange().getRegistrant(),
|
||||||
command.getInnerAdd().getNameservers());
|
add.getNameservers());
|
||||||
validateContactsHaveTypes(command.getInnerAdd().getContacts());
|
validateContactsHaveTypes(add.getContacts());
|
||||||
validateContactsHaveTypes(command.getInnerRemove().getContacts());
|
validateContactsHaveTypes(remove.getContacts());
|
||||||
validateRegistrantAllowedOnTld(tld, command.getInnerChange().getRegistrantContactId());
|
validateRegistrantAllowedOnTld(tld, command.getInnerChange().getRegistrantContactId());
|
||||||
validateNameserversAllowedOnTld(
|
validateNameserversAllowedOnTld(
|
||||||
tld, command.getInnerAdd().getNameserverFullyQualifiedHostNames());
|
tld, add.getNameserverFullyQualifiedHostNames());
|
||||||
}
|
}
|
||||||
|
|
||||||
private HistoryEntry buildHistoryEntry(DomainResource existingDomain) {
|
private HistoryEntry buildHistoryEntry(DomainResource existingDomain) {
|
||||||
|
@ -222,22 +227,31 @@ public final class DomainUpdateFlow extends Flow implements TransactionalFlow {
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private DomainResource performUpdate(Update command, DomainResource existingDomain)
|
private DomainResource performUpdate(Update command, DomainResource domain)
|
||||||
throws EppException {
|
throws EppException {
|
||||||
DomainResource.Builder builder = existingDomain.asBuilder()
|
AddRemove add = command.getInnerAdd();
|
||||||
.setLastEppUpdateTime(now)
|
AddRemove remove = command.getInnerRemove();
|
||||||
.setLastEppUpdateClientId(clientId);
|
checkSameValuesNotAddedAndRemoved(add.getNameservers(), remove.getNameservers());
|
||||||
try {
|
checkSameValuesNotAddedAndRemoved(add.getContacts(), remove.getContacts());
|
||||||
command.applyTo(builder);
|
checkSameValuesNotAddedAndRemoved(add.getStatusValues(), remove.getStatusValues());
|
||||||
} catch (AddRemoveSameValueException e) {
|
Change change = command.getInnerChange();
|
||||||
throw new AddRemoveSameValueEppException();
|
|
||||||
}
|
|
||||||
// Handle the secDNS extension.
|
|
||||||
SecDnsUpdateExtension secDnsUpdate = eppInput.getSingleExtension(SecDnsUpdateExtension.class);
|
SecDnsUpdateExtension secDnsUpdate = eppInput.getSingleExtension(SecDnsUpdateExtension.class);
|
||||||
if (secDnsUpdate != null) {
|
return domain.asBuilder()
|
||||||
builder.setDsData(updateDsData(existingDomain.getDsData(), secDnsUpdate));
|
// Handle the secDNS extension.
|
||||||
}
|
.setDsData(secDnsUpdate != null
|
||||||
return builder.build();
|
? updateDsData(domain.getDsData(), secDnsUpdate)
|
||||||
|
: domain.getDsData())
|
||||||
|
.setLastEppUpdateTime(now)
|
||||||
|
.setLastEppUpdateClientId(clientId)
|
||||||
|
.addStatusValues(add.getStatusValues())
|
||||||
|
.removeStatusValues(remove.getStatusValues())
|
||||||
|
.addNameservers(add.getNameservers())
|
||||||
|
.removeNameservers(remove.getNameservers())
|
||||||
|
.addContacts(add.getContacts())
|
||||||
|
.removeContacts(remove.getContacts())
|
||||||
|
.setRegistrant(firstNonNull(change.getRegistrant(), domain.getRegistrant()))
|
||||||
|
.setAuthInfo(firstNonNull(change.getAuthInfo(), domain.getAuthInfo()))
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private DomainResource convertSunrushAddToAdd(
|
private DomainResource convertSunrushAddToAdd(
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
// Copyright 2016 The Nomulus Authors. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package google.registry.flows.exceptions;
|
|
||||||
|
|
||||||
import google.registry.flows.EppException.ParameterValuePolicyErrorException;
|
|
||||||
|
|
||||||
/** Cannot add and remove the same value. */
|
|
||||||
public class AddRemoveSameValueEppException extends ParameterValuePolicyErrorException {
|
|
||||||
public AddRemoveSameValueEppException() {
|
|
||||||
super("Cannot add and remove the same value");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
// Copyright 2016 The Nomulus Authors. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package google.registry.flows.exceptions;
|
|
||||||
|
|
||||||
import google.registry.flows.EppException.ParameterValueRangeErrorException;
|
|
||||||
|
|
||||||
/** The specified status value cannot be set by clients. */
|
|
||||||
public class StatusNotClientSettableException extends ParameterValueRangeErrorException {
|
|
||||||
public StatusNotClientSettableException(String statusValue) {
|
|
||||||
super(String.format("Status value %s cannot be set by clients", statusValue));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -101,11 +101,11 @@ public final class HostCreateFlow extends Flow implements TransactionalFlow {
|
||||||
? new SubordinateHostMustHaveIpException()
|
? new SubordinateHostMustHaveIpException()
|
||||||
: new UnexpectedExternalHostIpException();
|
: new UnexpectedExternalHostIpException();
|
||||||
}
|
}
|
||||||
Builder builder = new Builder();
|
HostResource newHost = new Builder()
|
||||||
command.applyTo(builder);
|
|
||||||
HostResource newHost = builder
|
|
||||||
.setCreationClientId(clientId)
|
.setCreationClientId(clientId)
|
||||||
.setCurrentSponsorClientId(clientId)
|
.setCurrentSponsorClientId(clientId)
|
||||||
|
.setFullyQualifiedHostName(targetId)
|
||||||
|
.setInetAddresses(command.getInetAddresses())
|
||||||
.setRepoId(createContactHostRoid(ObjectifyService.allocateId()))
|
.setRepoId(createContactHostRoid(ObjectifyService.allocateId()))
|
||||||
.setSuperordinateDomain(
|
.setSuperordinateDomain(
|
||||||
superordinateDomain.isPresent() ? Key.create(superordinateDomain.get()) : null)
|
superordinateDomain.isPresent() ? Key.create(superordinateDomain.get()) : null)
|
||||||
|
|
|
@ -15,8 +15,11 @@
|
||||||
package google.registry.flows.host;
|
package google.registry.flows.host;
|
||||||
|
|
||||||
import static com.google.common.base.MoreObjects.firstNonNull;
|
import static com.google.common.base.MoreObjects.firstNonNull;
|
||||||
|
import static com.google.common.collect.Sets.union;
|
||||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||||
|
import static google.registry.flows.ResourceFlowUtils.checkSameValuesNotAddedAndRemoved;
|
||||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||||
|
import static google.registry.flows.ResourceFlowUtils.verifyAllStatusesAreClientSettable;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
|
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
|
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
|
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
|
||||||
|
@ -30,7 +33,6 @@ import static google.registry.util.CollectionUtils.isNullOrEmpty;
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import com.googlecode.objectify.Key;
|
import com.googlecode.objectify.Key;
|
||||||
import google.registry.dns.DnsQueue;
|
import google.registry.dns.DnsQueue;
|
||||||
import google.registry.flows.EppException;
|
import google.registry.flows.EppException;
|
||||||
|
@ -44,20 +46,18 @@ import google.registry.flows.FlowModule.ClientId;
|
||||||
import google.registry.flows.FlowModule.TargetId;
|
import google.registry.flows.FlowModule.TargetId;
|
||||||
import google.registry.flows.TransactionalFlow;
|
import google.registry.flows.TransactionalFlow;
|
||||||
import google.registry.flows.async.AsyncFlowEnqueuer;
|
import google.registry.flows.async.AsyncFlowEnqueuer;
|
||||||
import google.registry.flows.exceptions.AddRemoveSameValueEppException;
|
|
||||||
import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException;
|
import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException;
|
||||||
import google.registry.flows.exceptions.StatusNotClientSettableException;
|
|
||||||
import google.registry.model.ImmutableObject;
|
import google.registry.model.ImmutableObject;
|
||||||
import google.registry.model.domain.DomainResource;
|
import google.registry.model.domain.DomainResource;
|
||||||
import google.registry.model.domain.metadata.MetadataExtension;
|
import google.registry.model.domain.metadata.MetadataExtension;
|
||||||
import google.registry.model.eppcommon.AuthInfo;
|
import google.registry.model.eppcommon.AuthInfo;
|
||||||
import google.registry.model.eppcommon.StatusValue;
|
import google.registry.model.eppcommon.StatusValue;
|
||||||
import google.registry.model.eppinput.ResourceCommand;
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
import google.registry.model.eppinput.ResourceCommand.AddRemoveSameValueException;
|
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppOutput;
|
||||||
import google.registry.model.host.HostCommand.Update;
|
import google.registry.model.host.HostCommand.Update;
|
||||||
|
import google.registry.model.host.HostCommand.Update.AddRemove;
|
||||||
|
import google.registry.model.host.HostCommand.Update.Change;
|
||||||
import google.registry.model.host.HostResource;
|
import google.registry.model.host.HostResource;
|
||||||
import google.registry.model.host.HostResource.Builder;
|
|
||||||
import google.registry.model.index.ForeignKeyIndex;
|
import google.registry.model.index.ForeignKeyIndex;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
@ -76,11 +76,12 @@ import javax.inject.Inject;
|
||||||
* when it is renamed from external to internal at least one must be added. If the host is renamed
|
* when it is renamed from external to internal at least one must be added. If the host is renamed
|
||||||
* or IP addresses are added, tasks are enqueued to update DNS accordingly.
|
* or IP addresses are added, tasks are enqueued to update DNS accordingly.
|
||||||
*
|
*
|
||||||
|
* @error {@link google.registry.flows.ResourceFlowUtils.AddRemoveSameValueException}
|
||||||
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException}
|
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException}
|
||||||
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException}
|
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException}
|
||||||
|
* @error {@link google.registry.flows.ResourceFlowUtils.StatusNotClientSettableException}
|
||||||
* @error {@link google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException}
|
* @error {@link google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException}
|
||||||
* @error {@link google.registry.flows.exceptions.ResourceStatusProhibitsOperationException}
|
* @error {@link google.registry.flows.exceptions.ResourceStatusProhibitsOperationException}
|
||||||
* @error {@link google.registry.flows.exceptions.StatusNotClientSettableException}
|
|
||||||
* @error {@link HostFlowUtils.HostNameTooShallowException}
|
* @error {@link HostFlowUtils.HostNameTooShallowException}
|
||||||
* @error {@link HostFlowUtils.InvalidHostNameException}
|
* @error {@link HostFlowUtils.InvalidHostNameException}
|
||||||
* @error {@link HostFlowUtils.SuperordinateDomainDoesNotExistException}
|
* @error {@link HostFlowUtils.SuperordinateDomainDoesNotExistException}
|
||||||
|
@ -117,7 +118,8 @@ public final class HostUpdateFlow extends Flow implements TransactionalFlow {
|
||||||
extensionManager.validate();
|
extensionManager.validate();
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
Update command = (Update) resourceCommand;
|
Update command = (Update) resourceCommand;
|
||||||
String suppliedNewHostName = command.getInnerChange().getFullyQualifiedHostName();
|
Change change = command.getInnerChange();
|
||||||
|
String suppliedNewHostName = change.getFullyQualifiedHostName();
|
||||||
HostResource existingHost = loadAndVerifyExistence(HostResource.class, targetId, now);
|
HostResource existingHost = loadAndVerifyExistence(HostResource.class, targetId, now);
|
||||||
boolean isHostRename = suppliedNewHostName != null;
|
boolean isHostRename = suppliedNewHostName != null;
|
||||||
String oldHostName = targetId;
|
String oldHostName = targetId;
|
||||||
|
@ -128,13 +130,16 @@ public final class HostUpdateFlow extends Flow implements TransactionalFlow {
|
||||||
if (isHostRename && loadAndGetKey(HostResource.class, newHostName, now) != null) {
|
if (isHostRename && loadAndGetKey(HostResource.class, newHostName, now) != null) {
|
||||||
throw new HostAlreadyExistsException(newHostName);
|
throw new HostAlreadyExistsException(newHostName);
|
||||||
}
|
}
|
||||||
Builder builder = existingHost.asBuilder();
|
AddRemove add = command.getInnerAdd();
|
||||||
try {
|
AddRemove remove = command.getInnerRemove();
|
||||||
command.applyTo(builder);
|
checkSameValuesNotAddedAndRemoved(add.getStatusValues(), remove.getStatusValues());
|
||||||
} catch (AddRemoveSameValueException e) {
|
checkSameValuesNotAddedAndRemoved(add.getInetAddresses(), remove.getInetAddresses());
|
||||||
throw new AddRemoveSameValueEppException();
|
HostResource newHost = existingHost.asBuilder()
|
||||||
}
|
.setFullyQualifiedHostName(newHostName)
|
||||||
builder
|
.addStatusValues(add.getStatusValues())
|
||||||
|
.removeStatusValues(remove.getStatusValues())
|
||||||
|
.addInetAddresses(add.getInetAddresses())
|
||||||
|
.removeInetAddresses(remove.getInetAddresses())
|
||||||
.setLastEppUpdateTime(now)
|
.setLastEppUpdateTime(now)
|
||||||
.setLastEppUpdateClientId(clientId)
|
.setLastEppUpdateClientId(clientId)
|
||||||
// The superordinateDomain can be missing if the new name is external.
|
// The superordinateDomain can be missing if the new name is external.
|
||||||
|
@ -142,9 +147,10 @@ public final class HostUpdateFlow extends Flow implements TransactionalFlow {
|
||||||
// the lookupSuperordinateDomain(...) call above, so that it will never be stale.
|
// the lookupSuperordinateDomain(...) call above, so that it will never be stale.
|
||||||
.setSuperordinateDomain(
|
.setSuperordinateDomain(
|
||||||
superordinateDomain.isPresent() ? Key.create(superordinateDomain.get()) : null)
|
superordinateDomain.isPresent() ? Key.create(superordinateDomain.get()) : null)
|
||||||
.setLastSuperordinateChange(superordinateDomain == null ? null : now);
|
.setLastSuperordinateChange(superordinateDomain == null ? null : now)
|
||||||
// Rely on the host's cloneProjectedAtTime() method to handle setting of transfer data.
|
.build()
|
||||||
HostResource newHost = builder.build().cloneProjectedAtTime(now);
|
// Rely on the host's cloneProjectedAtTime() method to handle setting of transfer data.
|
||||||
|
.cloneProjectedAtTime(now);
|
||||||
verifyHasIpsIffIsExternal(command, existingHost, newHost);
|
verifyHasIpsIffIsExternal(command, existingHost, newHost);
|
||||||
ImmutableSet.Builder<ImmutableObject> entitiesToSave = new ImmutableSet.Builder<>();
|
ImmutableSet.Builder<ImmutableObject> entitiesToSave = new ImmutableSet.Builder<>();
|
||||||
entitiesToSave.add(newHost);
|
entitiesToSave.add(newHost);
|
||||||
|
@ -172,21 +178,16 @@ public final class HostUpdateFlow extends Flow implements TransactionalFlow {
|
||||||
verifyOptionalAuthInfoForResource(authInfo, existingResource);
|
verifyOptionalAuthInfoForResource(authInfo, existingResource);
|
||||||
if (!isSuperuser) {
|
if (!isSuperuser) {
|
||||||
verifyResourceOwnership(clientId, existingResource);
|
verifyResourceOwnership(clientId, existingResource);
|
||||||
|
ImmutableSet<StatusValue> statusesToAdd = command.getInnerAdd().getStatusValues();
|
||||||
|
ImmutableSet<StatusValue> statusesToRemove = command.getInnerRemove().getStatusValues();
|
||||||
// If the resource is marked with clientUpdateProhibited, and this update does not clear that
|
// If the resource is marked with clientUpdateProhibited, and this update does not clear that
|
||||||
// status, then the update must be disallowed (unless a superuser is requesting the change).
|
// status, then the update must be disallowed (unless a superuser is requesting the change).
|
||||||
if (!isSuperuser
|
if (!isSuperuser
|
||||||
&& existingResource.getStatusValues().contains(StatusValue.CLIENT_UPDATE_PROHIBITED)
|
&& existingResource.getStatusValues().contains(StatusValue.CLIENT_UPDATE_PROHIBITED)
|
||||||
&& !command.getInnerRemove().getStatusValues()
|
&& !statusesToRemove.contains(StatusValue.CLIENT_UPDATE_PROHIBITED)) {
|
||||||
.contains(StatusValue.CLIENT_UPDATE_PROHIBITED)) {
|
|
||||||
throw new ResourceHasClientUpdateProhibitedException();
|
throw new ResourceHasClientUpdateProhibitedException();
|
||||||
}
|
}
|
||||||
}
|
verifyAllStatusesAreClientSettable(union(statusesToAdd, statusesToRemove));
|
||||||
for (StatusValue statusValue : Sets.union(
|
|
||||||
command.getInnerAdd().getStatusValues(),
|
|
||||||
command.getInnerRemove().getStatusValues())) {
|
|
||||||
if (!isSuperuser && !statusValue.isClientSettable()) { // The superuser can set any status.
|
|
||||||
throw new StatusNotClientSettableException(statusValue.getXmlName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
verifyDomainIsSameRegistrar(superordinateDomain, clientId);
|
verifyDomainIsSameRegistrar(superordinateDomain, clientId);
|
||||||
verifyNoDisallowedStatuses(existingResource, DISALLOWED_STATUSES);
|
verifyNoDisallowedStatuses(existingResource, DISALLOWED_STATUSES);
|
||||||
|
|
|
@ -20,7 +20,6 @@ import static google.registry.util.CollectionUtils.nullToEmpty;
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import google.registry.model.ImmutableObject;
|
import google.registry.model.ImmutableObject;
|
||||||
import google.registry.model.contact.ContactResource.Builder;
|
|
||||||
import google.registry.model.contact.PostalInfo.Type;
|
import google.registry.model.contact.PostalInfo.Type;
|
||||||
import google.registry.model.eppinput.ResourceCommand.AbstractSingleResourceCommand;
|
import google.registry.model.eppinput.ResourceCommand.AbstractSingleResourceCommand;
|
||||||
import google.registry.model.eppinput.ResourceCommand.ResourceCheck;
|
import google.registry.model.eppinput.ResourceCommand.ResourceCheck;
|
||||||
|
@ -75,23 +74,32 @@ public class ContactCommand {
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public ContactPhoneNumber getVoice() {
|
||||||
public void applyTo(Builder builder) {
|
return voice;
|
||||||
if (authInfo != null) {
|
}
|
||||||
builder.setAuthInfo(authInfo);
|
|
||||||
}
|
public ContactPhoneNumber getFax() {
|
||||||
if (disclose != null) {
|
return fax;
|
||||||
builder.setDisclose(disclose);
|
}
|
||||||
}
|
|
||||||
if (email != null) {
|
public String getEmail() {
|
||||||
builder.setEmailAddress(email);
|
return email;
|
||||||
}
|
}
|
||||||
if (fax != null) {
|
|
||||||
builder.setFaxNumber(fax);
|
public ContactAuthInfo getAuthInfo() {
|
||||||
}
|
return authInfo;
|
||||||
if (voice != null) {
|
}
|
||||||
builder.setVoiceNumber(voice);
|
|
||||||
}
|
public Disclose getDisclose() {
|
||||||
|
return disclose;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PostalInfo getInternationalizedPostalInfo() {
|
||||||
|
return getPostalInfosAsMap().get(Type.INTERNATIONALIZED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PostalInfo getLocalizedPostalInfo() {
|
||||||
|
return getPostalInfosAsMap().get(Type.LOCALIZED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,21 +142,6 @@ public class ContactCommand {
|
||||||
public ContactAuthInfo getAuthInfo() {
|
public ContactAuthInfo getAuthInfo() {
|
||||||
return authInfo;
|
return authInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void applyTo(ContactResource.Builder builder) {
|
|
||||||
super.applyTo(builder);
|
|
||||||
if (contactId != null) {
|
|
||||||
builder.setContactId(contactId);
|
|
||||||
}
|
|
||||||
Map<Type, PostalInfo> postalInfosAsMap = getPostalInfosAsMap();
|
|
||||||
if (postalInfosAsMap.containsKey(Type.INTERNATIONALIZED)) {
|
|
||||||
builder.setInternationalizedPostalInfo(postalInfosAsMap.get(Type.INTERNATIONALIZED));
|
|
||||||
}
|
|
||||||
if (postalInfosAsMap.containsKey(Type.LOCALIZED)) {
|
|
||||||
builder.setLocalizedPostalInfo(postalInfosAsMap.get(Type.LOCALIZED));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A delete command for a {@link ContactResource}. */
|
/** A delete command for a {@link ContactResource}. */
|
||||||
|
@ -204,34 +197,6 @@ public class ContactCommand {
|
||||||
|
|
||||||
/** The inner change type on a contact update command. */
|
/** The inner change type on a contact update command. */
|
||||||
@XmlType(propOrder = {"postalInfo", "voice", "fax", "email", "authInfo", "disclose"})
|
@XmlType(propOrder = {"postalInfo", "voice", "fax", "email", "authInfo", "disclose"})
|
||||||
public static class Change extends ContactCreateOrChange {
|
public static class Change extends ContactCreateOrChange {}
|
||||||
/**
|
|
||||||
* The spec requires the following behaviors:
|
|
||||||
* <ul>
|
|
||||||
* <li>If you update part of a postal info, the fields that you didn't update are unchanged.
|
|
||||||
* <li>If you update one postal info but not the other, the other is deleted.
|
|
||||||
* </ul>
|
|
||||||
* Therefore, if you want to preserve one postal info and update another you need to send the
|
|
||||||
* update and also something that technically updates the preserved one, even if it only
|
|
||||||
* "updates" it by setting just one field to the same value.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void applyTo(ContactResource.Builder builder) {
|
|
||||||
super.applyTo(builder);
|
|
||||||
Map<Type, PostalInfo> postalInfosAsMap = getPostalInfosAsMap();
|
|
||||||
if (postalInfosAsMap.containsKey(Type.INTERNATIONALIZED)) {
|
|
||||||
builder.overlayInternationalizedPostalInfo(postalInfosAsMap.get(Type.INTERNATIONALIZED));
|
|
||||||
if (postalInfosAsMap.size() == 1) {
|
|
||||||
builder.setLocalizedPostalInfo(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (postalInfosAsMap.containsKey(Type.LOCALIZED)) {
|
|
||||||
builder.overlayLocalizedPostalInfo(postalInfosAsMap.get(Type.LOCALIZED));
|
|
||||||
if (postalInfosAsMap.size() == 1) {
|
|
||||||
builder.setInternationalizedPostalInfo(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@ import google.registry.model.EppResource;
|
||||||
import google.registry.model.EppResource.ForeignKeyedEppResource;
|
import google.registry.model.EppResource.ForeignKeyedEppResource;
|
||||||
import google.registry.model.annotations.ExternalMessagingName;
|
import google.registry.model.annotations.ExternalMessagingName;
|
||||||
import google.registry.model.contact.PostalInfo.Type;
|
import google.registry.model.contact.PostalInfo.Type;
|
||||||
import google.registry.model.eppcommon.AuthInfo;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.xml.bind.annotation.XmlElement;
|
import javax.xml.bind.annotation.XmlElement;
|
||||||
import javax.xml.bind.annotation.XmlRootElement;
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
@ -147,7 +146,7 @@ public class ContactResource extends EppResource implements ForeignKeyedEppResou
|
||||||
return email;
|
return email;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AuthInfo getAuthInfo() {
|
public ContactAuthInfo getAuthInfo() {
|
||||||
return authInfo;
|
return authInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,6 @@ import google.registry.model.contact.ContactResource;
|
||||||
import google.registry.model.domain.DesignatedContact.Type;
|
import google.registry.model.domain.DesignatedContact.Type;
|
||||||
import google.registry.model.domain.launch.LaunchNotice;
|
import google.registry.model.domain.launch.LaunchNotice;
|
||||||
import google.registry.model.domain.secdns.DelegationSignerData;
|
import google.registry.model.domain.secdns.DelegationSignerData;
|
||||||
import google.registry.model.eppcommon.AuthInfo;
|
|
||||||
import google.registry.model.host.HostResource;
|
import google.registry.model.host.HostResource;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.xml.bind.annotation.XmlElement;
|
import javax.xml.bind.annotation.XmlElement;
|
||||||
|
@ -221,7 +220,7 @@ public abstract class DomainBase extends EppResource {
|
||||||
.toSet();
|
.toSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public AuthInfo getAuthInfo() {
|
public DomainAuthInfo getAuthInfo() {
|
||||||
return authInfo;
|
return authInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.collect.Iterables.getOnlyElement;
|
import static com.google.common.collect.Iterables.getOnlyElement;
|
||||||
import static com.google.common.collect.Maps.transformValues;
|
import static com.google.common.collect.Maps.transformValues;
|
||||||
import static com.google.common.collect.Sets.difference;
|
import static com.google.common.collect.Sets.difference;
|
||||||
import static com.google.common.collect.Sets.intersection;
|
|
||||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
import static google.registry.util.CollectionUtils.difference;
|
import static google.registry.util.CollectionUtils.difference;
|
||||||
import static google.registry.util.CollectionUtils.forceEmptyToNull;
|
import static google.registry.util.CollectionUtils.forceEmptyToNull;
|
||||||
|
@ -37,7 +36,6 @@ import com.googlecode.objectify.Work;
|
||||||
import google.registry.model.EppResource;
|
import google.registry.model.EppResource;
|
||||||
import google.registry.model.ImmutableObject;
|
import google.registry.model.ImmutableObject;
|
||||||
import google.registry.model.contact.ContactResource;
|
import google.registry.model.contact.ContactResource;
|
||||||
import google.registry.model.eppcommon.AuthInfo;
|
|
||||||
import google.registry.model.eppinput.ResourceCommand.AbstractSingleResourceCommand;
|
import google.registry.model.eppinput.ResourceCommand.AbstractSingleResourceCommand;
|
||||||
import google.registry.model.eppinput.ResourceCommand.ResourceCheck;
|
import google.registry.model.eppinput.ResourceCommand.ResourceCheck;
|
||||||
import google.registry.model.eppinput.ResourceCommand.ResourceCreateOrChange;
|
import google.registry.model.eppinput.ResourceCommand.ResourceCreateOrChange;
|
||||||
|
@ -98,14 +96,8 @@ public class DomainCommand {
|
||||||
return registrant;
|
return registrant;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public DomainAuthInfo getAuthInfo() {
|
||||||
public void applyTo(B builder) {
|
return authInfo;
|
||||||
if (registrant != null) {
|
|
||||||
builder.setRegistrant(registrant);
|
|
||||||
}
|
|
||||||
if (authInfo != null) {
|
|
||||||
builder.setAuthInfo(authInfo);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,24 +167,10 @@ public class DomainCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AuthInfo getAuthInfo() {
|
public DomainAuthInfo getAuthInfo() {
|
||||||
return authInfo;
|
return authInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void applyTo(DomainBase.Builder<?, ?> builder) {
|
|
||||||
super.applyTo(builder);
|
|
||||||
if (fullyQualifiedDomainName != null) {
|
|
||||||
builder.setFullyQualifiedDomainName(fullyQualifiedDomainName);
|
|
||||||
}
|
|
||||||
if (nameservers != null) {
|
|
||||||
builder.setNameservers(getNameservers());
|
|
||||||
}
|
|
||||||
if (contacts != null) {
|
|
||||||
builder.setContacts(getContacts());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Creates a copy of this {@link Create} with hard links to hosts and contacts. */
|
/** Creates a copy of this {@link Create} with hard links to hosts and contacts. */
|
||||||
@Override
|
@Override
|
||||||
public Create cloneAndLinkReferences(DateTime now) throws InvalidReferencesException {
|
public Create cloneAndLinkReferences(DateTime now) throws InvalidReferencesException {
|
||||||
|
@ -422,24 +400,6 @@ public class DomainCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void applyTo(DomainBase.Builder<?, ?> builder) throws AddRemoveSameValueException {
|
|
||||||
super.applyTo(builder);
|
|
||||||
getInnerChange().applyTo(builder);
|
|
||||||
AddRemove add = getInnerAdd();
|
|
||||||
AddRemove remove = getInnerRemove();
|
|
||||||
if (!intersection(add.getNameservers(), remove.getNameservers()).isEmpty()) {
|
|
||||||
throw new AddRemoveSameValueException();
|
|
||||||
}
|
|
||||||
builder.addNameservers(add.getNameservers());
|
|
||||||
builder.removeNameservers(remove.getNameservers());
|
|
||||||
if (!intersection(add.getContacts(), remove.getContacts()).isEmpty()) {
|
|
||||||
throw new AddRemoveSameValueException();
|
|
||||||
}
|
|
||||||
builder.addContacts(add.getContacts());
|
|
||||||
builder.removeContacts(remove.getContacts());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a copy of this {@link Update} with hard links to hosts and contacts.
|
* Creates a copy of this {@link Update} with hard links to hosts and contacts.
|
||||||
*
|
*
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
|
|
||||||
package google.registry.model.eppinput;
|
package google.registry.model.eppinput;
|
||||||
|
|
||||||
import static com.google.common.collect.Sets.intersection;
|
|
||||||
import static google.registry.util.CollectionUtils.nullSafeImmutableCopy;
|
import static google.registry.util.CollectionUtils.nullSafeImmutableCopy;
|
||||||
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
|
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
|
||||||
|
|
||||||
|
@ -83,9 +82,7 @@ public interface ResourceCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A create command, or the inner change (as opposed to add or remove) part of an update. */
|
/** A create command, or the inner change (as opposed to add or remove) part of an update. */
|
||||||
public interface ResourceCreateOrChange<B extends Builder<?>> {
|
public interface ResourceCreateOrChange<B extends Builder<?>> {}
|
||||||
public abstract void applyTo(B builder);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An update command for an {@link EppResource}.
|
* An update command for an {@link EppResource}.
|
||||||
|
@ -133,18 +130,5 @@ public interface ResourceCommand {
|
||||||
A remove = getNullableInnerRemove();
|
A remove = getNullableInnerRemove();
|
||||||
return remove == null ? new TypeInstantiator<A>(getClass()){}.instantiate() : remove;
|
return remove == null ? new TypeInstantiator<A>(getClass()){}.instantiate() : remove;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void applyTo(B builder) throws AddRemoveSameValueException {
|
|
||||||
getInnerChange().applyTo(builder);
|
|
||||||
if (!intersection(getInnerAdd().getStatusValues(), getInnerRemove().getStatusValues())
|
|
||||||
.isEmpty()) {
|
|
||||||
throw new AddRemoveSameValueException();
|
|
||||||
}
|
|
||||||
builder.addStatusValues(getInnerAdd().getStatusValues());
|
|
||||||
builder.removeStatusValues(getInnerRemove().getStatusValues());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Exception for adding and removing the same value in {@link ResourceUpdate#applyTo}. */
|
|
||||||
public static class AddRemoveSameValueException extends Exception {}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
|
|
||||||
package google.registry.model.host;
|
package google.registry.model.host;
|
||||||
|
|
||||||
import static com.google.common.collect.Sets.intersection;
|
|
||||||
import static google.registry.util.CollectionUtils.nullSafeImmutableCopy;
|
import static google.registry.util.CollectionUtils.nullSafeImmutableCopy;
|
||||||
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
|
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
|
||||||
|
|
||||||
|
@ -37,27 +36,9 @@ public class HostCommand {
|
||||||
@XmlTransient
|
@XmlTransient
|
||||||
abstract static class HostCreateOrChange extends AbstractSingleResourceCommand
|
abstract static class HostCreateOrChange extends AbstractSingleResourceCommand
|
||||||
implements ResourceCreateOrChange<HostResource.Builder> {
|
implements ResourceCreateOrChange<HostResource.Builder> {
|
||||||
/** IP Addresses for this host. Can be null if this is an external host. */
|
|
||||||
@XmlElement(name = "addr")
|
|
||||||
Set<InetAddress> inetAddresses;
|
|
||||||
|
|
||||||
public ImmutableSet<InetAddress> getInetAddresses() {
|
|
||||||
return nullSafeImmutableCopy(inetAddresses);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFullyQualifiedHostName() {
|
public String getFullyQualifiedHostName() {
|
||||||
return getTargetId();
|
return getTargetId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void applyTo(HostResource.Builder builder) {
|
|
||||||
if (getFullyQualifiedHostName() != null) {
|
|
||||||
builder.setFullyQualifiedHostName(getFullyQualifiedHostName());
|
|
||||||
}
|
|
||||||
if (getInetAddresses() != null) {
|
|
||||||
builder.setInetAddresses(getInetAddresses());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -67,7 +48,15 @@ public class HostCommand {
|
||||||
@XmlType(propOrder = {"targetId", "inetAddresses" })
|
@XmlType(propOrder = {"targetId", "inetAddresses" })
|
||||||
@XmlRootElement
|
@XmlRootElement
|
||||||
public static class Create
|
public static class Create
|
||||||
extends HostCreateOrChange implements ResourceCreateOrChange<HostResource.Builder> {}
|
extends HostCreateOrChange implements ResourceCreateOrChange<HostResource.Builder> {
|
||||||
|
/** IP Addresses for this host. Can be null if this is an external host. */
|
||||||
|
@XmlElement(name = "addr")
|
||||||
|
Set<InetAddress> inetAddresses;
|
||||||
|
|
||||||
|
public ImmutableSet<InetAddress> getInetAddresses() {
|
||||||
|
return nullSafeImmutableCopy(inetAddresses);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** A delete command for a {@link HostResource}. */
|
/** A delete command for a {@link HostResource}. */
|
||||||
@XmlRootElement
|
@XmlRootElement
|
||||||
|
@ -124,18 +113,6 @@ public class HostCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The inner change type on a host update command. */
|
/** The inner change type on a host update command. */
|
||||||
@XmlType(propOrder = {"targetId", "inetAddresses" })
|
|
||||||
public static class Change extends HostCreateOrChange {}
|
public static class Change extends HostCreateOrChange {}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void applyTo(HostResource.Builder builder) throws AddRemoveSameValueException {
|
|
||||||
super.applyTo(builder);
|
|
||||||
if (!intersection(getInnerAdd().getInetAddresses(), getInnerRemove().getInetAddresses())
|
|
||||||
.isEmpty()) {
|
|
||||||
throw new AddRemoveSameValueException();
|
|
||||||
}
|
|
||||||
builder.addInetAddresses(getInnerAdd().getInetAddresses());
|
|
||||||
builder.removeInetAddresses(getInnerRemove().getInetAddresses());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,14 +24,14 @@ import static google.registry.testing.DatastoreHelper.persistResource;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import google.registry.flows.ResourceFlowTestCase;
|
import google.registry.flows.ResourceFlowTestCase;
|
||||||
|
import google.registry.flows.ResourceFlowUtils.AddRemoveSameValueException;
|
||||||
import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
|
import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
|
||||||
import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException;
|
import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException;
|
||||||
|
import google.registry.flows.ResourceFlowUtils.StatusNotClientSettableException;
|
||||||
import google.registry.flows.contact.ContactFlowUtils.BadInternationalizedPostalInfoException;
|
import google.registry.flows.contact.ContactFlowUtils.BadInternationalizedPostalInfoException;
|
||||||
import google.registry.flows.contact.ContactFlowUtils.DeclineContactDisclosureFieldDisallowedPolicyException;
|
import google.registry.flows.contact.ContactFlowUtils.DeclineContactDisclosureFieldDisallowedPolicyException;
|
||||||
import google.registry.flows.exceptions.AddRemoveSameValueEppException;
|
|
||||||
import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException;
|
import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException;
|
||||||
import google.registry.flows.exceptions.ResourceStatusProhibitsOperationException;
|
import google.registry.flows.exceptions.ResourceStatusProhibitsOperationException;
|
||||||
import google.registry.flows.exceptions.StatusNotClientSettableException;
|
|
||||||
import google.registry.model.contact.ContactAddress;
|
import google.registry.model.contact.ContactAddress;
|
||||||
import google.registry.model.contact.ContactResource;
|
import google.registry.model.contact.ContactResource;
|
||||||
import google.registry.model.contact.PostalInfo;
|
import google.registry.model.contact.PostalInfo;
|
||||||
|
@ -84,7 +84,7 @@ public class ContactUpdateFlowTest
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuccess_updatingOnePostalInfoDeletesTheOther() throws Exception {
|
public void testSuccess_updatingInternationalizedPostalInfoDeletesLocalized() throws Exception {
|
||||||
ContactResource contact =
|
ContactResource contact =
|
||||||
persistResource(
|
persistResource(
|
||||||
newContactResource(getUniqueIdFromCommand()).asBuilder()
|
newContactResource(getUniqueIdFromCommand()).asBuilder()
|
||||||
|
@ -104,12 +104,60 @@ public class ContactUpdateFlowTest
|
||||||
// the localized one since they are treated as a pair for update purposes.
|
// the localized one since they are treated as a pair for update purposes.
|
||||||
assertAboutContacts().that(contact)
|
assertAboutContacts().that(contact)
|
||||||
.hasNonNullLocalizedPostalInfo().and()
|
.hasNonNullLocalizedPostalInfo().and()
|
||||||
.hasInternationalizedPostalInfo(null);
|
.hasNullInternationalizedPostalInfo();
|
||||||
|
|
||||||
runFlowAssertResponse(readFile("contact_update_response.xml"));
|
runFlowAssertResponse(readFile("contact_update_response.xml"));
|
||||||
assertAboutContacts().that(reloadResourceByForeignKey())
|
assertAboutContacts().that(reloadResourceByForeignKey())
|
||||||
.hasLocalizedPostalInfo(null).and()
|
.hasNullLocalizedPostalInfo().and()
|
||||||
.hasNonNullInternationalizedPostalInfo();
|
.hasInternationalizedPostalInfo(new PostalInfo.Builder()
|
||||||
|
.setType(Type.INTERNATIONALIZED)
|
||||||
|
.setAddress(new ContactAddress.Builder()
|
||||||
|
.setStreet(ImmutableList.of("124 Example Dr.", "Suite 200"))
|
||||||
|
.setCity("Dulles")
|
||||||
|
.setState("VA")
|
||||||
|
.setZip("20166-6503")
|
||||||
|
.setCountryCode("US")
|
||||||
|
.build())
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccess_updatingLocalizedPostalInfoDeletesInternationalized() throws Exception {
|
||||||
|
setEppInput("contact_update_localized.xml");
|
||||||
|
ContactResource contact =
|
||||||
|
persistResource(
|
||||||
|
newContactResource(getUniqueIdFromCommand()).asBuilder()
|
||||||
|
.setInternationalizedPostalInfo(new PostalInfo.Builder()
|
||||||
|
.setType(Type.INTERNATIONALIZED)
|
||||||
|
.setAddress(new ContactAddress.Builder()
|
||||||
|
.setStreet(ImmutableList.of("111 8th Ave", "4th Floor"))
|
||||||
|
.setCity("New York")
|
||||||
|
.setState("NY")
|
||||||
|
.setZip("10011")
|
||||||
|
.setCountryCode("US")
|
||||||
|
.build())
|
||||||
|
.build())
|
||||||
|
.build());
|
||||||
|
clock.advanceOneMilli();
|
||||||
|
// The test xml updates the localized postal info and should therefore implicitly delete
|
||||||
|
// the internationalized one since they are treated as a pair for update purposes.
|
||||||
|
assertAboutContacts().that(contact)
|
||||||
|
.hasNonNullInternationalizedPostalInfo().and()
|
||||||
|
.hasNullLocalizedPostalInfo();
|
||||||
|
|
||||||
|
runFlowAssertResponse(readFile("contact_update_response.xml"));
|
||||||
|
assertAboutContacts().that(reloadResourceByForeignKey())
|
||||||
|
.hasNullInternationalizedPostalInfo().and()
|
||||||
|
.hasLocalizedPostalInfo(new PostalInfo.Builder()
|
||||||
|
.setType(Type.LOCALIZED)
|
||||||
|
.setAddress(new ContactAddress.Builder()
|
||||||
|
.setStreet(ImmutableList.of("124 Example Dr.", "Suite 200"))
|
||||||
|
.setCity("Dulles")
|
||||||
|
.setState("VA")
|
||||||
|
.setZip("20166-6503")
|
||||||
|
.setCountryCode("US")
|
||||||
|
.build())
|
||||||
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -148,6 +196,73 @@ public class ContactUpdateFlowTest
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccess_updateOnePostalInfo_touchOtherPostalInfoPreservesIt() throws Exception {
|
||||||
|
setEppInput("contact_update_partial_postalinfo_preserve_int.xml");
|
||||||
|
persistResource(
|
||||||
|
newContactResource(getUniqueIdFromCommand()).asBuilder()
|
||||||
|
.setLocalizedPostalInfo(new PostalInfo.Builder()
|
||||||
|
.setType(Type.LOCALIZED)
|
||||||
|
.setName("A. Person")
|
||||||
|
.setOrg("Company Inc.")
|
||||||
|
.setAddress(new ContactAddress.Builder()
|
||||||
|
.setStreet(ImmutableList.of("123 4th st", "5th Floor"))
|
||||||
|
.setCity("City")
|
||||||
|
.setState("AB")
|
||||||
|
.setZip("12345")
|
||||||
|
.setCountryCode("US")
|
||||||
|
.build())
|
||||||
|
.build())
|
||||||
|
.setInternationalizedPostalInfo(new PostalInfo.Builder()
|
||||||
|
.setType(Type.INTERNATIONALIZED)
|
||||||
|
.setName("B. Person")
|
||||||
|
.setOrg("Company Co.")
|
||||||
|
.setAddress(new ContactAddress.Builder()
|
||||||
|
.setStreet(ImmutableList.of("100 200th Dr.", "6th Floor"))
|
||||||
|
.setCity("Town")
|
||||||
|
.setState("CD")
|
||||||
|
.setZip("67890")
|
||||||
|
.setCountryCode("US")
|
||||||
|
.build())
|
||||||
|
.build())
|
||||||
|
.build());
|
||||||
|
clock.advanceOneMilli();
|
||||||
|
// The test xml updates the address of the localized postal info. It also sets the name of the
|
||||||
|
// internationalized postal info to the same value it previously had, which causes it to be
|
||||||
|
// preserved. If the xml had not mentioned the internationalized one at all it would have been
|
||||||
|
// deleted.
|
||||||
|
runFlowAssertResponse(readFile("contact_update_response.xml"));
|
||||||
|
assertAboutContacts().that(reloadResourceByForeignKey())
|
||||||
|
.hasLocalizedPostalInfo(
|
||||||
|
new PostalInfo.Builder()
|
||||||
|
.setType(Type.LOCALIZED)
|
||||||
|
.setName("A. Person")
|
||||||
|
.setOrg("Company Inc.")
|
||||||
|
.setAddress(new ContactAddress.Builder()
|
||||||
|
.setStreet(ImmutableList.of("456 5th st"))
|
||||||
|
.setCity("Place")
|
||||||
|
.setState("CD")
|
||||||
|
.setZip("54321")
|
||||||
|
.setCountryCode("US")
|
||||||
|
.build())
|
||||||
|
.build())
|
||||||
|
.and()
|
||||||
|
.hasInternationalizedPostalInfo(
|
||||||
|
new PostalInfo.Builder()
|
||||||
|
.setType(Type.INTERNATIONALIZED)
|
||||||
|
.setName("B. Person")
|
||||||
|
.setOrg("Company Co.")
|
||||||
|
.setAddress(new ContactAddress.Builder()
|
||||||
|
.setStreet(ImmutableList.of("100 200th Dr.", "6th Floor"))
|
||||||
|
.setCity("Town")
|
||||||
|
.setState("CD")
|
||||||
|
.setZip("67890")
|
||||||
|
.setCountryCode("US")
|
||||||
|
.build())
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFailure_neverExisted() throws Exception {
|
public void testFailure_neverExisted() throws Exception {
|
||||||
thrown.expect(
|
thrown.expect(
|
||||||
|
@ -264,7 +379,7 @@ public class ContactUpdateFlowTest
|
||||||
public void testFailure_addRemoveSameValue() throws Exception {
|
public void testFailure_addRemoveSameValue() throws Exception {
|
||||||
setEppInput("contact_update_add_remove_same.xml");
|
setEppInput("contact_update_add_remove_same.xml");
|
||||||
persistActiveContact(getUniqueIdFromCommand());
|
persistActiveContact(getUniqueIdFromCommand());
|
||||||
thrown.expect(AddRemoveSameValueEppException.class);
|
thrown.expect(AddRemoveSameValueException.class);
|
||||||
runFlow();
|
runFlow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
36
javatests/google/registry/flows/contact/testdata/contact_update_localized.xml
vendored
Normal file
36
javatests/google/registry/flows/contact/testdata/contact_update_localized.xml
vendored
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
|
||||||
|
<command>
|
||||||
|
<update>
|
||||||
|
<contact:update
|
||||||
|
xmlns:contact="urn:ietf:params:xml:ns:contact-1.0">
|
||||||
|
<contact:id>sh8013</contact:id>
|
||||||
|
<contact:add>
|
||||||
|
<contact:status s="clientDeleteProhibited"/>
|
||||||
|
</contact:add>
|
||||||
|
<contact:chg>
|
||||||
|
<contact:postalInfo type="loc">
|
||||||
|
<contact:org/>
|
||||||
|
<contact:addr>
|
||||||
|
<contact:street>124 Example Dr.</contact:street>
|
||||||
|
<contact:street>Suite 200</contact:street>
|
||||||
|
<contact:city>Dulles</contact:city>
|
||||||
|
<contact:sp>VA</contact:sp>
|
||||||
|
<contact:pc>20166-6503</contact:pc>
|
||||||
|
<contact:cc>US</contact:cc>
|
||||||
|
</contact:addr>
|
||||||
|
</contact:postalInfo>
|
||||||
|
<contact:voice>+1.7034444444</contact:voice>
|
||||||
|
<contact:fax/>
|
||||||
|
<contact:authInfo>
|
||||||
|
<contact:pw>2fooBAR</contact:pw>
|
||||||
|
</contact:authInfo>
|
||||||
|
<contact:disclose flag="1">
|
||||||
|
<contact:voice/>
|
||||||
|
<contact:email/>
|
||||||
|
</contact:disclose>
|
||||||
|
</contact:chg>
|
||||||
|
</contact:update>
|
||||||
|
</update>
|
||||||
|
<clTRID>ABC-12345</clTRID>
|
||||||
|
</command>
|
||||||
|
</epp>
|
|
@ -0,0 +1,25 @@
|
||||||
|
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
|
||||||
|
<command>
|
||||||
|
<update>
|
||||||
|
<contact:update
|
||||||
|
xmlns:contact="urn:ietf:params:xml:ns:contact-1.0">
|
||||||
|
<contact:id>sh8013</contact:id>
|
||||||
|
<contact:chg>
|
||||||
|
<contact:postalInfo type="loc">
|
||||||
|
<contact:addr>
|
||||||
|
<contact:street>456 5th st</contact:street>
|
||||||
|
<contact:city>Place</contact:city>
|
||||||
|
<contact:sp>CD</contact:sp>
|
||||||
|
<contact:pc>54321</contact:pc>
|
||||||
|
<contact:cc>US</contact:cc>
|
||||||
|
</contact:addr>
|
||||||
|
</contact:postalInfo>
|
||||||
|
<contact:postalInfo type="int">
|
||||||
|
<contact:org>Company Co.</contact:org>
|
||||||
|
</contact:postalInfo>
|
||||||
|
</contact:chg>
|
||||||
|
</contact:update>
|
||||||
|
</update>
|
||||||
|
<clTRID>ABC-12345</clTRID>
|
||||||
|
</command>
|
||||||
|
</epp>
|
|
@ -32,8 +32,10 @@ import com.google.common.collect.ImmutableSet;
|
||||||
import com.googlecode.objectify.Key;
|
import com.googlecode.objectify.Key;
|
||||||
import google.registry.flows.EppException.UnimplementedExtensionException;
|
import google.registry.flows.EppException.UnimplementedExtensionException;
|
||||||
import google.registry.flows.ResourceFlowTestCase;
|
import google.registry.flows.ResourceFlowTestCase;
|
||||||
|
import google.registry.flows.ResourceFlowUtils.AddRemoveSameValueException;
|
||||||
import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
|
import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
|
||||||
import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException;
|
import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException;
|
||||||
|
import google.registry.flows.ResourceFlowUtils.StatusNotClientSettableException;
|
||||||
import google.registry.flows.domain.DomainApplicationUpdateFlow.ApplicationStatusProhibitsUpdateException;
|
import google.registry.flows.domain.DomainApplicationUpdateFlow.ApplicationStatusProhibitsUpdateException;
|
||||||
import google.registry.flows.domain.DomainFlowUtils.ApplicationDomainNameMismatchException;
|
import google.registry.flows.domain.DomainFlowUtils.ApplicationDomainNameMismatchException;
|
||||||
import google.registry.flows.domain.DomainFlowUtils.DuplicateContactForRoleException;
|
import google.registry.flows.domain.DomainFlowUtils.DuplicateContactForRoleException;
|
||||||
|
@ -50,10 +52,8 @@ import google.registry.flows.domain.DomainFlowUtils.SecDnsAllUsageException;
|
||||||
import google.registry.flows.domain.DomainFlowUtils.TooManyDsRecordsException;
|
import google.registry.flows.domain.DomainFlowUtils.TooManyDsRecordsException;
|
||||||
import google.registry.flows.domain.DomainFlowUtils.TooManyNameserversException;
|
import google.registry.flows.domain.DomainFlowUtils.TooManyNameserversException;
|
||||||
import google.registry.flows.domain.DomainFlowUtils.UrgentAttributeNotSupportedException;
|
import google.registry.flows.domain.DomainFlowUtils.UrgentAttributeNotSupportedException;
|
||||||
import google.registry.flows.exceptions.AddRemoveSameValueEppException;
|
|
||||||
import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException;
|
import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException;
|
||||||
import google.registry.flows.exceptions.ResourceStatusProhibitsOperationException;
|
import google.registry.flows.exceptions.ResourceStatusProhibitsOperationException;
|
||||||
import google.registry.flows.exceptions.StatusNotClientSettableException;
|
|
||||||
import google.registry.model.contact.ContactResource;
|
import google.registry.model.contact.ContactResource;
|
||||||
import google.registry.model.domain.DesignatedContact;
|
import google.registry.model.domain.DesignatedContact;
|
||||||
import google.registry.model.domain.DesignatedContact.Type;
|
import google.registry.model.domain.DesignatedContact.Type;
|
||||||
|
@ -587,7 +587,7 @@ public class DomainApplicationUpdateFlowTest
|
||||||
.setNameservers(ImmutableSet.of(Key.create(
|
.setNameservers(ImmutableSet.of(Key.create(
|
||||||
loadByForeignKey(HostResource.class, "ns1.example.tld", clock.nowUtc()))))
|
loadByForeignKey(HostResource.class, "ns1.example.tld", clock.nowUtc()))))
|
||||||
.build());
|
.build());
|
||||||
thrown.expect(AddRemoveSameValueEppException.class);
|
thrown.expect(AddRemoveSameValueException.class);
|
||||||
runFlow();
|
runFlow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -601,7 +601,7 @@ public class DomainApplicationUpdateFlowTest
|
||||||
Key.create(
|
Key.create(
|
||||||
loadByForeignKey(ContactResource.class, "sh8013", clock.nowUtc())))))
|
loadByForeignKey(ContactResource.class, "sh8013", clock.nowUtc())))))
|
||||||
.build());
|
.build());
|
||||||
thrown.expect(AddRemoveSameValueEppException.class);
|
thrown.expect(AddRemoveSameValueException.class);
|
||||||
runFlow();
|
runFlow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,8 +44,10 @@ import com.googlecode.objectify.Key;
|
||||||
import google.registry.flows.EppException.UnimplementedExtensionException;
|
import google.registry.flows.EppException.UnimplementedExtensionException;
|
||||||
import google.registry.flows.EppRequestSource;
|
import google.registry.flows.EppRequestSource;
|
||||||
import google.registry.flows.ResourceFlowTestCase;
|
import google.registry.flows.ResourceFlowTestCase;
|
||||||
|
import google.registry.flows.ResourceFlowUtils.AddRemoveSameValueException;
|
||||||
import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
|
import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
|
||||||
import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException;
|
import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException;
|
||||||
|
import google.registry.flows.ResourceFlowUtils.StatusNotClientSettableException;
|
||||||
import google.registry.flows.domain.DomainFlowUtils.DuplicateContactForRoleException;
|
import google.registry.flows.domain.DomainFlowUtils.DuplicateContactForRoleException;
|
||||||
import google.registry.flows.domain.DomainFlowUtils.EmptySecDnsUpdateException;
|
import google.registry.flows.domain.DomainFlowUtils.EmptySecDnsUpdateException;
|
||||||
import google.registry.flows.domain.DomainFlowUtils.FeesMismatchException;
|
import google.registry.flows.domain.DomainFlowUtils.FeesMismatchException;
|
||||||
|
@ -64,11 +66,9 @@ import google.registry.flows.domain.DomainFlowUtils.SecDnsAllUsageException;
|
||||||
import google.registry.flows.domain.DomainFlowUtils.TooManyDsRecordsException;
|
import google.registry.flows.domain.DomainFlowUtils.TooManyDsRecordsException;
|
||||||
import google.registry.flows.domain.DomainFlowUtils.TooManyNameserversException;
|
import google.registry.flows.domain.DomainFlowUtils.TooManyNameserversException;
|
||||||
import google.registry.flows.domain.DomainFlowUtils.UrgentAttributeNotSupportedException;
|
import google.registry.flows.domain.DomainFlowUtils.UrgentAttributeNotSupportedException;
|
||||||
import google.registry.flows.exceptions.AddRemoveSameValueEppException;
|
|
||||||
import google.registry.flows.exceptions.OnlyToolCanPassMetadataException;
|
import google.registry.flows.exceptions.OnlyToolCanPassMetadataException;
|
||||||
import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException;
|
import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException;
|
||||||
import google.registry.flows.exceptions.ResourceStatusProhibitsOperationException;
|
import google.registry.flows.exceptions.ResourceStatusProhibitsOperationException;
|
||||||
import google.registry.flows.exceptions.StatusNotClientSettableException;
|
|
||||||
import google.registry.model.billing.BillingEvent;
|
import google.registry.model.billing.BillingEvent;
|
||||||
import google.registry.model.billing.BillingEvent.Reason;
|
import google.registry.model.billing.BillingEvent.Reason;
|
||||||
import google.registry.model.contact.ContactResource;
|
import google.registry.model.contact.ContactResource;
|
||||||
|
@ -1003,7 +1003,7 @@ public class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow,
|
||||||
.setNameservers(ImmutableSet.of(Key.create(
|
.setNameservers(ImmutableSet.of(Key.create(
|
||||||
loadByForeignKey(HostResource.class, "ns1.example.foo", clock.nowUtc()))))
|
loadByForeignKey(HostResource.class, "ns1.example.foo", clock.nowUtc()))))
|
||||||
.build());
|
.build());
|
||||||
thrown.expect(AddRemoveSameValueEppException.class);
|
thrown.expect(AddRemoveSameValueException.class);
|
||||||
runFlow();
|
runFlow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1018,7 +1018,7 @@ public class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow,
|
||||||
Key.create(
|
Key.create(
|
||||||
loadByForeignKey(ContactResource.class, "sh8013", clock.nowUtc())))))
|
loadByForeignKey(ContactResource.class, "sh8013", clock.nowUtc())))))
|
||||||
.build());
|
.build());
|
||||||
thrown.expect(AddRemoveSameValueEppException.class);
|
thrown.expect(AddRemoveSameValueException.class);
|
||||||
runFlow();
|
runFlow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
package google.registry.flows.host;
|
package google.registry.flows.host;
|
||||||
|
|
||||||
|
import static com.google.common.base.Strings.nullToEmpty;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static google.registry.flows.async.RefreshDnsOnHostRenameAction.QUEUE_ASYNC_HOST_RENAME;
|
import static google.registry.flows.async.RefreshDnsOnHostRenameAction.QUEUE_ASYNC_HOST_RENAME;
|
||||||
import static google.registry.model.EppResourceUtils.loadByForeignKey;
|
import static google.registry.model.EppResourceUtils.loadByForeignKey;
|
||||||
|
@ -41,11 +42,12 @@ import com.google.common.net.InetAddresses;
|
||||||
import com.googlecode.objectify.Key;
|
import com.googlecode.objectify.Key;
|
||||||
import google.registry.flows.EppRequestSource;
|
import google.registry.flows.EppRequestSource;
|
||||||
import google.registry.flows.ResourceFlowTestCase;
|
import google.registry.flows.ResourceFlowTestCase;
|
||||||
|
import google.registry.flows.ResourceFlowUtils.AddRemoveSameValueException;
|
||||||
import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
|
import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
|
||||||
import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException;
|
import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException;
|
||||||
|
import google.registry.flows.ResourceFlowUtils.StatusNotClientSettableException;
|
||||||
import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException;
|
import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException;
|
||||||
import google.registry.flows.exceptions.ResourceStatusProhibitsOperationException;
|
import google.registry.flows.exceptions.ResourceStatusProhibitsOperationException;
|
||||||
import google.registry.flows.exceptions.StatusNotClientSettableException;
|
|
||||||
import google.registry.flows.host.HostFlowUtils.HostNameTooShallowException;
|
import google.registry.flows.host.HostFlowUtils.HostNameTooShallowException;
|
||||||
import google.registry.flows.host.HostFlowUtils.InvalidHostNameException;
|
import google.registry.flows.host.HostFlowUtils.InvalidHostNameException;
|
||||||
import google.registry.flows.host.HostFlowUtils.SuperordinateDomainDoesNotExistException;
|
import google.registry.flows.host.HostFlowUtils.SuperordinateDomainDoesNotExistException;
|
||||||
|
@ -69,14 +71,14 @@ import org.junit.Test;
|
||||||
public class HostUpdateFlowTest extends ResourceFlowTestCase<HostUpdateFlow, HostResource> {
|
public class HostUpdateFlowTest extends ResourceFlowTestCase<HostUpdateFlow, HostResource> {
|
||||||
|
|
||||||
private void setEppHostUpdateInput(
|
private void setEppHostUpdateInput(
|
||||||
String oldHostName, String newHostName, String addHostAddrs, String remHostAddrs) {
|
String oldHostName, String newHostName, String ipOrStatusToAdd, String ipOrStatusToRem) {
|
||||||
setEppInput(
|
setEppInput(
|
||||||
"host_update.xml",
|
"host_update.xml",
|
||||||
ImmutableMap.of(
|
ImmutableMap.of(
|
||||||
"OLD-HOSTNAME", oldHostName,
|
"OLD-HOSTNAME", oldHostName,
|
||||||
"NEW-HOSTNAME", newHostName,
|
"NEW-HOSTNAME", newHostName,
|
||||||
"ADD-HOSTADDRS", (addHostAddrs == null) ? "" : addHostAddrs,
|
"ADD-HOSTADDRSORSTATUS", nullToEmpty(ipOrStatusToAdd),
|
||||||
"REM-HOSTADDRS", (remHostAddrs == null) ? "" : remHostAddrs));
|
"REM-HOSTADDRSORSTATUS", nullToEmpty(ipOrStatusToRem)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public HostUpdateFlowTest() {
|
public HostUpdateFlowTest() {
|
||||||
|
@ -793,6 +795,34 @@ public class HostUpdateFlowTest extends ResourceFlowTestCase<HostUpdateFlow, Hos
|
||||||
runFlow();
|
runFlow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFailure_addRemoveSameStatusValues() throws Exception {
|
||||||
|
createTld("tld");
|
||||||
|
persistActiveDomain("example.tld");
|
||||||
|
setEppHostUpdateInput(
|
||||||
|
"ns1.example.tld",
|
||||||
|
"ns2.example.tld",
|
||||||
|
"<host:status s=\"clientUpdateProhibited\"/>",
|
||||||
|
"<host:status s=\"clientUpdateProhibited\"/>");
|
||||||
|
persistActiveHost(oldHostName());
|
||||||
|
thrown.expect(AddRemoveSameValueException.class);
|
||||||
|
runFlow();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFailure_addRemoveSameInetAddresses() throws Exception {
|
||||||
|
createTld("tld");
|
||||||
|
persistActiveDomain("example.tld");
|
||||||
|
setEppHostUpdateInput(
|
||||||
|
"ns1.example.tld",
|
||||||
|
"ns2.example.tld",
|
||||||
|
"<host:addr ip=\"v4\">192.0.2.22</host:addr>",
|
||||||
|
"<host:addr ip=\"v4\">192.0.2.22</host:addr>");
|
||||||
|
persistActiveHost(oldHostName());
|
||||||
|
thrown.expect(AddRemoveSameValueException.class);
|
||||||
|
runFlow();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFailure_clientProhibitedStatusValue() throws Exception {
|
public void testFailure_clientProhibitedStatusValue() throws Exception {
|
||||||
createTld("tld");
|
createTld("tld");
|
||||||
|
|
|
@ -5,11 +5,11 @@
|
||||||
xmlns:host="urn:ietf:params:xml:ns:host-1.0">
|
xmlns:host="urn:ietf:params:xml:ns:host-1.0">
|
||||||
<host:name>%OLD-HOSTNAME%</host:name>
|
<host:name>%OLD-HOSTNAME%</host:name>
|
||||||
<host:add>
|
<host:add>
|
||||||
%ADD-HOSTADDRS%
|
%ADD-HOSTADDRSORSTATUS%
|
||||||
<host:status s="clientUpdateProhibited"/>
|
<host:status s="clientUpdateProhibited"/>
|
||||||
</host:add>
|
</host:add>
|
||||||
<host:rem>
|
<host:rem>
|
||||||
%REM-HOSTADDRS%
|
%REM-HOSTADDRSORSTATUS%
|
||||||
</host:rem>
|
</host:rem>
|
||||||
<host:chg>
|
<host:chg>
|
||||||
<host:name>%NEW-HOSTNAME%</host:name>
|
<host:name>%NEW-HOSTNAME%</host:name>
|
||||||
|
|
|
@ -16,14 +16,10 @@ package google.registry.model.contact;
|
||||||
|
|
||||||
import static google.registry.flows.EppXmlTransformer.marshalInput;
|
import static google.registry.flows.EppXmlTransformer.marshalInput;
|
||||||
import static google.registry.flows.EppXmlTransformer.validateInput;
|
import static google.registry.flows.EppXmlTransformer.validateInput;
|
||||||
import static google.registry.testing.ContactResourceSubject.assertAboutContacts;
|
|
||||||
import static google.registry.testing.DatastoreHelper.createTld;
|
|
||||||
import static google.registry.xml.ValidationMode.LENIENT;
|
import static google.registry.xml.ValidationMode.LENIENT;
|
||||||
import static google.registry.xml.XmlTestUtils.assertXmlEquals;
|
import static google.registry.xml.XmlTestUtils.assertXmlEquals;
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import google.registry.model.contact.PostalInfo.Type;
|
|
||||||
import google.registry.testing.AppEngineRule;
|
import google.registry.testing.AppEngineRule;
|
||||||
import google.registry.testing.EppLoader;
|
import google.registry.testing.EppLoader;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
|
@ -103,75 +99,4 @@ public class ContactCommandTest {
|
||||||
public void testTransferRequest() throws Exception {
|
public void testTransferRequest() throws Exception {
|
||||||
doXmlRoundtripTest("contact_transfer_request.xml");
|
doXmlRoundtripTest("contact_transfer_request.xml");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testPostalInfoOverlay() {
|
|
||||||
createTld("foo");
|
|
||||||
|
|
||||||
ContactResource contact = new ContactResource.Builder()
|
|
||||||
.setLocalizedPostalInfo(new PostalInfo.Builder()
|
|
||||||
.setType(Type.LOCALIZED)
|
|
||||||
.setName("loc name")
|
|
||||||
.build())
|
|
||||||
.setInternationalizedPostalInfo(new PostalInfo.Builder()
|
|
||||||
.setType(Type.INTERNATIONALIZED)
|
|
||||||
.setName("int name")
|
|
||||||
.build())
|
|
||||||
.build();
|
|
||||||
ContactCommand.Update.Change change = new ContactCommand.Update.Change();
|
|
||||||
|
|
||||||
// Updating one field of the loc should delete the int and leave the loc otherwise untouched.
|
|
||||||
change.postalInfo = ImmutableList.of(new PostalInfo.Builder()
|
|
||||||
.setType(Type.LOCALIZED)
|
|
||||||
.setOrg("org")
|
|
||||||
.build());
|
|
||||||
ContactResource.Builder builder = contact.asBuilder();
|
|
||||||
change.applyTo(builder);
|
|
||||||
ContactResource changed = builder.build();
|
|
||||||
assertAboutContacts().that(changed)
|
|
||||||
.hasNullInternationalizedPostalInfo().and()
|
|
||||||
.hasLocalizedPostalInfo(new PostalInfo.Builder()
|
|
||||||
.setType(Type.LOCALIZED)
|
|
||||||
.setName("loc name")
|
|
||||||
.setOrg("org")
|
|
||||||
.build());
|
|
||||||
|
|
||||||
// Updating one field of the int should delete the loc and leave the int otherwise untouched.
|
|
||||||
change.postalInfo = ImmutableList.of(new PostalInfo.Builder()
|
|
||||||
.setType(Type.INTERNATIONALIZED)
|
|
||||||
.setOrg("org")
|
|
||||||
.build());
|
|
||||||
builder = contact.asBuilder();
|
|
||||||
change.applyTo(builder);
|
|
||||||
changed = builder.build();
|
|
||||||
assertAboutContacts().that(changed)
|
|
||||||
.hasNullLocalizedPostalInfo().and()
|
|
||||||
.hasInternationalizedPostalInfo(new PostalInfo.Builder()
|
|
||||||
.setType(Type.INTERNATIONALIZED)
|
|
||||||
.setName("int name")
|
|
||||||
.setOrg("org")
|
|
||||||
.build());
|
|
||||||
|
|
||||||
// Updating one field of the int and touching the loc with no changes should preserve both.
|
|
||||||
change.postalInfo = ImmutableList.of(
|
|
||||||
new PostalInfo.Builder()
|
|
||||||
.setType(Type.INTERNATIONALIZED)
|
|
||||||
.setName("new int name")
|
|
||||||
.build(),
|
|
||||||
new PostalInfo.Builder()
|
|
||||||
.setType(Type.LOCALIZED)
|
|
||||||
.build());
|
|
||||||
builder = contact.asBuilder();
|
|
||||||
change.applyTo(builder);
|
|
||||||
changed = builder.build();
|
|
||||||
assertAboutContacts().that(changed)
|
|
||||||
.hasLocalizedPostalInfo(new PostalInfo.Builder()
|
|
||||||
.setType(Type.LOCALIZED)
|
|
||||||
.setName("loc name")
|
|
||||||
.build()).and()
|
|
||||||
.hasInternationalizedPostalInfo(new PostalInfo.Builder()
|
|
||||||
.setType(Type.INTERNATIONALIZED)
|
|
||||||
.setName("new int name")
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue