mirror of
https://github.com/google/nomulus.git
synced 2025-05-14 00:17:20 +02:00
Flatten the contact flows
There was very little meat in the contact hierarchy and it flattened quiet easily. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=133080191
This commit is contained in:
parent
bf9a3a0fb2
commit
99af33328d
22 changed files with 682 additions and 154 deletions
|
@ -15,34 +15,46 @@
|
||||||
package google.registry.flows.contact;
|
package google.registry.flows.contact;
|
||||||
|
|
||||||
import static google.registry.model.EppResourceUtils.checkResourcesExist;
|
import static google.registry.model.EppResourceUtils.checkResourcesExist;
|
||||||
|
import static google.registry.model.eppoutput.Result.Code.Success;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import google.registry.flows.ResourceCheckFlow;
|
import google.registry.config.ConfigModule.Config;
|
||||||
|
import google.registry.flows.EppException;
|
||||||
|
import google.registry.flows.LoggedInFlow;
|
||||||
|
import google.registry.flows.exceptions.TooManyResourceChecksException;
|
||||||
import google.registry.model.contact.ContactCommand.Check;
|
import google.registry.model.contact.ContactCommand.Check;
|
||||||
import google.registry.model.contact.ContactResource;
|
import google.registry.model.contact.ContactResource;
|
||||||
import google.registry.model.eppoutput.CheckData;
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
import google.registry.model.eppoutput.CheckData.ContactCheck;
|
import google.registry.model.eppoutput.CheckData.ContactCheck;
|
||||||
import google.registry.model.eppoutput.CheckData.ContactCheckData;
|
import google.registry.model.eppoutput.CheckData.ContactCheckData;
|
||||||
|
import google.registry.model.eppoutput.EppOutput;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An EPP flow that checks whether a contact can be provisioned.
|
* An EPP flow that checks whether a contact can be provisioned.
|
||||||
*
|
*
|
||||||
* @error {@link google.registry.flows.ResourceCheckFlow.TooManyResourceChecksException}
|
* @error {@link google.registry.flows.exceptions.TooManyResourceChecksException}
|
||||||
*/
|
*/
|
||||||
public class ContactCheckFlow extends ResourceCheckFlow<ContactResource, Check> {
|
public class ContactCheckFlow extends LoggedInFlow {
|
||||||
|
|
||||||
|
@Inject ResourceCommand resourceCommand;
|
||||||
|
@Inject @Config("maxChecks") int maxChecks;
|
||||||
@Inject ContactCheckFlow() {}
|
@Inject ContactCheckFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected CheckData getCheckData() {
|
public final EppOutput run() throws EppException {
|
||||||
Set<String> existingIds = checkResourcesExist(resourceClass, targetIds, now);
|
List<String> targetIds = ((Check) resourceCommand).getTargetIds();
|
||||||
|
if (targetIds.size() > maxChecks) {
|
||||||
|
throw new TooManyResourceChecksException(maxChecks);
|
||||||
|
}
|
||||||
|
Set<String> existingIds = checkResourcesExist(ContactResource.class, targetIds, now);
|
||||||
ImmutableList.Builder<ContactCheck> checks = new ImmutableList.Builder<>();
|
ImmutableList.Builder<ContactCheck> checks = new ImmutableList.Builder<>();
|
||||||
for (String id : targetIds) {
|
for (String id : targetIds) {
|
||||||
boolean unused = !existingIds.contains(id);
|
boolean unused = !existingIds.contains(id);
|
||||||
checks.add(ContactCheck.create(unused, id, unused ? null : "In use"));
|
checks.add(ContactCheck.create(unused, id, unused ? null : "In use"));
|
||||||
}
|
}
|
||||||
return ContactCheckData.create(checks.build());
|
return createOutput(Success, ContactCheckData.create(checks.build()), null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,15 +17,24 @@ package google.registry.flows.contact;
|
||||||
import static google.registry.flows.contact.ContactFlowUtils.validateAsciiPostalInfo;
|
import static google.registry.flows.contact.ContactFlowUtils.validateAsciiPostalInfo;
|
||||||
import static google.registry.flows.contact.ContactFlowUtils.validateContactAgainstPolicy;
|
import static google.registry.flows.contact.ContactFlowUtils.validateContactAgainstPolicy;
|
||||||
import static google.registry.model.EppResourceUtils.createContactHostRoid;
|
import static google.registry.model.EppResourceUtils.createContactHostRoid;
|
||||||
|
import static google.registry.model.EppResourceUtils.loadByUniqueId;
|
||||||
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 com.googlecode.objectify.Key;
|
||||||
import google.registry.flows.EppException;
|
import google.registry.flows.EppException;
|
||||||
import google.registry.flows.ResourceCreateFlow;
|
import google.registry.flows.LoggedInFlow;
|
||||||
|
import google.registry.flows.TransactionalFlow;
|
||||||
|
import google.registry.flows.exceptions.ResourceAlreadyExistsException;
|
||||||
import google.registry.model.contact.ContactCommand.Create;
|
import google.registry.model.contact.ContactCommand.Create;
|
||||||
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.domain.metadata.MetadataExtension;
|
||||||
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
import google.registry.model.eppoutput.CreateData.ContactCreateData;
|
import google.registry.model.eppoutput.CreateData.ContactCreateData;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppOutput;
|
||||||
|
import google.registry.model.index.EppResourceIndex;
|
||||||
|
import google.registry.model.index.ForeignKeyIndex;
|
||||||
import google.registry.model.ofy.ObjectifyService;
|
import google.registry.model.ofy.ObjectifyService;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -33,37 +42,46 @@ import javax.inject.Inject;
|
||||||
/**
|
/**
|
||||||
* An EPP flow that creates a new contact resource.
|
* An EPP flow that creates a new contact resource.
|
||||||
*
|
*
|
||||||
* @error {@link google.registry.flows.ResourceCreateFlow.ResourceAlreadyExistsException}
|
* @error {@link google.registry.flows.exceptions.ResourceAlreadyExistsException}
|
||||||
* @error {@link ContactFlowUtils.BadInternationalizedPostalInfoException}
|
* @error {@link ContactFlowUtils.BadInternationalizedPostalInfoException}
|
||||||
* @error {@link ContactFlowUtils.DeclineContactDisclosureFieldDisallowedPolicyException}
|
* @error {@link ContactFlowUtils.DeclineContactDisclosureFieldDisallowedPolicyException}
|
||||||
*/
|
*/
|
||||||
public class ContactCreateFlow extends ResourceCreateFlow<ContactResource, Builder, Create> {
|
public class ContactCreateFlow extends LoggedInFlow implements TransactionalFlow {
|
||||||
|
|
||||||
|
@Inject ResourceCommand resourceCommand;
|
||||||
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
@Inject ContactCreateFlow() {}
|
@Inject ContactCreateFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected EppOutput getOutput() {
|
protected final void initLoggedInFlow() throws EppException {
|
||||||
return createOutput(Success, ContactCreateData.create(newResource.getContactId(), now));
|
registerExtensions(MetadataExtension.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String createFlowRepoId() {
|
protected final EppOutput run() throws EppException {
|
||||||
return createContactHostRoid(ObjectifyService.allocateId());
|
Create command = (Create) resourceCommand;
|
||||||
|
if (loadByUniqueId(ContactResource.class, command.getTargetId(), now) != null) {
|
||||||
|
throw new ResourceAlreadyExistsException(command.getTargetId());
|
||||||
}
|
}
|
||||||
|
Builder builder = new Builder();
|
||||||
@Override
|
command.applyTo(builder);
|
||||||
protected void verifyNewStateIsAllowed() throws EppException {
|
ContactResource newResource = builder
|
||||||
|
.setCreationClientId(getClientId())
|
||||||
|
.setCurrentSponsorClientId(getClientId())
|
||||||
|
.setRepoId(createContactHostRoid(ObjectifyService.allocateId()))
|
||||||
|
.build();
|
||||||
validateAsciiPostalInfo(newResource.getInternationalizedPostalInfo());
|
validateAsciiPostalInfo(newResource.getInternationalizedPostalInfo());
|
||||||
validateContactAgainstPolicy(newResource);
|
validateContactAgainstPolicy(newResource);
|
||||||
}
|
historyBuilder
|
||||||
|
.setType(HistoryEntry.Type.CONTACT_CREATE)
|
||||||
@Override
|
.setModificationTime(now)
|
||||||
protected boolean storeXmlInHistoryEntry() {
|
.setXmlBytes(null) // We don't want to store contact details in the history entry.
|
||||||
return false;
|
.setParent(Key.create(newResource));
|
||||||
}
|
ofy().save().entities(
|
||||||
|
newResource,
|
||||||
@Override
|
historyBuilder.build(),
|
||||||
protected final HistoryEntry.Type getHistoryEntryType() {
|
ForeignKeyIndex.create(newResource, newResource.getDeletionTime()),
|
||||||
return HistoryEntry.Type.CONTACT_CREATE;
|
EppResourceIndex.create(Key.create(newResource)));
|
||||||
|
return createOutput(Success, ContactCreateData.create(newResource.getContactId(), now));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,61 +14,87 @@
|
||||||
|
|
||||||
package google.registry.flows.contact;
|
package google.registry.flows.contact;
|
||||||
|
|
||||||
import static google.registry.model.EppResourceUtils.queryDomainsUsingResource;
|
import static google.registry.flows.ResourceFlowUtils.failfastForAsyncDelete;
|
||||||
|
import static google.registry.flows.ResourceFlowUtils.verifyAuthInfoForResource;
|
||||||
|
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
|
||||||
|
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
|
||||||
|
import static google.registry.model.EppResourceUtils.loadByUniqueId;
|
||||||
|
import static google.registry.model.eppoutput.Result.Code.SuccessWithActionPending;
|
||||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.googlecode.objectify.Key;
|
import com.googlecode.objectify.Key;
|
||||||
import google.registry.config.RegistryEnvironment;
|
import google.registry.config.ConfigModule.Config;
|
||||||
import google.registry.flows.EppException;
|
import google.registry.flows.EppException;
|
||||||
import google.registry.flows.ResourceAsyncDeleteFlow;
|
import google.registry.flows.LoggedInFlow;
|
||||||
|
import google.registry.flows.TransactionalFlow;
|
||||||
import google.registry.flows.async.AsyncFlowUtils;
|
import google.registry.flows.async.AsyncFlowUtils;
|
||||||
import google.registry.flows.async.DeleteContactResourceAction;
|
import google.registry.flows.async.DeleteContactResourceAction;
|
||||||
import google.registry.flows.async.DeleteEppResourceAction;
|
import google.registry.flows.async.DeleteEppResourceAction;
|
||||||
|
import google.registry.flows.exceptions.ResourceToMutateDoesNotExistException;
|
||||||
import google.registry.model.contact.ContactCommand.Delete;
|
import google.registry.model.contact.ContactCommand.Delete;
|
||||||
import google.registry.model.contact.ContactResource;
|
import google.registry.model.contact.ContactResource;
|
||||||
import google.registry.model.contact.ContactResource.Builder;
|
|
||||||
import google.registry.model.domain.DomainBase;
|
import google.registry.model.domain.DomainBase;
|
||||||
|
import google.registry.model.domain.metadata.MetadataExtension;
|
||||||
|
import google.registry.model.eppcommon.StatusValue;
|
||||||
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
|
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;
|
||||||
|
import org.joda.time.Duration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An EPP flow that deletes a contact resource.
|
* An EPP flow that deletes a contact resource.
|
||||||
*
|
*
|
||||||
* @error {@link google.registry.flows.ResourceAsyncDeleteFlow.ResourceToDeleteIsReferencedException}
|
|
||||||
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException}
|
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException}
|
||||||
* @error {@link google.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException}
|
* @error {@link google.registry.flows.exceptions.ResourceStatusProhibitsOperationException}
|
||||||
* @error {@link google.registry.flows.SingleResourceFlow.ResourceStatusProhibitsOperationException}
|
* @error {@link google.registry.flows.exceptions.ResourceToDeleteIsReferencedException}
|
||||||
|
* @error {@link google.registry.flows.exceptions.ResourceToMutateDoesNotExistException}
|
||||||
*/
|
*/
|
||||||
public class ContactDeleteFlow extends ResourceAsyncDeleteFlow<ContactResource, Builder, Delete> {
|
public class ContactDeleteFlow extends LoggedInFlow implements TransactionalFlow {
|
||||||
|
|
||||||
/** In {@link #isLinkedForFailfast}, check this (arbitrary) number of resources from the query. */
|
private static final ImmutableSet<StatusValue> DISALLOWED_STATUSES = ImmutableSet.of(
|
||||||
private static final int FAILFAST_CHECK_COUNT = 5;
|
StatusValue.LINKED,
|
||||||
|
StatusValue.CLIENT_DELETE_PROHIBITED,
|
||||||
|
StatusValue.PENDING_DELETE,
|
||||||
|
StatusValue.SERVER_DELETE_PROHIBITED);
|
||||||
|
|
||||||
|
@Inject ResourceCommand resourceCommand;
|
||||||
|
@Inject @Config("asyncDeleteFlowMapreduceDelay") Duration mapreduceDelay;
|
||||||
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
@Inject ContactDeleteFlow() {}
|
@Inject ContactDeleteFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isLinkedForFailfast(final Key<ContactResource> key) {
|
protected final void initLoggedInFlow() throws EppException {
|
||||||
// Query for the first few linked domains, and if found, actually load them. The query is
|
registerExtensions(MetadataExtension.class);
|
||||||
// eventually consistent and so might be very stale, but the direct load will not be stale,
|
|
||||||
// just non-transactional. If we find at least one actual reference then we can reliably
|
|
||||||
// fail. If we don't find any, we can't trust the query and need to do the full mapreduce.
|
|
||||||
return Iterables.any(
|
|
||||||
ofy().load().keys(
|
|
||||||
queryDomainsUsingResource(
|
|
||||||
ContactResource.class, key, now, FAILFAST_CHECK_COUNT)).values(),
|
|
||||||
new Predicate<DomainBase>() {
|
|
||||||
@Override
|
|
||||||
public boolean apply(DomainBase domain) {
|
|
||||||
return domain.getReferencedContacts().contains(key);
|
|
||||||
}});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Enqueues a contact resource deletion on the mapreduce queue. */
|
|
||||||
@Override
|
@Override
|
||||||
protected final void enqueueTasks() throws EppException {
|
public final EppOutput run() throws EppException {
|
||||||
|
Delete command = (Delete) resourceCommand;
|
||||||
|
String targetId = command.getTargetId();
|
||||||
|
failfastForAsyncDelete(
|
||||||
|
targetId,
|
||||||
|
now,
|
||||||
|
ContactResource.class,
|
||||||
|
new Function<DomainBase, ImmutableSet<?>>() {
|
||||||
|
@Override
|
||||||
|
public ImmutableSet<?> apply(DomainBase domain) {
|
||||||
|
return domain.getReferencedContacts();
|
||||||
|
}});
|
||||||
|
ContactResource existingResource = loadByUniqueId(ContactResource.class, targetId, now);
|
||||||
|
if (existingResource == null) {
|
||||||
|
throw new ResourceToMutateDoesNotExistException(ContactResource.class, targetId);
|
||||||
|
}
|
||||||
|
verifyNoDisallowedStatuses(existingResource, DISALLOWED_STATUSES);
|
||||||
|
if (command.getAuthInfo() != null) {
|
||||||
|
verifyAuthInfoForResource(command.getAuthInfo(), existingResource);
|
||||||
|
}
|
||||||
|
if (!isSuperuser) {
|
||||||
|
verifyResourceOwnership(getClientId(), existingResource);
|
||||||
|
}
|
||||||
AsyncFlowUtils.enqueueMapreduceAction(
|
AsyncFlowUtils.enqueueMapreduceAction(
|
||||||
DeleteContactResourceAction.class,
|
DeleteContactResourceAction.class,
|
||||||
ImmutableMap.of(
|
ImmutableMap.of(
|
||||||
|
@ -78,11 +104,14 @@ public class ContactDeleteFlow extends ResourceAsyncDeleteFlow<ContactResource,
|
||||||
getClientId(),
|
getClientId(),
|
||||||
DeleteEppResourceAction.PARAM_IS_SUPERUSER,
|
DeleteEppResourceAction.PARAM_IS_SUPERUSER,
|
||||||
Boolean.toString(isSuperuser)),
|
Boolean.toString(isSuperuser)),
|
||||||
RegistryEnvironment.get().config().getAsyncDeleteFlowMapreduceDelay());
|
mapreduceDelay);
|
||||||
}
|
ContactResource newResource =
|
||||||
|
existingResource.asBuilder().addStatusValue(StatusValue.PENDING_DELETE).build();
|
||||||
@Override
|
historyBuilder
|
||||||
protected final HistoryEntry.Type getHistoryEntryType() {
|
.setType(HistoryEntry.Type.CONTACT_PENDING_DELETE)
|
||||||
return HistoryEntry.Type.CONTACT_PENDING_DELETE;
|
.setModificationTime(now)
|
||||||
|
.setParent(Key.create(existingResource));
|
||||||
|
ofy().save().<Object>entities(newResource, historyBuilder.build());
|
||||||
|
return createOutput(SuccessWithActionPending, null, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,17 +14,41 @@
|
||||||
|
|
||||||
package google.registry.flows.contact;
|
package google.registry.flows.contact;
|
||||||
|
|
||||||
import google.registry.flows.ResourceInfoFlow;
|
import static google.registry.flows.ResourceFlowUtils.verifyAuthInfoForResource;
|
||||||
|
import static google.registry.model.EppResourceUtils.cloneResourceWithLinkedStatus;
|
||||||
|
import static google.registry.model.EppResourceUtils.loadByUniqueId;
|
||||||
|
import static google.registry.model.eppoutput.Result.Code.Success;
|
||||||
|
|
||||||
|
import google.registry.flows.EppException;
|
||||||
|
import google.registry.flows.LoggedInFlow;
|
||||||
|
import google.registry.flows.exceptions.ResourceToQueryDoesNotExistException;
|
||||||
import google.registry.model.contact.ContactCommand.Info;
|
import google.registry.model.contact.ContactCommand.Info;
|
||||||
import google.registry.model.contact.ContactResource;
|
import google.registry.model.contact.ContactResource;
|
||||||
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
|
import google.registry.model.eppoutput.EppOutput;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An EPP flow that reads a contact.
|
* An EPP flow that reads a contact.
|
||||||
*
|
*
|
||||||
* @error {@link google.registry.flows.ResourceQueryFlow.ResourceToQueryDoesNotExistException}
|
* @error {@link google.registry.flows.exceptions.ResourceToQueryDoesNotExistException}
|
||||||
*/
|
*/
|
||||||
public class ContactInfoFlow extends ResourceInfoFlow<ContactResource, Info> {
|
public class ContactInfoFlow extends LoggedInFlow {
|
||||||
@Inject ContactInfoFlow() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Inject ResourceCommand resourceCommand;
|
||||||
|
@Inject ContactInfoFlow() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final EppOutput run() throws EppException {
|
||||||
|
Info command = (Info) resourceCommand;
|
||||||
|
String targetId = command.getTargetId();
|
||||||
|
ContactResource existingResource = loadByUniqueId(ContactResource.class, targetId, now);
|
||||||
|
if (existingResource == null) {
|
||||||
|
throw new ResourceToQueryDoesNotExistException(ContactResource.class, targetId);
|
||||||
|
}
|
||||||
|
if (command.getAuthInfo() != null) {
|
||||||
|
verifyAuthInfoForResource(command.getAuthInfo(), existingResource);
|
||||||
|
}
|
||||||
|
return createOutput(Success, cloneResourceWithLinkedStatus(existingResource, now), null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -14,11 +14,31 @@
|
||||||
|
|
||||||
package google.registry.flows.contact;
|
package google.registry.flows.contact;
|
||||||
|
|
||||||
import google.registry.flows.ResourceTransferApproveFlow;
|
import static google.registry.flows.ResourceFlowUtils.createPendingTransferNotificationResponse;
|
||||||
|
import static google.registry.flows.ResourceFlowUtils.createTransferResponse;
|
||||||
|
import static google.registry.flows.ResourceFlowUtils.verifyAuthInfoForResource;
|
||||||
|
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
|
||||||
|
import static google.registry.model.EppResourceUtils.loadByUniqueId;
|
||||||
|
import static google.registry.model.eppoutput.Result.Code.Success;
|
||||||
|
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.googlecode.objectify.Key;
|
||||||
|
import google.registry.flows.EppException;
|
||||||
|
import google.registry.flows.LoggedInFlow;
|
||||||
|
import google.registry.flows.TransactionalFlow;
|
||||||
|
import google.registry.flows.exceptions.NotPendingTransferException;
|
||||||
|
import google.registry.flows.exceptions.ResourceToMutateDoesNotExistException;
|
||||||
import google.registry.model.contact.ContactCommand.Transfer;
|
import google.registry.model.contact.ContactCommand.Transfer;
|
||||||
import google.registry.model.contact.ContactResource;
|
import google.registry.model.contact.ContactResource;
|
||||||
import google.registry.model.contact.ContactResource.Builder;
|
import google.registry.model.domain.metadata.MetadataExtension;
|
||||||
|
import google.registry.model.eppcommon.StatusValue;
|
||||||
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
|
import google.registry.model.eppoutput.EppOutput;
|
||||||
|
import google.registry.model.poll.PollMessage;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
|
import google.registry.model.transfer.TransferData;
|
||||||
|
import google.registry.model.transfer.TransferStatus;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,16 +46,71 @@ import javax.inject.Inject;
|
||||||
*
|
*
|
||||||
* @error {@link google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException}
|
* @error {@link google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException}
|
||||||
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException}
|
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException}
|
||||||
* @error {@link google.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException}
|
* @error {@link google.registry.flows.exceptions.NotPendingTransferException}
|
||||||
* @error {@link google.registry.flows.ResourceMutatePendingTransferFlow.NotPendingTransferException}
|
* @error {@link google.registry.flows.exceptions.ResourceToMutateDoesNotExistException}
|
||||||
*/
|
*/
|
||||||
public class ContactTransferApproveFlow
|
public class ContactTransferApproveFlow extends LoggedInFlow implements TransactionalFlow {
|
||||||
extends ResourceTransferApproveFlow<ContactResource, Builder, Transfer> {
|
|
||||||
|
|
||||||
|
@Inject ResourceCommand resourceCommand;
|
||||||
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
@Inject ContactTransferApproveFlow() {}
|
@Inject ContactTransferApproveFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final HistoryEntry.Type getHistoryEntryType() {
|
protected final void initLoggedInFlow() throws EppException {
|
||||||
return HistoryEntry.Type.CONTACT_TRANSFER_APPROVE;
|
registerExtensions(MetadataExtension.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final EppOutput run() throws EppException {
|
||||||
|
Transfer command = (Transfer) resourceCommand;
|
||||||
|
String targetId = command.getTargetId();
|
||||||
|
ContactResource existingResource = loadByUniqueId(ContactResource.class, targetId, now);
|
||||||
|
if (existingResource == null) {
|
||||||
|
throw new ResourceToMutateDoesNotExistException(ContactResource.class, targetId);
|
||||||
|
}
|
||||||
|
if (command.getAuthInfo() != null) {
|
||||||
|
verifyAuthInfoForResource(command.getAuthInfo(), existingResource);
|
||||||
|
}
|
||||||
|
if (existingResource.getTransferData().getTransferStatus() != TransferStatus.PENDING) {
|
||||||
|
throw new NotPendingTransferException(targetId);
|
||||||
|
}
|
||||||
|
verifyResourceOwnership(getClientId(), existingResource);
|
||||||
|
TransferData oldTransferData = existingResource.getTransferData();
|
||||||
|
ContactResource newResource = existingResource.asBuilder()
|
||||||
|
.removeStatusValue(StatusValue.PENDING_TRANSFER)
|
||||||
|
.setLastTransferTime(now)
|
||||||
|
.setCurrentSponsorClientId(existingResource.getTransferData().getGainingClientId())
|
||||||
|
.setTransferData(oldTransferData.asBuilder()
|
||||||
|
.setTransferStatus(TransferStatus.CLIENT_APPROVED)
|
||||||
|
.setPendingTransferExpirationTime(now)
|
||||||
|
.setExtendedRegistrationYears(null)
|
||||||
|
.setServerApproveEntities(null)
|
||||||
|
.setServerApproveBillingEvent(null)
|
||||||
|
.setServerApproveAutorenewEvent(null)
|
||||||
|
.setServerApproveAutorenewPollMessage(null)
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
HistoryEntry historyEntry = historyBuilder
|
||||||
|
.setType(HistoryEntry.Type.CONTACT_TRANSFER_APPROVE)
|
||||||
|
.setModificationTime(now)
|
||||||
|
.setParent(Key.create(existingResource))
|
||||||
|
.build();
|
||||||
|
// Create a poll message for the gaining client.
|
||||||
|
PollMessage gainingPollMessage = new PollMessage.OneTime.Builder()
|
||||||
|
.setClientId(oldTransferData.getGainingClientId())
|
||||||
|
.setEventTime(now)
|
||||||
|
.setMsg(TransferStatus.CLIENT_APPROVED.getMessage())
|
||||||
|
.setResponseData(ImmutableList.of(
|
||||||
|
createTransferResponse(newResource, newResource.getTransferData(), now),
|
||||||
|
createPendingTransferNotificationResponse(
|
||||||
|
existingResource, oldTransferData.getTransferRequestTrid(), true, now)))
|
||||||
|
.setParent(historyEntry)
|
||||||
|
.build();
|
||||||
|
ofy().save().<Object>entities(newResource, historyEntry, gainingPollMessage);
|
||||||
|
// Delete the billing event and poll messages that were written in case the transfer would have
|
||||||
|
// been implicitly server approved.
|
||||||
|
ofy().delete().keys(existingResource.getTransferData().getServerApproveEntities());
|
||||||
|
return createOutput(
|
||||||
|
Success, createTransferResponse(newResource, newResource.getTransferData(), now));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,28 +14,101 @@
|
||||||
|
|
||||||
package google.registry.flows.contact;
|
package google.registry.flows.contact;
|
||||||
|
|
||||||
import google.registry.flows.ResourceTransferCancelFlow;
|
import static google.registry.flows.ResourceFlowUtils.createTransferResponse;
|
||||||
|
import static google.registry.flows.ResourceFlowUtils.verifyAuthInfoForResource;
|
||||||
|
import static google.registry.model.EppResourceUtils.loadByUniqueId;
|
||||||
|
import static google.registry.model.eppoutput.Result.Code.Success;
|
||||||
|
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.googlecode.objectify.Key;
|
||||||
|
import google.registry.flows.EppException;
|
||||||
|
import google.registry.flows.LoggedInFlow;
|
||||||
|
import google.registry.flows.TransactionalFlow;
|
||||||
|
import google.registry.flows.exceptions.NotPendingTransferException;
|
||||||
|
import google.registry.flows.exceptions.NotTransferInitiatorException;
|
||||||
|
import google.registry.flows.exceptions.ResourceToMutateDoesNotExistException;
|
||||||
import google.registry.model.contact.ContactCommand.Transfer;
|
import google.registry.model.contact.ContactCommand.Transfer;
|
||||||
import google.registry.model.contact.ContactResource;
|
import google.registry.model.contact.ContactResource;
|
||||||
import google.registry.model.contact.ContactResource.Builder;
|
import google.registry.model.domain.metadata.MetadataExtension;
|
||||||
|
import google.registry.model.eppcommon.StatusValue;
|
||||||
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
|
import google.registry.model.eppoutput.EppOutput;
|
||||||
|
import google.registry.model.poll.PollMessage;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
|
import google.registry.model.transfer.TransferStatus;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An EPP flow that cancels a pending transfer on a {@link ContactResource}.
|
* An EPP flow that cancels a pending transfer on a {@link ContactResource}.
|
||||||
*
|
*
|
||||||
* @error {@link google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException}
|
* @error {@link google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException}
|
||||||
* @error {@link google.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException}
|
* @error {@link google.registry.flows.exceptions.NotPendingTransferException}
|
||||||
* @error {@link google.registry.flows.ResourceMutatePendingTransferFlow.NotPendingTransferException}
|
* @error {@link google.registry.flows.exceptions.NotTransferInitiatorException}
|
||||||
* @error {@link google.registry.flows.ResourceTransferCancelFlow.NotTransferInitiatorException}
|
* @error {@link google.registry.flows.exceptions.ResourceToMutateDoesNotExistException}
|
||||||
*/
|
*/
|
||||||
public class ContactTransferCancelFlow
|
public class ContactTransferCancelFlow extends LoggedInFlow implements TransactionalFlow {
|
||||||
extends ResourceTransferCancelFlow<ContactResource, Builder, Transfer> {
|
|
||||||
|
|
||||||
|
@Inject ResourceCommand resourceCommand;
|
||||||
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
@Inject ContactTransferCancelFlow() {}
|
@Inject ContactTransferCancelFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final HistoryEntry.Type getHistoryEntryType() {
|
protected final void initLoggedInFlow() throws EppException {
|
||||||
return HistoryEntry.Type.CONTACT_TRANSFER_CANCEL;
|
registerExtensions(MetadataExtension.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected final EppOutput run() throws EppException {
|
||||||
|
Transfer command = (Transfer) resourceCommand;
|
||||||
|
String targetId = command.getTargetId();
|
||||||
|
ContactResource existingResource = loadByUniqueId(ContactResource.class, targetId, now);
|
||||||
|
// Fail if the object doesn't exist or was deleted.
|
||||||
|
if (existingResource == null) {
|
||||||
|
throw new ResourceToMutateDoesNotExistException(ContactResource.class, targetId);
|
||||||
|
}
|
||||||
|
if (command.getAuthInfo() != null) {
|
||||||
|
verifyAuthInfoForResource(command.getAuthInfo(), existingResource);
|
||||||
|
}
|
||||||
|
// Fail if object doesn't have a pending transfer, or if authinfo doesn't match. */
|
||||||
|
if (existingResource.getTransferData().getTransferStatus() != TransferStatus.PENDING) {
|
||||||
|
throw new NotPendingTransferException(targetId);
|
||||||
|
}
|
||||||
|
// TODO(b/18997997): Determine if authInfo is necessary to cancel a transfer.
|
||||||
|
if (!getClientId().equals(existingResource.getTransferData().getGainingClientId())) {
|
||||||
|
throw new NotTransferInitiatorException();
|
||||||
|
}
|
||||||
|
ContactResource newResource = existingResource.asBuilder()
|
||||||
|
.removeStatusValue(StatusValue.PENDING_TRANSFER)
|
||||||
|
.setTransferData(existingResource.getTransferData().asBuilder()
|
||||||
|
.setTransferStatus(TransferStatus.CLIENT_CANCELLED)
|
||||||
|
.setPendingTransferExpirationTime(now)
|
||||||
|
.setExtendedRegistrationYears(null)
|
||||||
|
.setServerApproveEntities(null)
|
||||||
|
.setServerApproveBillingEvent(null)
|
||||||
|
.setServerApproveAutorenewEvent(null)
|
||||||
|
.setServerApproveAutorenewPollMessage(null)
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
HistoryEntry historyEntry = historyBuilder
|
||||||
|
.setType(HistoryEntry.Type.CONTACT_TRANSFER_CANCEL)
|
||||||
|
.setModificationTime(now)
|
||||||
|
.setParent(Key.create(existingResource))
|
||||||
|
.build();
|
||||||
|
// Create a poll message for the losing client.
|
||||||
|
PollMessage losingPollMessage = new PollMessage.OneTime.Builder()
|
||||||
|
.setClientId(existingResource.getTransferData().getLosingClientId())
|
||||||
|
.setEventTime(now)
|
||||||
|
.setMsg(TransferStatus.CLIENT_CANCELLED.getMessage())
|
||||||
|
.setResponseData(ImmutableList.of(
|
||||||
|
createTransferResponse(newResource, newResource.getTransferData(), now)))
|
||||||
|
.setParent(historyEntry)
|
||||||
|
.build();
|
||||||
|
ofy().save().<Object>entities(newResource, historyEntry, losingPollMessage);
|
||||||
|
// Delete the billing event and poll messages that were written in case the transfer would have
|
||||||
|
// been implicitly server approved.
|
||||||
|
ofy().delete().keys(existingResource.getTransferData().getServerApproveEntities());
|
||||||
|
return createOutput(
|
||||||
|
Success, createTransferResponse(newResource, newResource.getTransferData(), now));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,19 +14,59 @@
|
||||||
|
|
||||||
package google.registry.flows.contact;
|
package google.registry.flows.contact;
|
||||||
|
|
||||||
import google.registry.flows.ResourceTransferQueryFlow;
|
import static google.registry.flows.ResourceFlowUtils.createTransferResponse;
|
||||||
|
import static google.registry.flows.ResourceFlowUtils.verifyAuthInfoForResource;
|
||||||
|
import static google.registry.model.EppResourceUtils.loadByUniqueId;
|
||||||
|
import static google.registry.model.eppoutput.Result.Code.Success;
|
||||||
|
|
||||||
|
import google.registry.flows.EppException;
|
||||||
|
import google.registry.flows.LoggedInFlow;
|
||||||
|
import google.registry.flows.exceptions.NoTransferHistoryToQueryException;
|
||||||
|
import google.registry.flows.exceptions.NotAuthorizedToViewTransferException;
|
||||||
|
import google.registry.flows.exceptions.ResourceToQueryDoesNotExistException;
|
||||||
import google.registry.model.contact.ContactCommand.Transfer;
|
import google.registry.model.contact.ContactCommand.Transfer;
|
||||||
import google.registry.model.contact.ContactResource;
|
import google.registry.model.contact.ContactResource;
|
||||||
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
|
import google.registry.model.eppoutput.EppOutput;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An EPP flow that queries a pending transfer on a {@link ContactResource}.
|
* An EPP flow that queries a pending transfer on a {@link ContactResource}.
|
||||||
*
|
*
|
||||||
* @error {@link google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException}
|
* @error {@link google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException}
|
||||||
* @error {@link google.registry.flows.ResourceQueryFlow.ResourceToQueryDoesNotExistException}
|
* @error {@link google.registry.flows.exceptions.NoTransferHistoryToQueryException}
|
||||||
* @error {@link google.registry.flows.ResourceTransferQueryFlow.NoTransferHistoryToQueryException}
|
* @error {@link google.registry.flows.exceptions.NotAuthorizedToViewTransferException}
|
||||||
* @error {@link google.registry.flows.ResourceTransferQueryFlow.NotAuthorizedToViewTransferException}
|
* @error {@link google.registry.flows.exceptions.ResourceToQueryDoesNotExistException}
|
||||||
*/
|
*/
|
||||||
public class ContactTransferQueryFlow extends ResourceTransferQueryFlow<ContactResource, Transfer> {
|
public class ContactTransferQueryFlow extends LoggedInFlow {
|
||||||
|
|
||||||
|
@Inject ResourceCommand resourceCommand;
|
||||||
@Inject ContactTransferQueryFlow() {}
|
@Inject ContactTransferQueryFlow() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final EppOutput run() throws EppException {
|
||||||
|
Transfer command = (Transfer) resourceCommand;
|
||||||
|
String targetId = command.getTargetId();
|
||||||
|
ContactResource existingResource = loadByUniqueId(ContactResource.class, targetId, now);
|
||||||
|
if (existingResource == null) {
|
||||||
|
throw new ResourceToQueryDoesNotExistException(ContactResource.class, targetId);
|
||||||
|
}
|
||||||
|
if (command.getAuthInfo() != null) {
|
||||||
|
verifyAuthInfoForResource(command.getAuthInfo(), existingResource);
|
||||||
|
}
|
||||||
|
// Most of the fields on the transfer response are required, so there's no way to return valid
|
||||||
|
// XML if the object has never been transferred (and hence the fields aren't populated).
|
||||||
|
if (existingResource.getTransferData().getTransferStatus() == null) {
|
||||||
|
throw new NoTransferHistoryToQueryException();
|
||||||
|
}
|
||||||
|
// Note that the authorization info on the command (if present) has already been verified by the
|
||||||
|
// parent class. If it's present, then the other checks are unnecessary.
|
||||||
|
if (command.getAuthInfo() == null
|
||||||
|
&& !getClientId().equals(existingResource.getTransferData().getGainingClientId())
|
||||||
|
&& !getClientId().equals(existingResource.getTransferData().getLosingClientId())) {
|
||||||
|
throw new NotAuthorizedToViewTransferException();
|
||||||
|
}
|
||||||
|
return createOutput(
|
||||||
|
Success, createTransferResponse(existingResource, existingResource.getTransferData(), now));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,11 +14,31 @@
|
||||||
|
|
||||||
package google.registry.flows.contact;
|
package google.registry.flows.contact;
|
||||||
|
|
||||||
import google.registry.flows.ResourceTransferRejectFlow;
|
import static google.registry.flows.ResourceFlowUtils.createPendingTransferNotificationResponse;
|
||||||
|
import static google.registry.flows.ResourceFlowUtils.createTransferResponse;
|
||||||
|
import static google.registry.flows.ResourceFlowUtils.verifyAuthInfoForResource;
|
||||||
|
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
|
||||||
|
import static google.registry.model.EppResourceUtils.loadByUniqueId;
|
||||||
|
import static google.registry.model.eppoutput.Result.Code.Success;
|
||||||
|
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.googlecode.objectify.Key;
|
||||||
|
import google.registry.flows.EppException;
|
||||||
|
import google.registry.flows.LoggedInFlow;
|
||||||
|
import google.registry.flows.TransactionalFlow;
|
||||||
|
import google.registry.flows.exceptions.NotPendingTransferException;
|
||||||
|
import google.registry.flows.exceptions.ResourceToMutateDoesNotExistException;
|
||||||
import google.registry.model.contact.ContactCommand.Transfer;
|
import google.registry.model.contact.ContactCommand.Transfer;
|
||||||
import google.registry.model.contact.ContactResource;
|
import google.registry.model.contact.ContactResource;
|
||||||
import google.registry.model.contact.ContactResource.Builder;
|
import google.registry.model.domain.metadata.MetadataExtension;
|
||||||
|
import google.registry.model.eppcommon.StatusValue;
|
||||||
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
|
import google.registry.model.eppoutput.EppOutput;
|
||||||
|
import google.registry.model.poll.PollMessage;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
|
import google.registry.model.transfer.TransferData;
|
||||||
|
import google.registry.model.transfer.TransferStatus;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,16 +46,68 @@ import javax.inject.Inject;
|
||||||
*
|
*
|
||||||
* @error {@link google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException}
|
* @error {@link google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException}
|
||||||
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException}
|
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException}
|
||||||
* @error {@link google.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException}
|
* @error {@link google.registry.flows.exceptions.NotPendingTransferException}
|
||||||
* @error {@link google.registry.flows.ResourceMutatePendingTransferFlow.NotPendingTransferException}
|
* @error {@link google.registry.flows.exceptions.ResourceToMutateDoesNotExistException}
|
||||||
*/
|
*/
|
||||||
public class ContactTransferRejectFlow
|
public class ContactTransferRejectFlow extends LoggedInFlow implements TransactionalFlow {
|
||||||
extends ResourceTransferRejectFlow<ContactResource, Builder, Transfer> {
|
|
||||||
|
|
||||||
|
@Inject ResourceCommand resourceCommand;
|
||||||
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
@Inject ContactTransferRejectFlow() {}
|
@Inject ContactTransferRejectFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final HistoryEntry.Type getHistoryEntryType() {
|
protected final void initLoggedInFlow() throws EppException {
|
||||||
return HistoryEntry.Type.CONTACT_TRANSFER_REJECT;
|
registerExtensions(MetadataExtension.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected final EppOutput run() throws EppException {
|
||||||
|
Transfer command = (Transfer) resourceCommand;
|
||||||
|
String targetId = command.getTargetId();
|
||||||
|
ContactResource existingResource = loadByUniqueId(ContactResource.class, targetId, now);
|
||||||
|
if (existingResource == null) {
|
||||||
|
throw new ResourceToMutateDoesNotExistException(ContactResource.class, targetId);
|
||||||
|
}
|
||||||
|
if (command.getAuthInfo() != null) {
|
||||||
|
verifyAuthInfoForResource(command.getAuthInfo(), existingResource);
|
||||||
|
}
|
||||||
|
if (existingResource.getTransferData().getTransferStatus() != TransferStatus.PENDING) {
|
||||||
|
throw new NotPendingTransferException(targetId);
|
||||||
|
}
|
||||||
|
verifyResourceOwnership(getClientId(), existingResource);
|
||||||
|
TransferData oldTransferData = existingResource.getTransferData();
|
||||||
|
ContactResource newResource = existingResource.asBuilder()
|
||||||
|
.removeStatusValue(StatusValue.PENDING_TRANSFER)
|
||||||
|
.setTransferData(oldTransferData.asBuilder()
|
||||||
|
.setTransferStatus(TransferStatus.CLIENT_REJECTED)
|
||||||
|
.setPendingTransferExpirationTime(now)
|
||||||
|
.setExtendedRegistrationYears(null)
|
||||||
|
.setServerApproveEntities(null)
|
||||||
|
.setServerApproveBillingEvent(null)
|
||||||
|
.setServerApproveAutorenewEvent(null)
|
||||||
|
.setServerApproveAutorenewPollMessage(null)
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
HistoryEntry historyEntry = historyBuilder
|
||||||
|
.setType(HistoryEntry.Type.CONTACT_TRANSFER_REJECT)
|
||||||
|
.setModificationTime(now)
|
||||||
|
.setParent(Key.create(existingResource))
|
||||||
|
.build();
|
||||||
|
PollMessage.OneTime gainingPollMessage = new PollMessage.OneTime.Builder()
|
||||||
|
.setClientId(oldTransferData.getGainingClientId())
|
||||||
|
.setEventTime(now)
|
||||||
|
.setMsg(TransferStatus.CLIENT_REJECTED.getMessage())
|
||||||
|
.setResponseData(ImmutableList.of(
|
||||||
|
createTransferResponse(newResource, newResource.getTransferData(), now),
|
||||||
|
createPendingTransferNotificationResponse(
|
||||||
|
existingResource, oldTransferData.getTransferRequestTrid(), false, now)))
|
||||||
|
.setParent(historyEntry)
|
||||||
|
.build();
|
||||||
|
ofy().save().<Object>entities(newResource, historyEntry, gainingPollMessage);
|
||||||
|
// Delete the billing event and poll messages that were written in case the transfer would have
|
||||||
|
// been implicitly server approved.
|
||||||
|
ofy().delete().keys(existingResource.getTransferData().getServerApproveEntities());
|
||||||
|
return createOutput(
|
||||||
|
Success, createTransferResponse(newResource, newResource.getTransferData(), now));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,35 +14,151 @@
|
||||||
|
|
||||||
package google.registry.flows.contact;
|
package google.registry.flows.contact;
|
||||||
|
|
||||||
import google.registry.config.RegistryEnvironment;
|
import static google.registry.flows.ResourceFlowUtils.createPendingTransferNotificationResponse;
|
||||||
import google.registry.flows.ResourceTransferRequestFlow;
|
import static google.registry.flows.ResourceFlowUtils.createTransferResponse;
|
||||||
|
import static google.registry.flows.ResourceFlowUtils.verifyAuthInfoForResource;
|
||||||
|
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
|
||||||
|
import static google.registry.model.EppResourceUtils.loadByUniqueId;
|
||||||
|
import static google.registry.model.eppoutput.Result.Code.SuccessWithActionPending;
|
||||||
|
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.googlecode.objectify.Key;
|
||||||
|
import google.registry.config.ConfigModule.Config;
|
||||||
|
import google.registry.flows.EppException;
|
||||||
|
import google.registry.flows.LoggedInFlow;
|
||||||
|
import google.registry.flows.TransactionalFlow;
|
||||||
|
import google.registry.flows.exceptions.AlreadyPendingTransferException;
|
||||||
|
import google.registry.flows.exceptions.MissingTransferRequestAuthInfoException;
|
||||||
|
import google.registry.flows.exceptions.ObjectAlreadySponsoredException;
|
||||||
|
import google.registry.flows.exceptions.ResourceToMutateDoesNotExistException;
|
||||||
import google.registry.model.contact.ContactCommand.Transfer;
|
import google.registry.model.contact.ContactCommand.Transfer;
|
||||||
import google.registry.model.contact.ContactResource;
|
import google.registry.model.contact.ContactResource;
|
||||||
|
import google.registry.model.domain.metadata.MetadataExtension;
|
||||||
|
import google.registry.model.eppcommon.StatusValue;
|
||||||
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
|
import google.registry.model.eppoutput.EppOutput;
|
||||||
|
import google.registry.model.poll.PollMessage;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
|
import google.registry.model.transfer.TransferData;
|
||||||
|
import google.registry.model.transfer.TransferStatus;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
import org.joda.time.Duration;
|
import org.joda.time.Duration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An EPP flow that requests a transfer on a {@link ContactResource}.
|
* An EPP flow that requests a transfer on a {@link ContactResource}.
|
||||||
*
|
*
|
||||||
* @error {@link google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException}
|
* @error {@link google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException}
|
||||||
* @error {@link google.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException}
|
* @error {@link google.registry.flows.exceptions.ResourceToMutateDoesNotExistException}
|
||||||
* @error {@link google.registry.flows.ResourceTransferRequestFlow.AlreadyPendingTransferException}
|
* @error {@link google.registry.flows.exceptions.AlreadyPendingTransferException}
|
||||||
* @error {@link google.registry.flows.ResourceTransferRequestFlow.MissingTransferRequestAuthInfoException}
|
* @error {@link google.registry.flows.exceptions.MissingTransferRequestAuthInfoException}
|
||||||
* @error {@link google.registry.flows.ResourceTransferRequestFlow.ObjectAlreadySponsoredException}
|
* @error {@link google.registry.flows.exceptions.ObjectAlreadySponsoredException}
|
||||||
*/
|
*/
|
||||||
public class ContactTransferRequestFlow
|
public class ContactTransferRequestFlow extends LoggedInFlow implements TransactionalFlow {
|
||||||
extends ResourceTransferRequestFlow<ContactResource, Transfer> {
|
|
||||||
|
|
||||||
|
private static final ImmutableSet<StatusValue> DISALLOWED_STATUSES = ImmutableSet.of(
|
||||||
|
StatusValue.CLIENT_TRANSFER_PROHIBITED,
|
||||||
|
StatusValue.PENDING_DELETE,
|
||||||
|
StatusValue.SERVER_TRANSFER_PROHIBITED);
|
||||||
|
|
||||||
|
@Inject ResourceCommand resourceCommand;
|
||||||
|
@Inject @Config("contactAutomaticTransferLength") Duration automaticTransferLength;
|
||||||
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
@Inject ContactTransferRequestFlow() {}
|
@Inject ContactTransferRequestFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final HistoryEntry.Type getHistoryEntryType() {
|
protected final void initLoggedInFlow() throws EppException {
|
||||||
return HistoryEntry.Type.CONTACT_TRANSFER_REQUEST;
|
registerExtensions(MetadataExtension.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Duration getAutomaticTransferLength() {
|
protected final EppOutput run() throws EppException {
|
||||||
return RegistryEnvironment.get().config().getContactAutomaticTransferLength();
|
Transfer command = (Transfer) resourceCommand;
|
||||||
|
String targetId = command.getTargetId();
|
||||||
|
ContactResource existingResource = loadByUniqueId(ContactResource.class, targetId, now);
|
||||||
|
if (existingResource == null) {
|
||||||
|
throw new ResourceToMutateDoesNotExistException(ContactResource.class, targetId);
|
||||||
|
}
|
||||||
|
if (command.getAuthInfo() == null) {
|
||||||
|
throw new MissingTransferRequestAuthInfoException();
|
||||||
|
}
|
||||||
|
verifyAuthInfoForResource(command.getAuthInfo(), existingResource);
|
||||||
|
// Verify that the resource does not already have a pending transfer.
|
||||||
|
if (TransferStatus.PENDING.equals(existingResource.getTransferData().getTransferStatus())) {
|
||||||
|
throw new AlreadyPendingTransferException(targetId);
|
||||||
|
}
|
||||||
|
String gainingClientId = getClientId();
|
||||||
|
String losingClientId = existingResource.getCurrentSponsorClientId();
|
||||||
|
// Verify that this client doesn't already sponsor this resource.
|
||||||
|
if (gainingClientId.equals(losingClientId)) {
|
||||||
|
throw new ObjectAlreadySponsoredException();
|
||||||
|
}
|
||||||
|
verifyAuthInfoForResource(command.getAuthInfo(), existingResource);
|
||||||
|
verifyNoDisallowedStatuses(existingResource, DISALLOWED_STATUSES);
|
||||||
|
HistoryEntry historyEntry = historyBuilder
|
||||||
|
.setType(HistoryEntry.Type.CONTACT_TRANSFER_REQUEST)
|
||||||
|
.setModificationTime(now)
|
||||||
|
.setParent(Key.create(existingResource))
|
||||||
|
.build();
|
||||||
|
DateTime transferExpirationTime = now.plus(automaticTransferLength);
|
||||||
|
TransferData serverApproveTransferData = new TransferData.Builder()
|
||||||
|
.setTransferRequestTime(now)
|
||||||
|
.setTransferRequestTrid(trid)
|
||||||
|
.setGainingClientId(gainingClientId)
|
||||||
|
.setLosingClientId(losingClientId)
|
||||||
|
.setPendingTransferExpirationTime(transferExpirationTime)
|
||||||
|
.setTransferStatus(TransferStatus.SERVER_APPROVED)
|
||||||
|
.build();
|
||||||
|
// If the transfer is server approved, this message will be sent to the losing registrar. */
|
||||||
|
PollMessage.OneTime serverApproveLosingPollMessage = new PollMessage.OneTime.Builder()
|
||||||
|
.setClientId(losingClientId)
|
||||||
|
.setMsg(TransferStatus.SERVER_APPROVED.getMessage())
|
||||||
|
.setParent(historyEntry)
|
||||||
|
.setEventTime(transferExpirationTime)
|
||||||
|
.setResponseData(ImmutableList.of(
|
||||||
|
createTransferResponse(existingResource, serverApproveTransferData, now)))
|
||||||
|
.build();
|
||||||
|
// If the transfer is server approved, this message will be sent to the gaining registrar. */
|
||||||
|
PollMessage.OneTime serverApproveGainingPollMessage = new PollMessage.OneTime.Builder()
|
||||||
|
.setClientId(gainingClientId)
|
||||||
|
.setMsg(TransferStatus.SERVER_APPROVED.getMessage())
|
||||||
|
.setParent(historyEntry)
|
||||||
|
.setEventTime(transferExpirationTime)
|
||||||
|
.setResponseData(ImmutableList.of(
|
||||||
|
createTransferResponse(existingResource, serverApproveTransferData, now),
|
||||||
|
createPendingTransferNotificationResponse(existingResource, trid, true, now)))
|
||||||
|
.build();
|
||||||
|
TransferData pendingTransferData = serverApproveTransferData.asBuilder()
|
||||||
|
.setTransferStatus(TransferStatus.PENDING)
|
||||||
|
.setServerApproveEntities(
|
||||||
|
ImmutableSet.<Key<? extends TransferData.TransferServerApproveEntity>>of(
|
||||||
|
Key.create(serverApproveGainingPollMessage),
|
||||||
|
Key.create(serverApproveLosingPollMessage)))
|
||||||
|
.build();
|
||||||
|
// When a transfer is requested, a poll message is created to notify the losing registrar.
|
||||||
|
PollMessage.OneTime requestPollMessage = new PollMessage.OneTime.Builder()
|
||||||
|
.setClientId(losingClientId)
|
||||||
|
.setMsg(TransferStatus.PENDING.getMessage())
|
||||||
|
.setParent(historyEntry)
|
||||||
|
.setEventTime(now)
|
||||||
|
.setResponseData(ImmutableList.of(
|
||||||
|
createTransferResponse(existingResource, pendingTransferData, now)))
|
||||||
|
.build();
|
||||||
|
ContactResource newResource = existingResource.asBuilder()
|
||||||
|
.setTransferData(pendingTransferData)
|
||||||
|
.addStatusValue(StatusValue.PENDING_TRANSFER)
|
||||||
|
.build();
|
||||||
|
ofy().save().<Object>entities(
|
||||||
|
newResource,
|
||||||
|
historyEntry,
|
||||||
|
requestPollMessage,
|
||||||
|
serverApproveGainingPollMessage,
|
||||||
|
serverApproveLosingPollMessage);
|
||||||
|
return createOutput(
|
||||||
|
SuccessWithActionPending,
|
||||||
|
createTransferResponse(newResource, newResource.getTransferData(), now),
|
||||||
|
null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,14 +14,33 @@
|
||||||
|
|
||||||
package google.registry.flows.contact;
|
package google.registry.flows.contact;
|
||||||
|
|
||||||
|
import static google.registry.flows.ResourceFlowUtils.verifyAuthInfoForResource;
|
||||||
|
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
|
||||||
|
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
|
||||||
import static google.registry.flows.contact.ContactFlowUtils.validateAsciiPostalInfo;
|
import static google.registry.flows.contact.ContactFlowUtils.validateAsciiPostalInfo;
|
||||||
import static google.registry.flows.contact.ContactFlowUtils.validateContactAgainstPolicy;
|
import static google.registry.flows.contact.ContactFlowUtils.validateContactAgainstPolicy;
|
||||||
|
import static google.registry.model.EppResourceUtils.loadByUniqueId;
|
||||||
|
import static google.registry.model.eppoutput.Result.Code.Success;
|
||||||
|
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import com.googlecode.objectify.Key;
|
||||||
import google.registry.flows.EppException;
|
import google.registry.flows.EppException;
|
||||||
import google.registry.flows.ResourceUpdateFlow;
|
import google.registry.flows.LoggedInFlow;
|
||||||
|
import google.registry.flows.TransactionalFlow;
|
||||||
|
import google.registry.flows.exceptions.AddRemoveSameValueEppException;
|
||||||
|
import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException;
|
||||||
|
import google.registry.flows.exceptions.ResourceToMutateDoesNotExistException;
|
||||||
|
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.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.domain.metadata.MetadataExtension;
|
||||||
|
import google.registry.model.eppcommon.StatusValue;
|
||||||
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
|
import google.registry.model.eppinput.ResourceCommand.AddRemoveSameValueException;
|
||||||
|
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;
|
||||||
|
|
||||||
|
@ -29,31 +48,81 @@ import javax.inject.Inject;
|
||||||
* An EPP flow that updates a contact resource.
|
* An EPP flow that updates a contact resource.
|
||||||
*
|
*
|
||||||
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException}
|
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException}
|
||||||
* @error {@link google.registry.flows.ResourceUpdateFlow.AddRemoveSameValueEppException}
|
* @error {@link google.registry.flows.exceptions.AddRemoveSameValueEppException}
|
||||||
* @error {@link google.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException}
|
* @error {@link google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException}
|
||||||
* @error {@link google.registry.flows.ResourceUpdateFlow.ResourceHasClientUpdateProhibitedException}
|
* @error {@link google.registry.flows.exceptions.ResourceStatusProhibitsOperationException}
|
||||||
* @error {@link google.registry.flows.ResourceUpdateFlow.StatusNotClientSettableException}
|
* @error {@link google.registry.flows.exceptions.ResourceToMutateDoesNotExistException}
|
||||||
* @error {@link google.registry.flows.SingleResourceFlow.ResourceStatusProhibitsOperationException}
|
* @error {@link google.registry.flows.exceptions.StatusNotClientSettableException}
|
||||||
* @error {@link ContactFlowUtils.BadInternationalizedPostalInfoException}
|
* @error {@link ContactFlowUtils.BadInternationalizedPostalInfoException}
|
||||||
* @error {@link ContactFlowUtils.DeclineContactDisclosureFieldDisallowedPolicyException}
|
* @error {@link ContactFlowUtils.DeclineContactDisclosureFieldDisallowedPolicyException}
|
||||||
*/
|
*/
|
||||||
public class ContactUpdateFlow extends ResourceUpdateFlow<ContactResource, Builder, Update> {
|
public class ContactUpdateFlow extends LoggedInFlow implements TransactionalFlow {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note that CLIENT_UPDATE_PROHIBITED is intentionally not in this list. This is because it
|
||||||
|
* requires special checking, since you must be able to clear the status off the object with an
|
||||||
|
* update.
|
||||||
|
*/
|
||||||
|
private static final ImmutableSet<StatusValue> DISALLOWED_STATUSES = ImmutableSet.of(
|
||||||
|
StatusValue.PENDING_DELETE,
|
||||||
|
StatusValue.SERVER_UPDATE_PROHIBITED);
|
||||||
|
|
||||||
|
@Inject ResourceCommand resourceCommand;
|
||||||
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
@Inject ContactUpdateFlow() {}
|
@Inject ContactUpdateFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void verifyNewUpdatedStateIsAllowed() throws EppException {
|
protected final void initLoggedInFlow() throws EppException {
|
||||||
|
registerExtensions(MetadataExtension.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final EppOutput run() throws EppException {
|
||||||
|
Update command = (Update) resourceCommand;
|
||||||
|
String targetId = command.getTargetId();
|
||||||
|
ContactResource existingResource = loadByUniqueId(ContactResource.class, targetId, now);
|
||||||
|
if (existingResource == null) {
|
||||||
|
throw new ResourceToMutateDoesNotExistException(ContactResource.class, targetId);
|
||||||
|
}
|
||||||
|
if (command.getAuthInfo() != null) {
|
||||||
|
verifyAuthInfoForResource(command.getAuthInfo(), existingResource);
|
||||||
|
}
|
||||||
|
if (!isSuperuser) {
|
||||||
|
verifyResourceOwnership(getClientId(), existingResource);
|
||||||
|
}
|
||||||
|
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(existingResource, DISALLOWED_STATUSES);
|
||||||
|
historyBuilder
|
||||||
|
.setType(HistoryEntry.Type.CONTACT_UPDATE)
|
||||||
|
.setModificationTime(now)
|
||||||
|
.setXmlBytes(null) // We don't want to store contact details in the history entry.
|
||||||
|
.setParent(Key.create(existingResource));
|
||||||
|
Builder builder = existingResource.asBuilder();
|
||||||
|
try {
|
||||||
|
command.applyTo(builder);
|
||||||
|
} catch (AddRemoveSameValueException e) {
|
||||||
|
throw new AddRemoveSameValueEppException();
|
||||||
|
}
|
||||||
|
ContactResource newResource = builder
|
||||||
|
.setLastEppUpdateTime(now)
|
||||||
|
.setLastEppUpdateClientId(getClientId())
|
||||||
|
.build();
|
||||||
|
// 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).
|
||||||
|
if (!isSuperuser
|
||||||
|
&& existingResource.getStatusValues().contains(StatusValue.CLIENT_UPDATE_PROHIBITED)
|
||||||
|
&& newResource.getStatusValues().contains(StatusValue.CLIENT_UPDATE_PROHIBITED)) {
|
||||||
|
throw new ResourceHasClientUpdateProhibitedException();
|
||||||
|
}
|
||||||
validateAsciiPostalInfo(newResource.getInternationalizedPostalInfo());
|
validateAsciiPostalInfo(newResource.getInternationalizedPostalInfo());
|
||||||
validateContactAgainstPolicy(newResource);
|
validateContactAgainstPolicy(newResource);
|
||||||
}
|
ofy().save().<Object>entities(newResource, historyBuilder.build());
|
||||||
|
return createOutput(Success);
|
||||||
@Override
|
|
||||||
protected boolean storeXmlInHistoryEntry() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected final HistoryEntry.Type getHistoryEntryType() {
|
|
||||||
return HistoryEntry.Type.CONTACT_UPDATE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ public class EppLifecycleContactTest extends EppTestCase {
|
||||||
DateTime.parse("2000-06-08T22:01:00Z"));
|
DateTime.parse("2000-06-08T22:01:00Z"));
|
||||||
assertCommandAndResponse(
|
assertCommandAndResponse(
|
||||||
"poll_ack.xml",
|
"poll_ack.xml",
|
||||||
ImmutableMap.of("ID", "2-1-ROID-3-4"),
|
ImmutableMap.of("ID", "2-1-ROID-3-6"),
|
||||||
"poll_ack_response_empty.xml",
|
"poll_ack_response_empty.xml",
|
||||||
null,
|
null,
|
||||||
DateTime.parse("2000-06-08T22:02:00Z"));
|
DateTime.parse("2000-06-08T22:02:00Z"));
|
||||||
|
|
|
@ -18,8 +18,8 @@ import static google.registry.model.eppoutput.CheckData.ContactCheck.create;
|
||||||
import static google.registry.testing.DatastoreHelper.persistActiveContact;
|
import static google.registry.testing.DatastoreHelper.persistActiveContact;
|
||||||
import static google.registry.testing.DatastoreHelper.persistDeletedContact;
|
import static google.registry.testing.DatastoreHelper.persistDeletedContact;
|
||||||
|
|
||||||
import google.registry.flows.ResourceCheckFlow.TooManyResourceChecksException;
|
|
||||||
import google.registry.flows.ResourceCheckFlowTestCase;
|
import google.registry.flows.ResourceCheckFlowTestCase;
|
||||||
|
import google.registry.flows.exceptions.TooManyResourceChecksException;
|
||||||
import google.registry.model.contact.ContactResource;
|
import google.registry.model.contact.ContactResource;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
|
|
@ -19,10 +19,10 @@ import static google.registry.testing.DatastoreHelper.assertNoBillingEvents;
|
||||||
import static google.registry.testing.DatastoreHelper.persistActiveContact;
|
import static google.registry.testing.DatastoreHelper.persistActiveContact;
|
||||||
import static google.registry.testing.DatastoreHelper.persistDeletedContact;
|
import static google.registry.testing.DatastoreHelper.persistDeletedContact;
|
||||||
|
|
||||||
import google.registry.flows.ResourceCreateFlow.ResourceAlreadyExistsException;
|
|
||||||
import google.registry.flows.ResourceFlowTestCase;
|
import google.registry.flows.ResourceFlowTestCase;
|
||||||
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.ResourceAlreadyExistsException;
|
||||||
import google.registry.model.contact.ContactResource;
|
import google.registry.model.contact.ContactResource;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
|
@ -28,13 +28,13 @@ import static google.registry.testing.TaskQueueHelper.assertTasksEnqueued;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.googlecode.objectify.Key;
|
import com.googlecode.objectify.Key;
|
||||||
import google.registry.flows.ResourceAsyncDeleteFlow.ResourceToDeleteIsReferencedException;
|
|
||||||
import google.registry.flows.ResourceFlowTestCase;
|
import google.registry.flows.ResourceFlowTestCase;
|
||||||
import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException;
|
import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException;
|
||||||
import google.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException;
|
|
||||||
import google.registry.flows.SingleResourceFlow.ResourceStatusProhibitsOperationException;
|
|
||||||
import google.registry.flows.async.DeleteContactResourceAction;
|
import google.registry.flows.async.DeleteContactResourceAction;
|
||||||
import google.registry.flows.async.DeleteEppResourceAction;
|
import google.registry.flows.async.DeleteEppResourceAction;
|
||||||
|
import google.registry.flows.exceptions.ResourceStatusProhibitsOperationException;
|
||||||
|
import google.registry.flows.exceptions.ResourceToDeleteIsReferencedException;
|
||||||
|
import google.registry.flows.exceptions.ResourceToMutateDoesNotExistException;
|
||||||
import google.registry.model.contact.ContactResource;
|
import google.registry.model.contact.ContactResource;
|
||||||
import google.registry.model.eppcommon.StatusValue;
|
import google.registry.model.eppcommon.StatusValue;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
|
|
|
@ -24,7 +24,7 @@ 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.ResourceQueryFlow.ResourceToQueryDoesNotExistException;
|
import google.registry.flows.exceptions.ResourceToQueryDoesNotExistException;
|
||||||
import google.registry.model.contact.ContactAddress;
|
import google.registry.model.contact.ContactAddress;
|
||||||
import google.registry.model.contact.ContactAuthInfo;
|
import google.registry.model.contact.ContactAuthInfo;
|
||||||
import google.registry.model.contact.ContactPhoneNumber;
|
import google.registry.model.contact.ContactPhoneNumber;
|
||||||
|
|
|
@ -27,8 +27,8 @@ import com.google.common.collect.FluentIterable;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException;
|
import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException;
|
||||||
import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException;
|
import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException;
|
||||||
import google.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException;
|
import google.registry.flows.exceptions.NotPendingTransferException;
|
||||||
import google.registry.flows.ResourceMutatePendingTransferFlow.NotPendingTransferException;
|
import google.registry.flows.exceptions.ResourceToMutateDoesNotExistException;
|
||||||
import google.registry.model.contact.ContactAuthInfo;
|
import google.registry.model.contact.ContactAuthInfo;
|
||||||
import google.registry.model.contact.ContactResource;
|
import google.registry.model.contact.ContactResource;
|
||||||
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
||||||
|
|
|
@ -25,9 +25,9 @@ import static google.registry.testing.DatastoreHelper.persistResource;
|
||||||
import com.google.common.collect.FluentIterable;
|
import com.google.common.collect.FluentIterable;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException;
|
import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException;
|
||||||
import google.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException;
|
import google.registry.flows.exceptions.NotPendingTransferException;
|
||||||
import google.registry.flows.ResourceMutatePendingTransferFlow.NotPendingTransferException;
|
import google.registry.flows.exceptions.NotTransferInitiatorException;
|
||||||
import google.registry.flows.ResourceTransferCancelFlow.NotTransferInitiatorException;
|
import google.registry.flows.exceptions.ResourceToMutateDoesNotExistException;
|
||||||
import google.registry.model.contact.ContactAuthInfo;
|
import google.registry.model.contact.ContactAuthInfo;
|
||||||
import google.registry.model.contact.ContactResource;
|
import google.registry.model.contact.ContactResource;
|
||||||
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
||||||
|
|
|
@ -20,9 +20,9 @@ import static google.registry.testing.DatastoreHelper.deleteResource;
|
||||||
import static google.registry.testing.DatastoreHelper.persistResource;
|
import static google.registry.testing.DatastoreHelper.persistResource;
|
||||||
|
|
||||||
import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException;
|
import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException;
|
||||||
import google.registry.flows.ResourceQueryFlow.ResourceToQueryDoesNotExistException;
|
import google.registry.flows.exceptions.NoTransferHistoryToQueryException;
|
||||||
import google.registry.flows.ResourceTransferQueryFlow.NoTransferHistoryToQueryException;
|
import google.registry.flows.exceptions.NotAuthorizedToViewTransferException;
|
||||||
import google.registry.flows.ResourceTransferQueryFlow.NotAuthorizedToViewTransferException;
|
import google.registry.flows.exceptions.ResourceToQueryDoesNotExistException;
|
||||||
import google.registry.model.contact.ContactAuthInfo;
|
import google.registry.model.contact.ContactAuthInfo;
|
||||||
import google.registry.model.contact.ContactResource;
|
import google.registry.model.contact.ContactResource;
|
||||||
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
||||||
|
|
|
@ -26,8 +26,8 @@ import com.google.common.collect.FluentIterable;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException;
|
import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException;
|
||||||
import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException;
|
import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException;
|
||||||
import google.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException;
|
import google.registry.flows.exceptions.NotPendingTransferException;
|
||||||
import google.registry.flows.ResourceMutatePendingTransferFlow.NotPendingTransferException;
|
import google.registry.flows.exceptions.ResourceToMutateDoesNotExistException;
|
||||||
import google.registry.model.contact.ContactAuthInfo;
|
import google.registry.model.contact.ContactAuthInfo;
|
||||||
import google.registry.model.contact.ContactResource;
|
import google.registry.model.contact.ContactResource;
|
||||||
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
||||||
|
|
|
@ -24,10 +24,10 @@ import static google.registry.testing.DatastoreHelper.persistResource;
|
||||||
|
|
||||||
import google.registry.config.RegistryEnvironment;
|
import google.registry.config.RegistryEnvironment;
|
||||||
import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException;
|
import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException;
|
||||||
import google.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException;
|
import google.registry.flows.exceptions.AlreadyPendingTransferException;
|
||||||
import google.registry.flows.ResourceTransferRequestFlow.AlreadyPendingTransferException;
|
import google.registry.flows.exceptions.MissingTransferRequestAuthInfoException;
|
||||||
import google.registry.flows.ResourceTransferRequestFlow.MissingTransferRequestAuthInfoException;
|
import google.registry.flows.exceptions.ObjectAlreadySponsoredException;
|
||||||
import google.registry.flows.ResourceTransferRequestFlow.ObjectAlreadySponsoredException;
|
import google.registry.flows.exceptions.ResourceToMutateDoesNotExistException;
|
||||||
import google.registry.model.contact.ContactAuthInfo;
|
import google.registry.model.contact.ContactAuthInfo;
|
||||||
import google.registry.model.contact.ContactResource;
|
import google.registry.model.contact.ContactResource;
|
||||||
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
||||||
|
|
|
@ -25,13 +25,13 @@ 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.ResourceNotOwnedException;
|
import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException;
|
||||||
import google.registry.flows.ResourceMutateFlow.ResourceToMutateDoesNotExistException;
|
|
||||||
import google.registry.flows.ResourceUpdateFlow.AddRemoveSameValueEppException;
|
|
||||||
import google.registry.flows.ResourceUpdateFlow.ResourceHasClientUpdateProhibitedException;
|
|
||||||
import google.registry.flows.ResourceUpdateFlow.StatusNotClientSettableException;
|
|
||||||
import google.registry.flows.SingleResourceFlow.ResourceStatusProhibitsOperationException;
|
|
||||||
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.ResourceStatusProhibitsOperationException;
|
||||||
|
import google.registry.flows.exceptions.ResourceToMutateDoesNotExistException;
|
||||||
|
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;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<result code="1301">
|
<result code="1301">
|
||||||
<msg>Command completed successfully; ack to dequeue</msg>
|
<msg>Command completed successfully; ack to dequeue</msg>
|
||||||
</result>
|
</result>
|
||||||
<msgQ count="1" id="2-1-ROID-3-4">
|
<msgQ count="1" id="2-1-ROID-3-6">
|
||||||
<qDate>2000-06-08T22:00:00Z</qDate>
|
<qDate>2000-06-08T22:00:00Z</qDate>
|
||||||
<msg>Transfer requested.</msg>
|
<msg>Transfer requested.</msg>
|
||||||
</msgQ>
|
</msgQ>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue