mirror of
https://github.com/google/nomulus.git
synced 2025-05-13 16:07:15 +02:00
Turn Flow into an interface and inject all its fields
This concludes your flow flattening experience. Please fill out a flow flattening satisfaction survey before exiting. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=137903095
This commit is contained in:
parent
82b0bff9b5
commit
053538b1b5
49 changed files with 630 additions and 569 deletions
|
@ -14,90 +14,24 @@
|
||||||
|
|
||||||
package google.registry.flows;
|
package google.registry.flows;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import google.registry.model.eppoutput.EppOutput.ResponseOrGreeting;
|
||||||
import google.registry.model.eppcommon.Trid;
|
|
||||||
import google.registry.model.eppinput.EppInput;
|
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
|
||||||
import google.registry.model.eppoutput.EppResponse;
|
|
||||||
import google.registry.model.eppoutput.EppResponse.ResponseData;
|
|
||||||
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
|
|
||||||
import google.registry.model.eppoutput.Result;
|
|
||||||
import google.registry.model.poll.MessageQueueInfo;
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import org.joda.time.DateTime;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An abstract EPP flow.
|
* An Extensible Provisioning Protocol flow.
|
||||||
*
|
*
|
||||||
* <p>This class also contains static methods for loading an appropriate flow based on model
|
* <p>A "flow" is our word for a "command", since we've overloaded the word "command" to mean the
|
||||||
* classes.
|
* command objects and also the CLI operation classes.
|
||||||
*/
|
*/
|
||||||
public abstract class Flow {
|
public interface Flow {
|
||||||
|
|
||||||
protected EppInput eppInput;
|
|
||||||
protected SessionMetadata sessionMetadata;
|
|
||||||
protected TransportCredentials credentials;
|
|
||||||
protected Trid trid;
|
|
||||||
protected DateTime now;
|
|
||||||
|
|
||||||
/** Whether this flow is being run in a superuser mode that can skip some checks. */
|
|
||||||
protected boolean isSuperuser;
|
|
||||||
|
|
||||||
/** Flows can override this for custom initialization. */
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
protected void initFlow() throws EppException {}
|
|
||||||
|
|
||||||
/** Execute the business logic for this flow. */
|
|
||||||
protected abstract EppOutput run() throws EppException;
|
|
||||||
|
|
||||||
protected EppOutput createOutput(Result.Code code) {
|
|
||||||
return createOutput(code, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected EppOutput createOutput(Result.Code code, ResponseData responseData) {
|
|
||||||
return createOutput(code, responseData, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected EppOutput createOutput(
|
|
||||||
Result.Code code,
|
|
||||||
@Nullable ResponseData responseData,
|
|
||||||
@Nullable ImmutableList<? extends ResponseExtension> extensions) {
|
|
||||||
return createOutput(
|
|
||||||
code, responseData == null ? null : ImmutableList.of(responseData), extensions, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected EppOutput createOutput(
|
|
||||||
Result.Code code,
|
|
||||||
@Nullable ImmutableList<ResponseData> responseData,
|
|
||||||
@Nullable ImmutableList<? extends ResponseExtension> responseExtensions,
|
|
||||||
@Nullable MessageQueueInfo messageQueueInfo) {
|
|
||||||
return EppOutput.create(new EppResponse.Builder()
|
|
||||||
.setTrid(trid)
|
|
||||||
.setResult(Result.create(code))
|
|
||||||
.setMessageQueueInfo(messageQueueInfo)
|
|
||||||
.setResData(responseData)
|
|
||||||
.setExtensions(responseExtensions)
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Using an init function instead of a constructor avoids duplicating constructors across the
|
* Executes an EPP "flow" and returns a response object (or in the specific case of the "hello"
|
||||||
* entire hierarchy of flow classes
|
* flow a greeting object) that can be converted to XML and returned to the caller.
|
||||||
|
*
|
||||||
|
* <p>Flows should have {@link #run} called once per instance. If a flow needs to be retried, a
|
||||||
|
* new instance should be created.
|
||||||
|
*
|
||||||
|
* <p>Flows should get all of their parameters via injection off of {@link FlowComponent}.
|
||||||
*/
|
*/
|
||||||
public final Flow init(
|
ResponseOrGreeting run() throws EppException;
|
||||||
EppInput eppInput,
|
|
||||||
Trid trid,
|
|
||||||
SessionMetadata sessionMetadata,
|
|
||||||
TransportCredentials credentials,
|
|
||||||
boolean isSuperuser,
|
|
||||||
DateTime now) throws EppException {
|
|
||||||
this.eppInput = eppInput;
|
|
||||||
this.trid = trid;
|
|
||||||
this.sessionMetadata = sessionMetadata;
|
|
||||||
this.credentials = credentials;
|
|
||||||
this.now = now;
|
|
||||||
this.isSuperuser = isSuperuser;
|
|
||||||
initFlow();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,8 @@ import google.registry.model.eppinput.EppInput.Poll;
|
||||||
import google.registry.model.eppinput.EppInput.ResourceCommandWrapper;
|
import google.registry.model.eppinput.EppInput.ResourceCommandWrapper;
|
||||||
import google.registry.model.eppinput.ResourceCommand;
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
import google.registry.model.eppinput.ResourceCommand.SingleResourceCommand;
|
import google.registry.model.eppinput.ResourceCommand.SingleResourceCommand;
|
||||||
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
|
import google.registry.model.eppoutput.Result;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import java.lang.annotation.Documented;
|
import java.lang.annotation.Documented;
|
||||||
import javax.inject.Qualifier;
|
import javax.inject.Qualifier;
|
||||||
|
@ -244,6 +246,19 @@ public class FlowModule {
|
||||||
return historyBuilder;
|
return historyBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a partially filled in {@link EppResponse} builder.
|
||||||
|
*
|
||||||
|
* <p>This is not marked with {@link FlowScope} so that each retry gets a fresh one. Otherwise,
|
||||||
|
* the fact that the builder is one-use would cause NPEs.
|
||||||
|
*/
|
||||||
|
@Provides
|
||||||
|
static EppResponse.Builder provideEppResponseBuilder(Trid trid) {
|
||||||
|
return new EppResponse.Builder()
|
||||||
|
.setTrid(trid)
|
||||||
|
.setResultFromCode(Result.Code.SUCCESS); // Default to success.
|
||||||
|
}
|
||||||
|
|
||||||
/** Wrapper class to carry an {@link EppException} to the calling code. */
|
/** Wrapper class to carry an {@link EppException} to the calling code. */
|
||||||
static class EppExceptionInProviderException extends RuntimeException {
|
static class EppExceptionInProviderException extends RuntimeException {
|
||||||
EppExceptionInProviderException(EppException exception) {
|
EppExceptionInProviderException(EppException exception) {
|
||||||
|
|
|
@ -28,14 +28,11 @@ import google.registry.flows.FlowModule.InputXml;
|
||||||
import google.registry.flows.FlowModule.Superuser;
|
import google.registry.flows.FlowModule.Superuser;
|
||||||
import google.registry.flows.FlowModule.Transactional;
|
import google.registry.flows.FlowModule.Transactional;
|
||||||
import google.registry.model.eppcommon.Trid;
|
import google.registry.model.eppcommon.Trid;
|
||||||
import google.registry.model.eppinput.EppInput;
|
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppOutput;
|
||||||
import google.registry.monitoring.whitebox.EppMetric;
|
import google.registry.monitoring.whitebox.EppMetric;
|
||||||
import google.registry.util.Clock;
|
|
||||||
import google.registry.util.FormattingLogger;
|
import google.registry.util.FormattingLogger;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Provider;
|
import javax.inject.Provider;
|
||||||
import org.joda.time.DateTime;
|
|
||||||
import org.json.simple.JSONValue;
|
import org.json.simple.JSONValue;
|
||||||
|
|
||||||
/** Run a flow, either transactionally or not, with logging and retrying as needed. */
|
/** Run a flow, either transactionally or not, with logging and retrying as needed. */
|
||||||
|
@ -56,9 +53,7 @@ public class FlowRunner {
|
||||||
private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass();
|
private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass();
|
||||||
|
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject Clock clock;
|
|
||||||
@Inject TransportCredentials credentials;
|
@Inject TransportCredentials credentials;
|
||||||
@Inject EppInput eppInput;
|
|
||||||
@Inject EppRequestSource eppRequestSource;
|
@Inject EppRequestSource eppRequestSource;
|
||||||
@Inject Provider<Flow> flowProvider;
|
@Inject Provider<Flow> flowProvider;
|
||||||
@Inject @InputXml byte[] inputXmlBytes;
|
@Inject @InputXml byte[] inputXmlBytes;
|
||||||
|
@ -99,7 +94,7 @@ public class FlowRunner {
|
||||||
"xmlBytes", xmlBase64)));
|
"xmlBytes", xmlBase64)));
|
||||||
if (!isTransactional) {
|
if (!isTransactional) {
|
||||||
metric.incrementAttempts();
|
metric.incrementAttempts();
|
||||||
return createAndInitFlow(clock.nowUtc()).run();
|
return EppOutput.create(flowProvider.get().run());
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return ofy().transact(new Work<EppOutput>() {
|
return ofy().transact(new Work<EppOutput>() {
|
||||||
|
@ -107,7 +102,7 @@ public class FlowRunner {
|
||||||
public EppOutput run() {
|
public EppOutput run() {
|
||||||
metric.incrementAttempts();
|
metric.incrementAttempts();
|
||||||
try {
|
try {
|
||||||
EppOutput output = createAndInitFlow(ofy().getTransactionTime()).run();
|
EppOutput output = EppOutput.create(flowProvider.get().run());
|
||||||
if (isDryRun) {
|
if (isDryRun) {
|
||||||
throw new DryRunException(output);
|
throw new DryRunException(output);
|
||||||
}
|
}
|
||||||
|
@ -127,15 +122,6 @@ public class FlowRunner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Flow createAndInitFlow(DateTime now) throws EppException {
|
|
||||||
return flowProvider.get().init(
|
|
||||||
eppInput,
|
|
||||||
trid,
|
|
||||||
sessionMetadata,
|
|
||||||
credentials,
|
|
||||||
isSuperuser,
|
|
||||||
now);
|
|
||||||
}
|
|
||||||
/** Exception for canceling a transaction while capturing what the output would have been. */
|
/** Exception for canceling a transaction while capturing what the output would have been. */
|
||||||
private static class DryRunException extends RuntimeException {
|
private static class DryRunException extends RuntimeException {
|
||||||
final EppOutput output;
|
final EppOutput output;
|
||||||
|
|
|
@ -15,9 +15,9 @@
|
||||||
package google.registry.flows;
|
package google.registry.flows;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marker interface indicating that a {@link Flow} needs to be run transactionally.
|
* Interface for a {@link Flow} that needs to be run transactionally.
|
||||||
*
|
*
|
||||||
* <p>Any flow that mutates the datastore should be tagged with this so that {@link FlowRunner} will
|
* <p>Any flow that mutates the datastore should implement this so that {@link FlowRunner} will know
|
||||||
* know how to run it.
|
* how to run it.
|
||||||
*/
|
*/
|
||||||
public interface TransactionalFlow {}
|
public interface TransactionalFlow extends Flow {}
|
||||||
|
|
|
@ -17,7 +17,6 @@ package google.registry.flows.contact;
|
||||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyTargetIdCount;
|
import static google.registry.flows.ResourceFlowUtils.verifyTargetIdCount;
|
||||||
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.config.ConfigModule.Config;
|
import google.registry.config.ConfigModule.Config;
|
||||||
|
@ -30,7 +29,8 @@ import google.registry.model.contact.ContactResource;
|
||||||
import google.registry.model.eppinput.ResourceCommand;
|
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 google.registry.model.eppoutput.EppResponse;
|
||||||
|
import google.registry.util.Clock;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -42,26 +42,28 @@ import javax.inject.Inject;
|
||||||
*
|
*
|
||||||
* @error {@link google.registry.flows.exceptions.TooManyResourceChecksException}
|
* @error {@link google.registry.flows.exceptions.TooManyResourceChecksException}
|
||||||
*/
|
*/
|
||||||
public final class ContactCheckFlow extends Flow {
|
public final class ContactCheckFlow implements Flow {
|
||||||
|
|
||||||
@Inject ResourceCommand resourceCommand;
|
@Inject ResourceCommand resourceCommand;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
|
@Inject Clock clock;
|
||||||
@Inject @Config("maxChecks") int maxChecks;
|
@Inject @Config("maxChecks") int maxChecks;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject ContactCheckFlow() {}
|
@Inject ContactCheckFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.validate(); // There are no legal extensions for this flow.
|
extensionManager.validate(); // There are no legal extensions for this flow.
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
List<String> targetIds = ((Check) resourceCommand).getTargetIds();
|
List<String> targetIds = ((Check) resourceCommand).getTargetIds();
|
||||||
verifyTargetIdCount(targetIds, maxChecks);
|
verifyTargetIdCount(targetIds, maxChecks);
|
||||||
Set<String> existingIds = checkResourcesExist(ContactResource.class, targetIds, now);
|
Set<String> existingIds = checkResourcesExist(ContactResource.class, targetIds, clock.nowUtc());
|
||||||
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 createOutput(SUCCESS, ContactCheckData.create(checks.build()));
|
return responseBuilder.setResData(ContactCheckData.create(checks.build())).build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,13 +19,11 @@ import static google.registry.flows.ResourceFlowUtils.verifyResourceDoesNotExist
|
||||||
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.eppoutput.Result.Code.SUCCESS;
|
|
||||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
|
|
||||||
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;
|
||||||
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;
|
||||||
|
@ -35,12 +33,13 @@ import google.registry.model.contact.ContactResource.Builder;
|
||||||
import google.registry.model.domain.metadata.MetadataExtension;
|
import google.registry.model.domain.metadata.MetadataExtension;
|
||||||
import google.registry.model.eppinput.ResourceCommand;
|
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.EppResponse;
|
||||||
import google.registry.model.index.EppResourceIndex;
|
import google.registry.model.index.EppResourceIndex;
|
||||||
import google.registry.model.index.ForeignKeyIndex;
|
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;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An EPP flow that creates a new contact.
|
* An EPP flow that creates a new contact.
|
||||||
|
@ -49,21 +48,23 @@ import javax.inject.Inject;
|
||||||
* @error {@link ContactFlowUtils.BadInternationalizedPostalInfoException}
|
* @error {@link ContactFlowUtils.BadInternationalizedPostalInfoException}
|
||||||
* @error {@link ContactFlowUtils.DeclineContactDisclosureFieldDisallowedPolicyException}
|
* @error {@link ContactFlowUtils.DeclineContactDisclosureFieldDisallowedPolicyException}
|
||||||
*/
|
*/
|
||||||
public final class ContactCreateFlow extends Flow implements TransactionalFlow {
|
public final class ContactCreateFlow implements TransactionalFlow {
|
||||||
|
|
||||||
@Inject ResourceCommand resourceCommand;
|
@Inject ResourceCommand resourceCommand;
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject @TargetId String targetId;
|
@Inject @TargetId String targetId;
|
||||||
@Inject HistoryEntry.Builder historyBuilder;
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject ContactCreateFlow() {}
|
@Inject ContactCreateFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.register(MetadataExtension.class);
|
extensionManager.register(MetadataExtension.class);
|
||||||
extensionManager.validate();
|
extensionManager.validate();
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
Create command = (Create) resourceCommand;
|
Create command = (Create) resourceCommand;
|
||||||
|
DateTime now = ofy().getTransactionTime();
|
||||||
verifyResourceDoesNotExist(ContactResource.class, targetId, now);
|
verifyResourceDoesNotExist(ContactResource.class, targetId, now);
|
||||||
ContactResource newContact = new Builder()
|
ContactResource newContact = new Builder()
|
||||||
.setContactId(targetId)
|
.setContactId(targetId)
|
||||||
|
@ -90,6 +91,8 @@ public final class ContactCreateFlow extends Flow implements TransactionalFlow {
|
||||||
historyBuilder.build(),
|
historyBuilder.build(),
|
||||||
ForeignKeyIndex.create(newContact, newContact.getDeletionTime()),
|
ForeignKeyIndex.create(newContact, newContact.getDeletionTime()),
|
||||||
EppResourceIndex.create(Key.create(newContact)));
|
EppResourceIndex.create(Key.create(newContact)));
|
||||||
return createOutput(SUCCESS, ContactCreateData.create(newContact.getContactId(), now));
|
return responseBuilder
|
||||||
|
.setResData(ContactCreateData.create(newContact.getContactId(), now))
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,8 @@ import com.google.common.collect.ImmutableSet;
|
||||||
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;
|
||||||
import google.registry.flows.Flow;
|
|
||||||
import google.registry.flows.FlowModule.ClientId;
|
import google.registry.flows.FlowModule.ClientId;
|
||||||
|
import google.registry.flows.FlowModule.Superuser;
|
||||||
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;
|
||||||
|
@ -39,9 +39,10 @@ import google.registry.model.domain.DomainBase;
|
||||||
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.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An EPP flow that deletes a contact.
|
* An EPP flow that deletes a contact.
|
||||||
|
@ -57,7 +58,7 @@ import javax.inject.Inject;
|
||||||
* @error {@link google.registry.flows.exceptions.ResourceStatusProhibitsOperationException}
|
* @error {@link google.registry.flows.exceptions.ResourceStatusProhibitsOperationException}
|
||||||
* @error {@link google.registry.flows.exceptions.ResourceToDeleteIsReferencedException}
|
* @error {@link google.registry.flows.exceptions.ResourceToDeleteIsReferencedException}
|
||||||
*/
|
*/
|
||||||
public final class ContactDeleteFlow extends Flow implements TransactionalFlow {
|
public final class ContactDeleteFlow implements TransactionalFlow {
|
||||||
|
|
||||||
private static final ImmutableSet<StatusValue> DISALLOWED_STATUSES = ImmutableSet.of(
|
private static final ImmutableSet<StatusValue> DISALLOWED_STATUSES = ImmutableSet.of(
|
||||||
StatusValue.LINKED,
|
StatusValue.LINKED,
|
||||||
|
@ -75,16 +76,19 @@ public final class ContactDeleteFlow extends Flow implements TransactionalFlow {
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject @TargetId String targetId;
|
@Inject @TargetId String targetId;
|
||||||
|
@Inject @Superuser boolean isSuperuser;
|
||||||
@Inject Optional<AuthInfo> authInfo;
|
@Inject Optional<AuthInfo> authInfo;
|
||||||
@Inject HistoryEntry.Builder historyBuilder;
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
@Inject AsyncFlowEnqueuer asyncFlowEnqueuer;
|
@Inject AsyncFlowEnqueuer asyncFlowEnqueuer;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject ContactDeleteFlow() {}
|
@Inject ContactDeleteFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.register(MetadataExtension.class);
|
extensionManager.register(MetadataExtension.class);
|
||||||
extensionManager.validate();
|
extensionManager.validate();
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
|
DateTime now = ofy().getTransactionTime();
|
||||||
failfastForAsyncDelete(targetId, now, ContactResource.class, GET_REFERENCED_CONTACTS);
|
failfastForAsyncDelete(targetId, now, ContactResource.class, GET_REFERENCED_CONTACTS);
|
||||||
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
||||||
verifyNoDisallowedStatuses(existingContact, DISALLOWED_STATUSES);
|
verifyNoDisallowedStatuses(existingContact, DISALLOWED_STATUSES);
|
||||||
|
@ -100,6 +104,6 @@ public final class ContactDeleteFlow extends Flow implements TransactionalFlow {
|
||||||
.setModificationTime(now)
|
.setModificationTime(now)
|
||||||
.setParent(Key.create(existingContact));
|
.setParent(Key.create(existingContact));
|
||||||
ofy().save().<Object>entities(newContact, historyBuilder.build());
|
ofy().save().<Object>entities(newContact, historyBuilder.build());
|
||||||
return createOutput(SUCCESS_WITH_ACTION_PENDING);
|
return responseBuilder.setResultFromCode(SUCCESS_WITH_ACTION_PENDING).build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@ import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
|
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
|
||||||
import static google.registry.model.EppResourceUtils.cloneResourceWithLinkedStatus;
|
import static google.registry.model.EppResourceUtils.cloneResourceWithLinkedStatus;
|
||||||
import static google.registry.model.eppoutput.Result.Code.SUCCESS;
|
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
import google.registry.flows.EppException;
|
import google.registry.flows.EppException;
|
||||||
|
@ -28,8 +27,10 @@ import google.registry.flows.FlowModule.ClientId;
|
||||||
import google.registry.flows.FlowModule.TargetId;
|
import google.registry.flows.FlowModule.TargetId;
|
||||||
import google.registry.model.contact.ContactResource;
|
import google.registry.model.contact.ContactResource;
|
||||||
import google.registry.model.eppcommon.AuthInfo;
|
import google.registry.model.eppcommon.AuthInfo;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
|
import google.registry.util.Clock;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An EPP flow that returns information about a contact.
|
* An EPP flow that returns information about a contact.
|
||||||
|
@ -41,16 +42,19 @@ import javax.inject.Inject;
|
||||||
*
|
*
|
||||||
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException}
|
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException}
|
||||||
*/
|
*/
|
||||||
public final class ContactInfoFlow extends Flow {
|
public final class ContactInfoFlow implements Flow {
|
||||||
|
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
|
@Inject Clock clock;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject @TargetId String targetId;
|
@Inject @TargetId String targetId;
|
||||||
@Inject Optional<AuthInfo> authInfo;
|
@Inject Optional<AuthInfo> authInfo;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject ContactInfoFlow() {}
|
@Inject ContactInfoFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
|
DateTime now = clock.nowUtc();
|
||||||
extensionManager.validate(); // There are no legal extensions for this flow.
|
extensionManager.validate(); // There are no legal extensions for this flow.
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
ContactResource contact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
ContactResource contact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
||||||
|
@ -58,6 +62,6 @@ public final class ContactInfoFlow extends Flow {
|
||||||
if (!clientId.equals(contact.getCurrentSponsorClientId()) && !authInfo.isPresent()) {
|
if (!clientId.equals(contact.getCurrentSponsorClientId()) && !authInfo.isPresent()) {
|
||||||
contact = contact.asBuilder().setAuthInfo(null).build();
|
contact = contact.asBuilder().setAuthInfo(null).build();
|
||||||
}
|
}
|
||||||
return createOutput(SUCCESS, cloneResourceWithLinkedStatus(contact, now));
|
return responseBuilder.setResData(cloneResourceWithLinkedStatus(contact, now)).build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,14 +21,12 @@ import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForR
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
|
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
|
||||||
import static google.registry.flows.contact.ContactFlowUtils.createGainingTransferPollMessage;
|
import static google.registry.flows.contact.ContactFlowUtils.createGainingTransferPollMessage;
|
||||||
import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse;
|
import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse;
|
||||||
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;
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
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;
|
||||||
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;
|
||||||
|
@ -37,12 +35,13 @@ import google.registry.model.contact.ContactResource;
|
||||||
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.eppinput.ResourceCommand;
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.poll.PollMessage;
|
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.TransferData;
|
||||||
import google.registry.model.transfer.TransferStatus;
|
import google.registry.model.transfer.TransferStatus;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An EPP flow that approves a pending transfer on a contact.
|
* An EPP flow that approves a pending transfer on a contact.
|
||||||
|
@ -57,7 +56,7 @@ import javax.inject.Inject;
|
||||||
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException}
|
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException}
|
||||||
* @error {@link google.registry.flows.exceptions.NotPendingTransferException}
|
* @error {@link google.registry.flows.exceptions.NotPendingTransferException}
|
||||||
*/
|
*/
|
||||||
public final class ContactTransferApproveFlow extends Flow implements TransactionalFlow {
|
public final class ContactTransferApproveFlow implements TransactionalFlow {
|
||||||
|
|
||||||
@Inject ResourceCommand resourceCommand;
|
@Inject ResourceCommand resourceCommand;
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
|
@ -65,6 +64,7 @@ public final class ContactTransferApproveFlow extends Flow implements Transactio
|
||||||
@Inject @TargetId String targetId;
|
@Inject @TargetId String targetId;
|
||||||
@Inject Optional<AuthInfo> authInfo;
|
@Inject Optional<AuthInfo> authInfo;
|
||||||
@Inject HistoryEntry.Builder historyBuilder;
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject ContactTransferApproveFlow() {}
|
@Inject ContactTransferApproveFlow() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -72,10 +72,11 @@ public final class ContactTransferApproveFlow extends Flow implements Transactio
|
||||||
* {@link ContactResource#cloneProjectedAtTime} which handles implicit server approvals.
|
* {@link ContactResource#cloneProjectedAtTime} which handles implicit server approvals.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.register(MetadataExtension.class);
|
extensionManager.register(MetadataExtension.class);
|
||||||
extensionManager.validate();
|
extensionManager.validate();
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
|
DateTime now = ofy().getTransactionTime();
|
||||||
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
||||||
verifyOptionalAuthInfoForResource(authInfo, existingContact);
|
verifyOptionalAuthInfoForResource(authInfo, existingContact);
|
||||||
TransferData transferData = existingContact.getTransferData();
|
TransferData transferData = existingContact.getTransferData();
|
||||||
|
@ -97,6 +98,8 @@ public final class ContactTransferApproveFlow extends Flow implements Transactio
|
||||||
// Delete the billing event and poll messages that were written in case the transfer would have
|
// Delete the billing event and poll messages that were written in case the transfer would have
|
||||||
// been implicitly server approved.
|
// been implicitly server approved.
|
||||||
ofy().delete().keys(transferData.getServerApproveEntities());
|
ofy().delete().keys(transferData.getServerApproveEntities());
|
||||||
return createOutput(SUCCESS, createTransferResponse(targetId, newContact.getTransferData()));
|
return responseBuilder
|
||||||
|
.setResData(createTransferResponse(targetId, newContact.getTransferData()))
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,14 +20,12 @@ import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
|
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
|
||||||
import static google.registry.flows.contact.ContactFlowUtils.createLosingTransferPollMessage;
|
import static google.registry.flows.contact.ContactFlowUtils.createLosingTransferPollMessage;
|
||||||
import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse;
|
import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse;
|
||||||
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;
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
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;
|
||||||
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;
|
||||||
|
@ -37,12 +35,13 @@ import google.registry.model.contact.ContactResource;
|
||||||
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.eppinput.ResourceCommand;
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.poll.PollMessage;
|
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.TransferData;
|
||||||
import google.registry.model.transfer.TransferStatus;
|
import google.registry.model.transfer.TransferStatus;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An EPP flow that cancels a pending transfer on a contact.
|
* An EPP flow that cancels a pending transfer on a contact.
|
||||||
|
@ -57,7 +56,7 @@ import javax.inject.Inject;
|
||||||
* @error {@link google.registry.flows.exceptions.NotPendingTransferException}
|
* @error {@link google.registry.flows.exceptions.NotPendingTransferException}
|
||||||
* @error {@link google.registry.flows.exceptions.NotTransferInitiatorException}
|
* @error {@link google.registry.flows.exceptions.NotTransferInitiatorException}
|
||||||
*/
|
*/
|
||||||
public final class ContactTransferCancelFlow extends Flow implements TransactionalFlow {
|
public final class ContactTransferCancelFlow implements TransactionalFlow {
|
||||||
|
|
||||||
@Inject ResourceCommand resourceCommand;
|
@Inject ResourceCommand resourceCommand;
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
|
@ -65,13 +64,15 @@ public final class ContactTransferCancelFlow extends Flow implements Transaction
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject @TargetId String targetId;
|
@Inject @TargetId String targetId;
|
||||||
@Inject HistoryEntry.Builder historyBuilder;
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject ContactTransferCancelFlow() {}
|
@Inject ContactTransferCancelFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.register(MetadataExtension.class);
|
extensionManager.register(MetadataExtension.class);
|
||||||
extensionManager.validate();
|
extensionManager.validate();
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
|
DateTime now = ofy().getTransactionTime();
|
||||||
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
||||||
verifyOptionalAuthInfoForResource(authInfo, existingContact);
|
verifyOptionalAuthInfoForResource(authInfo, existingContact);
|
||||||
TransferData transferData = existingContact.getTransferData();
|
TransferData transferData = existingContact.getTransferData();
|
||||||
|
@ -95,6 +96,8 @@ public final class ContactTransferCancelFlow extends Flow implements Transaction
|
||||||
// Delete the billing event and poll messages that were written in case the transfer would have
|
// Delete the billing event and poll messages that were written in case the transfer would have
|
||||||
// been implicitly server approved.
|
// been implicitly server approved.
|
||||||
ofy().delete().keys(transferData.getServerApproveEntities());
|
ofy().delete().keys(transferData.getServerApproveEntities());
|
||||||
return createOutput(SUCCESS, createTransferResponse(targetId, newContact.getTransferData()));
|
return responseBuilder
|
||||||
|
.setResData(createTransferResponse(targetId, newContact.getTransferData()))
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@ import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
|
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
|
||||||
import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse;
|
import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse;
|
||||||
import static google.registry.model.eppoutput.Result.Code.SUCCESS;
|
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
import google.registry.flows.EppException;
|
import google.registry.flows.EppException;
|
||||||
|
@ -30,7 +29,8 @@ import google.registry.flows.exceptions.NoTransferHistoryToQueryException;
|
||||||
import google.registry.flows.exceptions.NotAuthorizedToViewTransferException;
|
import google.registry.flows.exceptions.NotAuthorizedToViewTransferException;
|
||||||
import google.registry.model.contact.ContactResource;
|
import google.registry.model.contact.ContactResource;
|
||||||
import google.registry.model.eppcommon.AuthInfo;
|
import google.registry.model.eppcommon.AuthInfo;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
|
import google.registry.util.Clock;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,19 +48,22 @@ import javax.inject.Inject;
|
||||||
* @error {@link google.registry.flows.exceptions.NoTransferHistoryToQueryException}
|
* @error {@link google.registry.flows.exceptions.NoTransferHistoryToQueryException}
|
||||||
* @error {@link google.registry.flows.exceptions.NotAuthorizedToViewTransferException}
|
* @error {@link google.registry.flows.exceptions.NotAuthorizedToViewTransferException}
|
||||||
*/
|
*/
|
||||||
public final class ContactTransferQueryFlow extends Flow {
|
public final class ContactTransferQueryFlow implements Flow {
|
||||||
|
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
@Inject Optional<AuthInfo> authInfo;
|
@Inject Optional<AuthInfo> authInfo;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject @TargetId String targetId;
|
@Inject @TargetId String targetId;
|
||||||
|
@Inject Clock clock;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject ContactTransferQueryFlow() {}
|
@Inject ContactTransferQueryFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.validate(); // There are no legal extensions for this flow.
|
extensionManager.validate(); // There are no legal extensions for this flow.
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
ContactResource contact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
ContactResource contact =
|
||||||
|
loadAndVerifyExistence(ContactResource.class, targetId, clock.nowUtc());
|
||||||
verifyOptionalAuthInfoForResource(authInfo, contact);
|
verifyOptionalAuthInfoForResource(authInfo, contact);
|
||||||
// Most of the fields on the transfer response are required, so there's no way to return valid
|
// 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).
|
// XML if the object has never been transferred (and hence the fields aren't populated).
|
||||||
|
@ -74,6 +77,8 @@ public final class ContactTransferQueryFlow extends Flow {
|
||||||
&& !clientId.equals(contact.getTransferData().getLosingClientId())) {
|
&& !clientId.equals(contact.getTransferData().getLosingClientId())) {
|
||||||
throw new NotAuthorizedToViewTransferException();
|
throw new NotAuthorizedToViewTransferException();
|
||||||
}
|
}
|
||||||
return createOutput(SUCCESS, createTransferResponse(targetId, contact.getTransferData()));
|
return responseBuilder
|
||||||
|
.setResData(createTransferResponse(targetId, contact.getTransferData()))
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,14 +21,12 @@ import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForR
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
|
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
|
||||||
import static google.registry.flows.contact.ContactFlowUtils.createGainingTransferPollMessage;
|
import static google.registry.flows.contact.ContactFlowUtils.createGainingTransferPollMessage;
|
||||||
import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse;
|
import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse;
|
||||||
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;
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
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;
|
||||||
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;
|
||||||
|
@ -36,12 +34,13 @@ import google.registry.flows.exceptions.NotPendingTransferException;
|
||||||
import google.registry.model.contact.ContactResource;
|
import google.registry.model.contact.ContactResource;
|
||||||
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.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.poll.PollMessage;
|
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.TransferData;
|
||||||
import google.registry.model.transfer.TransferStatus;
|
import google.registry.model.transfer.TransferStatus;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An EPP flow that rejects a pending transfer on a contact.
|
* An EPP flow that rejects a pending transfer on a contact.
|
||||||
|
@ -56,20 +55,22 @@ import javax.inject.Inject;
|
||||||
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException}
|
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException}
|
||||||
* @error {@link google.registry.flows.exceptions.NotPendingTransferException}
|
* @error {@link google.registry.flows.exceptions.NotPendingTransferException}
|
||||||
*/
|
*/
|
||||||
public final class ContactTransferRejectFlow extends Flow implements TransactionalFlow {
|
public final class ContactTransferRejectFlow implements TransactionalFlow {
|
||||||
|
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
@Inject Optional<AuthInfo> authInfo;
|
@Inject Optional<AuthInfo> authInfo;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject @TargetId String targetId;
|
@Inject @TargetId String targetId;
|
||||||
@Inject HistoryEntry.Builder historyBuilder;
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject ContactTransferRejectFlow() {}
|
@Inject ContactTransferRejectFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.register(MetadataExtension.class);
|
extensionManager.register(MetadataExtension.class);
|
||||||
extensionManager.validate();
|
extensionManager.validate();
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
|
DateTime now = ofy().getTransactionTime();
|
||||||
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
||||||
verifyOptionalAuthInfoForResource(authInfo, existingContact);
|
verifyOptionalAuthInfoForResource(authInfo, existingContact);
|
||||||
TransferData transferData = existingContact.getTransferData();
|
TransferData transferData = existingContact.getTransferData();
|
||||||
|
@ -90,6 +91,8 @@ public final class ContactTransferRejectFlow extends Flow implements Transaction
|
||||||
// Delete the billing event and poll messages that were written in case the transfer would have
|
// Delete the billing event and poll messages that were written in case the transfer would have
|
||||||
// been implicitly server approved.
|
// been implicitly server approved.
|
||||||
ofy().delete().keys(transferData.getServerApproveEntities());
|
ofy().delete().keys(transferData.getServerApproveEntities());
|
||||||
return createOutput(SUCCESS, createTransferResponse(targetId, newContact.getTransferData()));
|
return responseBuilder
|
||||||
|
.setResData(createTransferResponse(targetId, newContact.getTransferData()))
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@ import com.googlecode.objectify.Key;
|
||||||
import google.registry.config.ConfigModule.Config;
|
import google.registry.config.ConfigModule.Config;
|
||||||
import google.registry.flows.EppException;
|
import google.registry.flows.EppException;
|
||||||
import google.registry.flows.ExtensionManager;
|
import google.registry.flows.ExtensionManager;
|
||||||
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;
|
||||||
|
@ -40,7 +39,8 @@ import google.registry.model.contact.ContactResource;
|
||||||
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.eppoutput.EppOutput;
|
import google.registry.model.eppcommon.Trid;
|
||||||
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.poll.PollMessage;
|
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.TransferData;
|
||||||
|
@ -64,7 +64,7 @@ import org.joda.time.Duration;
|
||||||
* @error {@link google.registry.flows.exceptions.MissingTransferRequestAuthInfoException}
|
* @error {@link google.registry.flows.exceptions.MissingTransferRequestAuthInfoException}
|
||||||
* @error {@link google.registry.flows.exceptions.ObjectAlreadySponsoredException}
|
* @error {@link google.registry.flows.exceptions.ObjectAlreadySponsoredException}
|
||||||
*/
|
*/
|
||||||
public final class ContactTransferRequestFlow extends Flow implements TransactionalFlow {
|
public final class ContactTransferRequestFlow implements TransactionalFlow {
|
||||||
|
|
||||||
private static final ImmutableSet<StatusValue> DISALLOWED_STATUSES = ImmutableSet.of(
|
private static final ImmutableSet<StatusValue> DISALLOWED_STATUSES = ImmutableSet.of(
|
||||||
StatusValue.CLIENT_TRANSFER_PROHIBITED,
|
StatusValue.CLIENT_TRANSFER_PROHIBITED,
|
||||||
|
@ -77,13 +77,16 @@ public final class ContactTransferRequestFlow extends Flow implements Transactio
|
||||||
@Inject @TargetId String targetId;
|
@Inject @TargetId String targetId;
|
||||||
@Inject @Config("contactAutomaticTransferLength") Duration automaticTransferLength;
|
@Inject @Config("contactAutomaticTransferLength") Duration automaticTransferLength;
|
||||||
@Inject HistoryEntry.Builder historyBuilder;
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
|
@Inject Trid trid;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject ContactTransferRequestFlow() {}
|
@Inject ContactTransferRequestFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.register(MetadataExtension.class);
|
extensionManager.register(MetadataExtension.class);
|
||||||
extensionManager.validate();
|
extensionManager.validate();
|
||||||
validateClientIsLoggedIn(gainingClientId);
|
validateClientIsLoggedIn(gainingClientId);
|
||||||
|
DateTime now = ofy().getTransactionTime();
|
||||||
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
||||||
verifyRequiredAuthInfoForResourceTransfer(authInfo, existingContact);
|
verifyRequiredAuthInfoForResourceTransfer(authInfo, existingContact);
|
||||||
// Verify that the resource does not already have a pending transfer.
|
// Verify that the resource does not already have a pending transfer.
|
||||||
|
@ -138,9 +141,10 @@ public final class ContactTransferRequestFlow extends Flow implements Transactio
|
||||||
requestPollMessage,
|
requestPollMessage,
|
||||||
serverApproveGainingPollMessage,
|
serverApproveGainingPollMessage,
|
||||||
serverApproveLosingPollMessage);
|
serverApproveLosingPollMessage);
|
||||||
return createOutput(
|
return responseBuilder
|
||||||
SUCCESS_WITH_ACTION_PENDING,
|
.setResultFromCode(SUCCESS_WITH_ACTION_PENDING)
|
||||||
createTransferResponse(targetId, newContact.getTransferData()));
|
.setResData(createTransferResponse(targetId, newContact.getTransferData()))
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,6 @@ import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForR
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
|
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.eppoutput.Result.Code.SUCCESS;
|
|
||||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
|
@ -32,8 +31,8 @@ import com.google.common.collect.ImmutableSet;
|
||||||
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;
|
||||||
import google.registry.flows.Flow;
|
|
||||||
import google.registry.flows.FlowModule.ClientId;
|
import google.registry.flows.FlowModule.ClientId;
|
||||||
|
import google.registry.flows.FlowModule.Superuser;
|
||||||
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.ResourceHasClientUpdateProhibitedException;
|
import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException;
|
||||||
|
@ -46,10 +45,11 @@ 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.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An EPP flow that updates a contact.
|
* An EPP flow that updates a contact.
|
||||||
|
@ -63,7 +63,7 @@ import javax.inject.Inject;
|
||||||
* @error {@link ContactFlowUtils.BadInternationalizedPostalInfoException}
|
* @error {@link ContactFlowUtils.BadInternationalizedPostalInfoException}
|
||||||
* @error {@link ContactFlowUtils.DeclineContactDisclosureFieldDisallowedPolicyException}
|
* @error {@link ContactFlowUtils.DeclineContactDisclosureFieldDisallowedPolicyException}
|
||||||
*/
|
*/
|
||||||
public final class ContactUpdateFlow extends Flow implements TransactionalFlow {
|
public final class ContactUpdateFlow implements TransactionalFlow {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note that CLIENT_UPDATE_PROHIBITED is intentionally not in this list. This is because it
|
* Note that CLIENT_UPDATE_PROHIBITED is intentionally not in this list. This is because it
|
||||||
|
@ -79,15 +79,18 @@ public final class ContactUpdateFlow extends Flow implements TransactionalFlow {
|
||||||
@Inject Optional<AuthInfo> authInfo;
|
@Inject Optional<AuthInfo> authInfo;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject @TargetId String targetId;
|
@Inject @TargetId String targetId;
|
||||||
|
@Inject @Superuser boolean isSuperuser;
|
||||||
@Inject HistoryEntry.Builder historyBuilder;
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject ContactUpdateFlow() {}
|
@Inject ContactUpdateFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.register(MetadataExtension.class);
|
extensionManager.register(MetadataExtension.class);
|
||||||
extensionManager.validate();
|
extensionManager.validate();
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
Update command = (Update) resourceCommand;
|
Update command = (Update) resourceCommand;
|
||||||
|
DateTime now = ofy().getTransactionTime();
|
||||||
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
||||||
verifyOptionalAuthInfoForResource(authInfo, existingContact);
|
verifyOptionalAuthInfoForResource(authInfo, existingContact);
|
||||||
ImmutableSet<StatusValue> statusToRemove = command.getInnerRemove().getStatusValues();
|
ImmutableSet<StatusValue> statusToRemove = command.getInnerRemove().getStatusValues();
|
||||||
|
@ -146,7 +149,7 @@ public final class ContactUpdateFlow extends Flow implements TransactionalFlow {
|
||||||
validateAsciiPostalInfo(newContact.getInternationalizedPostalInfo());
|
validateAsciiPostalInfo(newContact.getInternationalizedPostalInfo());
|
||||||
validateContactAgainstPolicy(newContact);
|
validateContactAgainstPolicy(newContact);
|
||||||
ofy().save().<Object>entities(newContact, historyBuilder.build());
|
ofy().save().<Object>entities(newContact, historyBuilder.build());
|
||||||
return createOutput(SUCCESS);
|
return responseBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return the first non-null param, or null if both are null. */
|
/** Return the first non-null param, or null if both are null. */
|
||||||
|
|
|
@ -22,7 +22,6 @@ import static google.registry.flows.domain.DomainFlowUtils.validateDomainNameWit
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.verifyClaimsPeriodNotEnded;
|
import static google.registry.flows.domain.DomainFlowUtils.verifyClaimsPeriodNotEnded;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.verifyNotInPredelegation;
|
import static google.registry.flows.domain.DomainFlowUtils.verifyNotInPredelegation;
|
||||||
import static google.registry.model.domain.launch.LaunchPhase.CLAIMS;
|
import static google.registry.model.domain.launch.LaunchPhase.CLAIMS;
|
||||||
import static google.registry.model.eppoutput.Result.Code.SUCCESS;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
@ -33,20 +32,23 @@ import google.registry.flows.EppException.CommandUseErrorException;
|
||||||
import google.registry.flows.ExtensionManager;
|
import google.registry.flows.ExtensionManager;
|
||||||
import google.registry.flows.Flow;
|
import google.registry.flows.Flow;
|
||||||
import google.registry.flows.FlowModule.ClientId;
|
import google.registry.flows.FlowModule.ClientId;
|
||||||
|
import google.registry.flows.FlowModule.Superuser;
|
||||||
import google.registry.model.domain.DomainCommand.Check;
|
import google.registry.model.domain.DomainCommand.Check;
|
||||||
import google.registry.model.domain.launch.LaunchCheckExtension;
|
import google.registry.model.domain.launch.LaunchCheckExtension;
|
||||||
import google.registry.model.domain.launch.LaunchCheckResponseExtension;
|
import google.registry.model.domain.launch.LaunchCheckResponseExtension;
|
||||||
import google.registry.model.domain.launch.LaunchCheckResponseExtension.LaunchCheck;
|
import google.registry.model.domain.launch.LaunchCheckResponseExtension.LaunchCheck;
|
||||||
import google.registry.model.domain.launch.LaunchCheckResponseExtension.LaunchCheckName;
|
import google.registry.model.domain.launch.LaunchCheckResponseExtension.LaunchCheckName;
|
||||||
import google.registry.model.eppinput.ResourceCommand;
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.registry.Registry;
|
import google.registry.model.registry.Registry;
|
||||||
import google.registry.model.registry.Registry.TldState;
|
import google.registry.model.registry.Registry.TldState;
|
||||||
import google.registry.model.tmch.ClaimsListShard;
|
import google.registry.model.tmch.ClaimsListShard;
|
||||||
|
import google.registry.util.Clock;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An EPP flow that checks whether strings are trademarked.
|
* An EPP flow that checks whether strings are trademarked.
|
||||||
|
@ -58,16 +60,19 @@ import javax.inject.Inject;
|
||||||
* @error {@link DomainFlowUtils.TldDoesNotExistException}
|
* @error {@link DomainFlowUtils.TldDoesNotExistException}
|
||||||
* @error {@link ClaimsCheckNotAllowedInSunrise}
|
* @error {@link ClaimsCheckNotAllowedInSunrise}
|
||||||
*/
|
*/
|
||||||
public final class ClaimsCheckFlow extends Flow {
|
public final class ClaimsCheckFlow implements Flow {
|
||||||
|
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
@Inject ResourceCommand resourceCommand;
|
@Inject ResourceCommand resourceCommand;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
|
@Inject @Superuser boolean isSuperuser;
|
||||||
|
@Inject Clock clock;
|
||||||
@Inject @Config("maxChecks") int maxChecks;
|
@Inject @Config("maxChecks") int maxChecks;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject ClaimsCheckFlow() {}
|
@Inject ClaimsCheckFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EppOutput run() throws EppException {
|
public EppResponse run() throws EppException {
|
||||||
extensionManager.register(LaunchCheckExtension.class);
|
extensionManager.register(LaunchCheckExtension.class);
|
||||||
extensionManager.validate();
|
extensionManager.validate();
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
|
@ -84,6 +89,7 @@ public final class ClaimsCheckFlow extends Flow {
|
||||||
checkAllowedAccessToTld(clientId, tld);
|
checkAllowedAccessToTld(clientId, tld);
|
||||||
Registry registry = Registry.get(tld);
|
Registry registry = Registry.get(tld);
|
||||||
if (!isSuperuser) {
|
if (!isSuperuser) {
|
||||||
|
DateTime now = clock.nowUtc();
|
||||||
verifyNotInPredelegation(registry, now);
|
verifyNotInPredelegation(registry, now);
|
||||||
if (registry.getTldState(now) == TldState.SUNRISE) {
|
if (registry.getTldState(now) == TldState.SUNRISE) {
|
||||||
throw new ClaimsCheckNotAllowedInSunrise();
|
throw new ClaimsCheckNotAllowedInSunrise();
|
||||||
|
@ -96,10 +102,9 @@ public final class ClaimsCheckFlow extends Flow {
|
||||||
LaunchCheck.create(
|
LaunchCheck.create(
|
||||||
LaunchCheckName.create(claimKey != null, targetId), claimKey));
|
LaunchCheckName.create(claimKey != null, targetId), claimKey));
|
||||||
}
|
}
|
||||||
return createOutput(
|
return responseBuilder
|
||||||
SUCCESS,
|
.setOnlyExtension(LaunchCheckResponseExtension.create(CLAIMS, launchChecksBuilder.build()))
|
||||||
null,
|
.build();
|
||||||
ImmutableList.of(LaunchCheckResponseExtension.create(CLAIMS, launchChecksBuilder.build())));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Claims checks are not allowed during sunrise. */
|
/** Claims checks are not allowed during sunrise. */
|
||||||
|
|
|
@ -48,8 +48,8 @@ import google.registry.flows.EppException.AuthorizationErrorException;
|
||||||
import google.registry.flows.EppException.ObjectDoesNotExistException;
|
import google.registry.flows.EppException.ObjectDoesNotExistException;
|
||||||
import google.registry.flows.EppException.StatusProhibitsOperationException;
|
import google.registry.flows.EppException.StatusProhibitsOperationException;
|
||||||
import google.registry.flows.ExtensionManager;
|
import google.registry.flows.ExtensionManager;
|
||||||
import google.registry.flows.Flow;
|
|
||||||
import google.registry.flows.FlowModule.ClientId;
|
import google.registry.flows.FlowModule.ClientId;
|
||||||
|
import google.registry.flows.FlowModule.Superuser;
|
||||||
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.domain.TldSpecificLogicProxy.EppCommandOperations;
|
import google.registry.flows.domain.TldSpecificLogicProxy.EppCommandOperations;
|
||||||
|
@ -73,10 +73,10 @@ import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||||
import google.registry.model.domain.secdns.SecDnsCreateExtension;
|
import google.registry.model.domain.secdns.SecDnsCreateExtension;
|
||||||
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.EppInput;
|
||||||
import google.registry.model.eppinput.ResourceCommand;
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
import google.registry.model.eppoutput.CreateData.DomainCreateData;
|
import google.registry.model.eppoutput.CreateData.DomainCreateData;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.eppoutput.Result;
|
|
||||||
import google.registry.model.index.EppResourceIndex;
|
import google.registry.model.index.EppResourceIndex;
|
||||||
import google.registry.model.index.ForeignKeyIndex;
|
import google.registry.model.index.ForeignKeyIndex;
|
||||||
import google.registry.model.ofy.ObjectifyService;
|
import google.registry.model.ofy.ObjectifyService;
|
||||||
|
@ -97,7 +97,7 @@ import org.joda.time.DateTime;
|
||||||
* @error {@link DomainAllocateFlow.MissingApplicationException}
|
* @error {@link DomainAllocateFlow.MissingApplicationException}
|
||||||
* @error {@link DomainAllocateFlow.OnlySuperuserCanAllocateException}
|
* @error {@link DomainAllocateFlow.OnlySuperuserCanAllocateException}
|
||||||
*/
|
*/
|
||||||
public class DomainAllocateFlow extends Flow implements TransactionalFlow {
|
public class DomainAllocateFlow implements TransactionalFlow {
|
||||||
|
|
||||||
private static final String COLLISION_MESSAGE =
|
private static final String COLLISION_MESSAGE =
|
||||||
"Domain on the name collision list was allocated. But by policy, the domain will not be "
|
"Domain on the name collision list was allocated. But by policy, the domain will not be "
|
||||||
|
@ -109,11 +109,14 @@ public class DomainAllocateFlow extends Flow implements TransactionalFlow {
|
||||||
@Inject ResourceCommand resourceCommand;
|
@Inject ResourceCommand resourceCommand;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject @TargetId String targetId;
|
@Inject @TargetId String targetId;
|
||||||
|
@Inject @Superuser boolean isSuperuser;
|
||||||
@Inject HistoryEntry.Builder historyBuilder;
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
|
@Inject EppInput eppInput;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject DomainAllocateFlow() {}
|
@Inject DomainAllocateFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.register(
|
extensionManager.register(
|
||||||
SecDnsCreateExtension.class,
|
SecDnsCreateExtension.class,
|
||||||
FlagsCreateCommandExtension.class,
|
FlagsCreateCommandExtension.class,
|
||||||
|
@ -123,6 +126,7 @@ public class DomainAllocateFlow extends Flow implements TransactionalFlow {
|
||||||
extensionManager.validate();
|
extensionManager.validate();
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
verifyIsSuperuser();
|
verifyIsSuperuser();
|
||||||
|
DateTime now = ofy().getTransactionTime();
|
||||||
Create command = cloneAndLinkReferences((Create) resourceCommand, now);
|
Create command = cloneAndLinkReferences((Create) resourceCommand, now);
|
||||||
failfastForCreate(targetId, now);
|
failfastForCreate(targetId, now);
|
||||||
verifyResourceDoesNotExist(DomainResource.class, targetId, now);
|
verifyResourceDoesNotExist(DomainResource.class, targetId, now);
|
||||||
|
@ -137,13 +141,14 @@ public class DomainAllocateFlow extends Flow implements TransactionalFlow {
|
||||||
boolean isSunrushAddGracePeriod = isNullOrEmpty(command.getNameservers());
|
boolean isSunrushAddGracePeriod = isNullOrEmpty(command.getNameservers());
|
||||||
AllocateCreateExtension allocateCreate =
|
AllocateCreateExtension allocateCreate =
|
||||||
eppInput.getSingleExtension(AllocateCreateExtension.class);
|
eppInput.getSingleExtension(AllocateCreateExtension.class);
|
||||||
DomainApplication application = loadAndValidateApplication(allocateCreate.getApplicationRoid());
|
DomainApplication application =
|
||||||
|
loadAndValidateApplication(allocateCreate.getApplicationRoid(), now);
|
||||||
String repoId = createDomainRoid(ObjectifyService.allocateId(), registry.getTldStr());
|
String repoId = createDomainRoid(ObjectifyService.allocateId(), registry.getTldStr());
|
||||||
ImmutableSet.Builder<ImmutableObject> entitiesToSave = new ImmutableSet.Builder<>();
|
ImmutableSet.Builder<ImmutableObject> entitiesToSave = new ImmutableSet.Builder<>();
|
||||||
HistoryEntry historyEntry = buildHistory(repoId, period);
|
HistoryEntry historyEntry = buildHistory(repoId, period, now);
|
||||||
entitiesToSave.add(historyEntry);
|
entitiesToSave.add(historyEntry);
|
||||||
ImmutableSet<? extends ImmutableObject> billsAndPolls = createBillingEventsAndPollMessages(
|
ImmutableSet<? extends ImmutableObject> billsAndPolls = createBillingEventsAndPollMessages(
|
||||||
domainName, application, historyEntry, isSunrushAddGracePeriod, registry, years);
|
domainName, application, historyEntry, isSunrushAddGracePeriod, registry, now, years);
|
||||||
entitiesToSave.addAll(billsAndPolls);
|
entitiesToSave.addAll(billsAndPolls);
|
||||||
DateTime registrationExpirationTime = leapSafeAddYears(now, years);
|
DateTime registrationExpirationTime = leapSafeAddYears(now, years);
|
||||||
DomainResource newDomain = new DomainResource.Builder()
|
DomainResource newDomain = new DomainResource.Builder()
|
||||||
|
@ -173,21 +178,21 @@ public class DomainAllocateFlow extends Flow implements TransactionalFlow {
|
||||||
.build();
|
.build();
|
||||||
entitiesToSave.add(
|
entitiesToSave.add(
|
||||||
newDomain,
|
newDomain,
|
||||||
buildApplicationHistory(application),
|
buildApplicationHistory(application, now),
|
||||||
updateApplication(application),
|
updateApplication(application),
|
||||||
ForeignKeyIndex.create(newDomain, newDomain.getDeletionTime()),
|
ForeignKeyIndex.create(newDomain, newDomain.getDeletionTime()),
|
||||||
EppResourceIndex.create(Key.create(newDomain)));
|
EppResourceIndex.create(Key.create(newDomain)));
|
||||||
// Anchor tenant registrations override LRP.
|
// Anchor tenant registrations override LRP.
|
||||||
String authInfoToken = authInfo.getPw().getValue();
|
String authInfoToken = authInfo.getPw().getValue();
|
||||||
if (hasLrpToken(domainName, registry, authInfoToken)) {
|
if (hasLrpToken(domainName, registry, authInfoToken, now)) {
|
||||||
entitiesToSave.add(prepareMarkedLrpTokenEntity(authInfoToken, domainName, historyEntry));
|
entitiesToSave.add(prepareMarkedLrpTokenEntity(authInfoToken, domainName, historyEntry));
|
||||||
}
|
}
|
||||||
ofy().save().entities(entitiesToSave.build());
|
ofy().save().entities(entitiesToSave.build());
|
||||||
enqueueTasks(allocateCreate, newDomain);
|
enqueueTasks(allocateCreate, newDomain);
|
||||||
return createOutput(
|
return responseBuilder
|
||||||
Result.Code.SUCCESS,
|
.setResData(DomainCreateData.create(targetId, now, registrationExpirationTime))
|
||||||
DomainCreateData.create(targetId, now, registrationExpirationTime),
|
.setExtensions(createResponseExtensions(now, registry, years))
|
||||||
createResponseExtensions(registry, years));
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T extends ImmutableObject> T getOnly(
|
private <T extends ImmutableObject> T getOnly(
|
||||||
|
@ -201,7 +206,8 @@ public class DomainAllocateFlow extends Flow implements TransactionalFlow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private DomainApplication loadAndValidateApplication(String applicationRoid) throws EppException {
|
private DomainApplication loadAndValidateApplication(
|
||||||
|
String applicationRoid, DateTime now) throws EppException {
|
||||||
DomainApplication application = loadDomainApplication(applicationRoid, now);
|
DomainApplication application = loadDomainApplication(applicationRoid, now);
|
||||||
if (application == null) {
|
if (application == null) {
|
||||||
throw new MissingApplicationException(applicationRoid);
|
throw new MissingApplicationException(applicationRoid);
|
||||||
|
@ -212,7 +218,7 @@ public class DomainAllocateFlow extends Flow implements TransactionalFlow {
|
||||||
return application;
|
return application;
|
||||||
}
|
}
|
||||||
|
|
||||||
private HistoryEntry buildHistory(String repoId, Period period) {
|
private HistoryEntry buildHistory(String repoId, Period period, DateTime now) {
|
||||||
return historyBuilder
|
return historyBuilder
|
||||||
.setType(HistoryEntry.Type.DOMAIN_ALLOCATE)
|
.setType(HistoryEntry.Type.DOMAIN_ALLOCATE)
|
||||||
.setPeriod(period)
|
.setPeriod(period)
|
||||||
|
@ -227,12 +233,13 @@ public class DomainAllocateFlow extends Flow implements TransactionalFlow {
|
||||||
HistoryEntry historyEntry,
|
HistoryEntry historyEntry,
|
||||||
boolean isSunrushAddGracePeriod,
|
boolean isSunrushAddGracePeriod,
|
||||||
Registry registry,
|
Registry registry,
|
||||||
|
DateTime now,
|
||||||
int years) {
|
int years) {
|
||||||
DateTime registrationExpirationTime = leapSafeAddYears(now, years);
|
DateTime registrationExpirationTime = leapSafeAddYears(now, years);
|
||||||
BillingEvent.OneTime oneTimeBillingEvent = createOneTimeBillingEvent(
|
BillingEvent.OneTime oneTimeBillingEvent = createOneTimeBillingEvent(
|
||||||
application, historyEntry, isSunrushAddGracePeriod, registry, years);
|
application, historyEntry, isSunrushAddGracePeriod, registry, now, years);
|
||||||
PollMessage.OneTime oneTimePollMessage =
|
PollMessage.OneTime oneTimePollMessage =
|
||||||
createOneTimePollMessage(application, historyEntry, getReservationType(domainName));
|
createOneTimePollMessage(application, historyEntry, getReservationType(domainName), now);
|
||||||
// Create a new autorenew billing event and poll message starting at the expiration time.
|
// Create a new autorenew billing event and poll message starting at the expiration time.
|
||||||
BillingEvent.Recurring autorenewBillingEvent =
|
BillingEvent.Recurring autorenewBillingEvent =
|
||||||
createAutorenewBillingEvent(historyEntry, registrationExpirationTime);
|
createAutorenewBillingEvent(historyEntry, registrationExpirationTime);
|
||||||
|
@ -250,6 +257,7 @@ public class DomainAllocateFlow extends Flow implements TransactionalFlow {
|
||||||
HistoryEntry historyEntry,
|
HistoryEntry historyEntry,
|
||||||
boolean isSunrushAddGracePeriod,
|
boolean isSunrushAddGracePeriod,
|
||||||
Registry registry,
|
Registry registry,
|
||||||
|
DateTime now,
|
||||||
int years) {
|
int years) {
|
||||||
return new BillingEvent.OneTime.Builder()
|
return new BillingEvent.OneTime.Builder()
|
||||||
.setReason(Reason.CREATE)
|
.setReason(Reason.CREATE)
|
||||||
|
@ -296,7 +304,7 @@ public class DomainAllocateFlow extends Flow implements TransactionalFlow {
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private GracePeriod createGracePeriod(boolean isSunrushAddGracePeriod,
|
private static GracePeriod createGracePeriod(boolean isSunrushAddGracePeriod,
|
||||||
BillingEvent.OneTime oneTimeBillingEvent) {
|
BillingEvent.OneTime oneTimeBillingEvent) {
|
||||||
return GracePeriod.forBillingEvent(
|
return GracePeriod.forBillingEvent(
|
||||||
isSunrushAddGracePeriod ? GracePeriodStatus.SUNRUSH_ADD : GracePeriodStatus.ADD,
|
isSunrushAddGracePeriod ? GracePeriodStatus.SUNRUSH_ADD : GracePeriodStatus.ADD,
|
||||||
|
@ -304,7 +312,7 @@ public class DomainAllocateFlow extends Flow implements TransactionalFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Create a history entry (with no xml or trid) to record that we updated the application. */
|
/** Create a history entry (with no xml or trid) to record that we updated the application. */
|
||||||
private HistoryEntry buildApplicationHistory(DomainApplication application) {
|
private static HistoryEntry buildApplicationHistory(DomainApplication application, DateTime now) {
|
||||||
return new HistoryEntry.Builder()
|
return new HistoryEntry.Builder()
|
||||||
.setType(HistoryEntry.Type.DOMAIN_APPLICATION_STATUS_UPDATE)
|
.setType(HistoryEntry.Type.DOMAIN_APPLICATION_STATUS_UPDATE)
|
||||||
.setParent(application)
|
.setParent(application)
|
||||||
|
@ -324,7 +332,10 @@ public class DomainAllocateFlow extends Flow implements TransactionalFlow {
|
||||||
|
|
||||||
/** Create a poll message informing the registrar that the application status was updated. */
|
/** Create a poll message informing the registrar that the application status was updated. */
|
||||||
private PollMessage.OneTime createOneTimePollMessage(
|
private PollMessage.OneTime createOneTimePollMessage(
|
||||||
DomainApplication application, HistoryEntry historyEntry, ReservationType reservationType) {
|
DomainApplication application,
|
||||||
|
HistoryEntry historyEntry,
|
||||||
|
ReservationType reservationType,
|
||||||
|
DateTime now) {
|
||||||
return new PollMessage.OneTime.Builder()
|
return new PollMessage.OneTime.Builder()
|
||||||
.setClientId(historyEntry.getClientId())
|
.setClientId(historyEntry.getClientId())
|
||||||
.setEventTime(now)
|
.setEventTime(now)
|
||||||
|
@ -345,7 +356,7 @@ public class DomainAllocateFlow extends Flow implements TransactionalFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasLrpToken(
|
private boolean hasLrpToken(
|
||||||
InternetDomainName domainName, Registry registry, String authInfoToken) {
|
InternetDomainName domainName, Registry registry, String authInfoToken, DateTime now) {
|
||||||
return registry.getLrpPeriod().contains(now)
|
return registry.getLrpPeriod().contains(now)
|
||||||
&& !matchesAnchorTenantReservation(domainName, authInfoToken);
|
&& !matchesAnchorTenantReservation(domainName, authInfoToken);
|
||||||
}
|
}
|
||||||
|
@ -360,7 +371,7 @@ public class DomainAllocateFlow extends Flow implements TransactionalFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
private ImmutableList<FeeTransformResponseExtension> createResponseExtensions(
|
private ImmutableList<FeeTransformResponseExtension> createResponseExtensions(
|
||||||
Registry registry, int years) throws EppException {
|
DateTime now, Registry registry, int years) throws EppException {
|
||||||
EppCommandOperations commandOperations = TldSpecificLogicProxy.getCreatePrice(
|
EppCommandOperations commandOperations = TldSpecificLogicProxy.getCreatePrice(
|
||||||
registry, targetId, clientId, now, years, eppInput);
|
registry, targetId, clientId, now, years, eppInput);
|
||||||
FeeTransformCommandExtension feeCreate =
|
FeeTransformCommandExtension feeCreate =
|
||||||
|
|
|
@ -39,7 +39,6 @@ import static google.registry.flows.domain.DomainFlowUtils.verifySignedMarks;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears;
|
import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears;
|
||||||
import static google.registry.model.EppResourceUtils.createDomainRoid;
|
import static google.registry.model.EppResourceUtils.createDomainRoid;
|
||||||
import static google.registry.model.domain.fee.Fee.FEE_CREATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER;
|
import static google.registry.model.domain.fee.Fee.FEE_CREATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER;
|
||||||
import static google.registry.model.eppoutput.Result.Code.SUCCESS;
|
|
||||||
import static google.registry.model.index.DomainApplicationIndex.loadActiveApplicationsByDomainName;
|
import static google.registry.model.index.DomainApplicationIndex.loadActiveApplicationsByDomainName;
|
||||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
import static google.registry.model.registry.label.ReservedList.matchesAnchorTenantReservation;
|
import static google.registry.model.registry.label.ReservedList.matchesAnchorTenantReservation;
|
||||||
|
@ -56,8 +55,8 @@ import google.registry.flows.EppException.CommandUseErrorException;
|
||||||
import google.registry.flows.EppException.ObjectAlreadyExistsException;
|
import google.registry.flows.EppException.ObjectAlreadyExistsException;
|
||||||
import google.registry.flows.EppException.RequiredParameterMissingException;
|
import google.registry.flows.EppException.RequiredParameterMissingException;
|
||||||
import google.registry.flows.ExtensionManager;
|
import google.registry.flows.ExtensionManager;
|
||||||
import google.registry.flows.Flow;
|
|
||||||
import google.registry.flows.FlowModule.ClientId;
|
import google.registry.flows.FlowModule.ClientId;
|
||||||
|
import google.registry.flows.FlowModule.Superuser;
|
||||||
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.domain.TldSpecificLogicProxy.EppCommandOperations;
|
import google.registry.flows.domain.TldSpecificLogicProxy.EppCommandOperations;
|
||||||
|
@ -76,9 +75,11 @@ import google.registry.model.domain.metadata.MetadataExtension;
|
||||||
import google.registry.model.domain.secdns.SecDnsCreateExtension;
|
import google.registry.model.domain.secdns.SecDnsCreateExtension;
|
||||||
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.eppcommon.Trid;
|
||||||
|
import google.registry.model.eppinput.EppInput;
|
||||||
import google.registry.model.eppinput.ResourceCommand;
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
import google.registry.model.eppoutput.CreateData.DomainCreateData;
|
import google.registry.model.eppoutput.CreateData.DomainCreateData;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
|
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
|
||||||
import google.registry.model.index.DomainApplicationIndex;
|
import google.registry.model.index.DomainApplicationIndex;
|
||||||
import google.registry.model.index.EppResourceIndex;
|
import google.registry.model.index.EppResourceIndex;
|
||||||
|
@ -89,6 +90,7 @@ import google.registry.model.reporting.HistoryEntry;
|
||||||
import google.registry.model.smd.AbstractSignedMark;
|
import google.registry.model.smd.AbstractSignedMark;
|
||||||
import google.registry.model.smd.EncodedSignedMark;
|
import google.registry.model.smd.EncodedSignedMark;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An EPP flow that creates a new application for a domain resource.
|
* An EPP flow that creates a new application for a domain resource.
|
||||||
|
@ -153,18 +155,22 @@ import javax.inject.Inject;
|
||||||
* @error {@link DomainFlowUtils.UnsupportedFeeAttributeException}
|
* @error {@link DomainFlowUtils.UnsupportedFeeAttributeException}
|
||||||
* @error {@link DomainFlowUtils.UnsupportedMarkTypeException}
|
* @error {@link DomainFlowUtils.UnsupportedMarkTypeException}
|
||||||
*/
|
*/
|
||||||
public final class DomainApplicationCreateFlow extends Flow implements TransactionalFlow {
|
public final class DomainApplicationCreateFlow implements TransactionalFlow {
|
||||||
|
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
|
@Inject EppInput eppInput;
|
||||||
@Inject AuthInfo authInfo;
|
@Inject AuthInfo authInfo;
|
||||||
@Inject ResourceCommand resourceCommand;
|
@Inject ResourceCommand resourceCommand;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject @TargetId String targetId;
|
@Inject @TargetId String targetId;
|
||||||
|
@Inject @Superuser boolean isSuperuser;
|
||||||
@Inject HistoryEntry.Builder historyBuilder;
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
|
@Inject Trid trid;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject DomainApplicationCreateFlow() {}
|
@Inject DomainApplicationCreateFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.register(
|
extensionManager.register(
|
||||||
SecDnsCreateExtension.class,
|
SecDnsCreateExtension.class,
|
||||||
FlagsCreateCommandExtension.class,
|
FlagsCreateCommandExtension.class,
|
||||||
|
@ -173,6 +179,7 @@ public final class DomainApplicationCreateFlow extends Flow implements Transacti
|
||||||
extensionManager.registerAsGroup(FEE_CREATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
|
extensionManager.registerAsGroup(FEE_CREATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
|
||||||
extensionManager.validate();
|
extensionManager.validate();
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
|
DateTime now = ofy().getTransactionTime();
|
||||||
Create command = cloneAndLinkReferences((Create) resourceCommand, now);
|
Create command = cloneAndLinkReferences((Create) resourceCommand, now);
|
||||||
failfastForCreate(targetId, now);
|
failfastForCreate(targetId, now);
|
||||||
// Fail if the domain is already registered (e.g. this is a landrush application but the domain
|
// Fail if the domain is already registered (e.g. this is a landrush application but the domain
|
||||||
|
@ -193,13 +200,13 @@ public final class DomainApplicationCreateFlow extends Flow implements Transacti
|
||||||
validateCreateCommandContactsAndNameservers(command, tld);
|
validateCreateCommandContactsAndNameservers(command, tld);
|
||||||
LaunchCreateExtension launchCreate = eppInput.getSingleExtension(LaunchCreateExtension.class);
|
LaunchCreateExtension launchCreate = eppInput.getSingleExtension(LaunchCreateExtension.class);
|
||||||
if (launchCreate != null) {
|
if (launchCreate != null) {
|
||||||
validateLaunchCreateExtension(launchCreate, registry, domainName);
|
validateLaunchCreateExtension(launchCreate, registry, domainName, now);
|
||||||
}
|
}
|
||||||
boolean isAnchorTenant =
|
boolean isAnchorTenant =
|
||||||
matchesAnchorTenantReservation(domainName, authInfo.getPw().getValue());
|
matchesAnchorTenantReservation(domainName, authInfo.getPw().getValue());
|
||||||
if (!isSuperuser) {
|
if (!isSuperuser) {
|
||||||
verifyPremiumNameIsNotBlocked(targetId, now, clientId);
|
verifyPremiumNameIsNotBlocked(targetId, now, clientId);
|
||||||
prohibitLandrushIfExactlyOneSunrise(registry);
|
prohibitLandrushIfExactlyOneSunrise(registry, now);
|
||||||
if (!isAnchorTenant) {
|
if (!isAnchorTenant) {
|
||||||
boolean isSunriseApplication = !launchCreate.getSignedMarks().isEmpty();
|
boolean isSunriseApplication = !launchCreate.getSignedMarks().isEmpty();
|
||||||
verifyNotReserved(domainName, isSunriseApplication);
|
verifyNotReserved(domainName, isSunriseApplication);
|
||||||
|
@ -236,7 +243,7 @@ public final class DomainApplicationCreateFlow extends Flow implements Transacti
|
||||||
}})
|
}})
|
||||||
.toList())
|
.toList())
|
||||||
.build();
|
.build();
|
||||||
HistoryEntry historyEntry = buildHistory(newApplication.getRepoId(), command.getPeriod());
|
HistoryEntry historyEntry = buildHistory(newApplication.getRepoId(), command.getPeriod(), now);
|
||||||
ImmutableSet.Builder<ImmutableObject> entitiesToSave = new ImmutableSet.Builder<>();
|
ImmutableSet.Builder<ImmutableObject> entitiesToSave = new ImmutableSet.Builder<>();
|
||||||
handleExtraFlowLogic(
|
handleExtraFlowLogic(
|
||||||
registry.getTldStr(), command.getPeriod().getValue(), historyEntry, newApplication);
|
registry.getTldStr(), command.getPeriod().getValue(), historyEntry, newApplication);
|
||||||
|
@ -252,16 +259,18 @@ public final class DomainApplicationCreateFlow extends Flow implements Transacti
|
||||||
prepareMarkedLrpTokenEntity(authInfo.getPw().getValue(), domainName, historyEntry));
|
prepareMarkedLrpTokenEntity(authInfo.getPw().getValue(), domainName, historyEntry));
|
||||||
}
|
}
|
||||||
ofy().save().entities(entitiesToSave.build());
|
ofy().save().entities(entitiesToSave.build());
|
||||||
return createOutput(
|
return responseBuilder
|
||||||
SUCCESS,
|
.setResData(DomainCreateData.create(targetId, now, null))
|
||||||
DomainCreateData.create(targetId, now, null),
|
.setExtensions(createResponseExtensions(
|
||||||
createResponseExtensions(
|
newApplication.getForeignKey(), launchCreate.getPhase(), feeCreate, commandOperations))
|
||||||
newApplication.getForeignKey(), launchCreate.getPhase(), feeCreate, commandOperations));
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateLaunchCreateExtension(
|
private void validateLaunchCreateExtension(
|
||||||
LaunchCreateExtension launchCreate, Registry registry, InternetDomainName domainName)
|
LaunchCreateExtension launchCreate,
|
||||||
throws EppException {
|
Registry registry,
|
||||||
|
InternetDomainName domainName,
|
||||||
|
DateTime now) throws EppException {
|
||||||
verifyNoCodeMarks(launchCreate);
|
verifyNoCodeMarks(launchCreate);
|
||||||
boolean hasClaimsNotice = launchCreate.getNotice() != null;
|
boolean hasClaimsNotice = launchCreate.getNotice() != null;
|
||||||
if (hasClaimsNotice) {
|
if (hasClaimsNotice) {
|
||||||
|
@ -302,7 +311,7 @@ public final class DomainApplicationCreateFlow extends Flow implements Transacti
|
||||||
* Prohibit creating a landrush application in LANDRUSH (but not in SUNRUSH) if there is exactly
|
* Prohibit creating a landrush application in LANDRUSH (but not in SUNRUSH) if there is exactly
|
||||||
* one sunrise application for the same name.
|
* one sunrise application for the same name.
|
||||||
*/
|
*/
|
||||||
private void prohibitLandrushIfExactlyOneSunrise(Registry registry)
|
private void prohibitLandrushIfExactlyOneSunrise(Registry registry, DateTime now)
|
||||||
throws UncontestedSunriseApplicationBlockedInLandrushException {
|
throws UncontestedSunriseApplicationBlockedInLandrushException {
|
||||||
if (registry.getTldState(now) == TldState.LANDRUSH) {
|
if (registry.getTldState(now) == TldState.LANDRUSH) {
|
||||||
ImmutableSet<DomainApplication> applications =
|
ImmutableSet<DomainApplication> applications =
|
||||||
|
@ -314,7 +323,7 @@ public final class DomainApplicationCreateFlow extends Flow implements Transacti
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private HistoryEntry buildHistory(String repoId, Period period) {
|
private HistoryEntry buildHistory(String repoId, Period period, DateTime now) {
|
||||||
return historyBuilder
|
return historyBuilder
|
||||||
.setType(HistoryEntry.Type.DOMAIN_APPLICATION_CREATE)
|
.setType(HistoryEntry.Type.DOMAIN_APPLICATION_CREATE)
|
||||||
.setPeriod(period)
|
.setPeriod(period)
|
||||||
|
@ -349,7 +358,7 @@ public final class DomainApplicationCreateFlow extends Flow implements Transacti
|
||||||
extraFlowLogic.get().performAdditionalApplicationCreateLogic(
|
extraFlowLogic.get().performAdditionalApplicationCreateLogic(
|
||||||
newApplication,
|
newApplication,
|
||||||
clientId,
|
clientId,
|
||||||
now,
|
newApplication.getCreationTime(),
|
||||||
years,
|
years,
|
||||||
eppInput,
|
eppInput,
|
||||||
historyEntry);
|
historyEntry);
|
||||||
|
|
|
@ -26,7 +26,6 @@ import static google.registry.flows.domain.DomainFlowUtils.verifyApplicationDoma
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.verifyLaunchPhaseMatchesRegistryPhase;
|
import static google.registry.flows.domain.DomainFlowUtils.verifyLaunchPhaseMatchesRegistryPhase;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.verifyRegistryStateAllowsLaunchFlows;
|
import static google.registry.flows.domain.DomainFlowUtils.verifyRegistryStateAllowsLaunchFlows;
|
||||||
import static google.registry.model.EppResourceUtils.loadDomainApplication;
|
import static google.registry.model.EppResourceUtils.loadDomainApplication;
|
||||||
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;
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
|
@ -34,9 +33,9 @@ import com.googlecode.objectify.Key;
|
||||||
import google.registry.flows.EppException;
|
import google.registry.flows.EppException;
|
||||||
import google.registry.flows.EppException.StatusProhibitsOperationException;
|
import google.registry.flows.EppException.StatusProhibitsOperationException;
|
||||||
import google.registry.flows.ExtensionManager;
|
import google.registry.flows.ExtensionManager;
|
||||||
import google.registry.flows.Flow;
|
|
||||||
import google.registry.flows.FlowModule.ApplicationId;
|
import google.registry.flows.FlowModule.ApplicationId;
|
||||||
import google.registry.flows.FlowModule.ClientId;
|
import google.registry.flows.FlowModule.ClientId;
|
||||||
|
import google.registry.flows.FlowModule.Superuser;
|
||||||
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.model.domain.DomainApplication;
|
import google.registry.model.domain.DomainApplication;
|
||||||
|
@ -44,11 +43,13 @@ import google.registry.model.domain.launch.LaunchDeleteExtension;
|
||||||
import google.registry.model.domain.launch.LaunchPhase;
|
import google.registry.model.domain.launch.LaunchPhase;
|
||||||
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.eppoutput.EppOutput;
|
import google.registry.model.eppinput.EppInput;
|
||||||
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.registry.Registry;
|
import google.registry.model.registry.Registry;
|
||||||
import google.registry.model.registry.Registry.TldState;
|
import google.registry.model.registry.Registry.TldState;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An EPP flow that deletes a domain application.
|
* An EPP flow that deletes a domain application.
|
||||||
|
@ -62,21 +63,25 @@ import javax.inject.Inject;
|
||||||
* @error {@link DomainFlowUtils.LaunchPhaseMismatchException}
|
* @error {@link DomainFlowUtils.LaunchPhaseMismatchException}
|
||||||
* @error {@link DomainFlowUtils.NotAuthorizedForTldException}
|
* @error {@link DomainFlowUtils.NotAuthorizedForTldException}
|
||||||
*/
|
*/
|
||||||
public final class DomainApplicationDeleteFlow extends Flow implements TransactionalFlow {
|
public final class DomainApplicationDeleteFlow implements TransactionalFlow {
|
||||||
|
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
|
@Inject EppInput eppInput;
|
||||||
@Inject Optional<AuthInfo> authInfo;
|
@Inject Optional<AuthInfo> authInfo;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject @TargetId String targetId;
|
@Inject @TargetId String targetId;
|
||||||
@Inject @ApplicationId String applicationId;
|
@Inject @ApplicationId String applicationId;
|
||||||
|
@Inject @Superuser boolean isSuperuser;
|
||||||
@Inject HistoryEntry.Builder historyBuilder;
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject DomainApplicationDeleteFlow() {}
|
@Inject DomainApplicationDeleteFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.register(MetadataExtension.class, LaunchDeleteExtension.class);
|
extensionManager.register(MetadataExtension.class, LaunchDeleteExtension.class);
|
||||||
extensionManager.validate();
|
extensionManager.validate();
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
|
DateTime now = ofy().getTransactionTime();
|
||||||
DomainApplication existingApplication = verifyExistence(
|
DomainApplication existingApplication = verifyExistence(
|
||||||
DomainApplication.class, applicationId, loadDomainApplication(applicationId, now));
|
DomainApplication.class, applicationId, loadDomainApplication(applicationId, now));
|
||||||
verifyApplicationDomainMatchesTargetId(existingApplication, targetId);
|
verifyApplicationDomainMatchesTargetId(existingApplication, targetId);
|
||||||
|
@ -105,7 +110,7 @@ public final class DomainApplicationDeleteFlow extends Flow implements Transacti
|
||||||
updateForeignKeyIndexDeletionTime(newApplication);
|
updateForeignKeyIndexDeletionTime(newApplication);
|
||||||
handlePendingTransferOnDelete(existingApplication, newApplication, now, historyEntry);
|
handlePendingTransferOnDelete(existingApplication, newApplication, now, historyEntry);
|
||||||
ofy().save().<Object>entities(newApplication, historyEntry);
|
ofy().save().<Object>entities(newApplication, historyEntry);
|
||||||
return createOutput(SUCCESS);
|
return responseBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A sunrise application cannot be deleted during landrush. */
|
/** A sunrise application cannot be deleted during landrush. */
|
||||||
|
|
|
@ -22,7 +22,6 @@ import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.addSecDnsExtensionIfPresent;
|
import static google.registry.flows.domain.DomainFlowUtils.addSecDnsExtensionIfPresent;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.verifyApplicationDomainMatchesTargetId;
|
import static google.registry.flows.domain.DomainFlowUtils.verifyApplicationDomainMatchesTargetId;
|
||||||
import static google.registry.model.EppResourceUtils.loadDomainApplication;
|
import static google.registry.model.EppResourceUtils.loadDomainApplication;
|
||||||
import static google.registry.model.eppoutput.Result.Code.SUCCESS;
|
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
@ -39,12 +38,14 @@ import google.registry.model.domain.DomainCommand.Info;
|
||||||
import google.registry.model.domain.launch.LaunchInfoExtension;
|
import google.registry.model.domain.launch.LaunchInfoExtension;
|
||||||
import google.registry.model.domain.launch.LaunchInfoResponseExtension;
|
import google.registry.model.domain.launch.LaunchInfoResponseExtension;
|
||||||
import google.registry.model.eppcommon.AuthInfo;
|
import google.registry.model.eppcommon.AuthInfo;
|
||||||
|
import google.registry.model.eppinput.EppInput;
|
||||||
import google.registry.model.eppinput.ResourceCommand;
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
|
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
|
||||||
import google.registry.model.mark.Mark;
|
import google.registry.model.mark.Mark;
|
||||||
import google.registry.model.smd.EncodedSignedMark;
|
import google.registry.model.smd.EncodedSignedMark;
|
||||||
import google.registry.model.smd.SignedMark;
|
import google.registry.model.smd.SignedMark;
|
||||||
|
import google.registry.util.Clock;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -59,18 +60,21 @@ import javax.inject.Inject;
|
||||||
* @error {@link DomainApplicationInfoFlow.ApplicationLaunchPhaseMismatchException}
|
* @error {@link DomainApplicationInfoFlow.ApplicationLaunchPhaseMismatchException}
|
||||||
* @error {@link MissingApplicationIdException}
|
* @error {@link MissingApplicationIdException}
|
||||||
*/
|
*/
|
||||||
public final class DomainApplicationInfoFlow extends Flow {
|
public final class DomainApplicationInfoFlow implements Flow {
|
||||||
|
|
||||||
@Inject ResourceCommand resourceCommand;
|
@Inject ResourceCommand resourceCommand;
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
|
@Inject EppInput eppInput;
|
||||||
@Inject Optional<AuthInfo> authInfo;
|
@Inject Optional<AuthInfo> authInfo;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject @TargetId String targetId;
|
@Inject @TargetId String targetId;
|
||||||
@Inject @ApplicationId String applicationId;
|
@Inject @ApplicationId String applicationId;
|
||||||
|
@Inject Clock clock;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject DomainApplicationInfoFlow() {}
|
@Inject DomainApplicationInfoFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.register(LaunchInfoExtension.class);
|
extensionManager.register(LaunchInfoExtension.class);
|
||||||
extensionManager.validate();
|
extensionManager.validate();
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
|
@ -78,7 +82,9 @@ public final class DomainApplicationInfoFlow extends Flow {
|
||||||
throw new MissingApplicationIdException();
|
throw new MissingApplicationIdException();
|
||||||
}
|
}
|
||||||
DomainApplication application = verifyExistence(
|
DomainApplication application = verifyExistence(
|
||||||
DomainApplication.class, applicationId, loadDomainApplication(applicationId, now));
|
DomainApplication.class,
|
||||||
|
applicationId,
|
||||||
|
loadDomainApplication(applicationId, clock.nowUtc()));
|
||||||
verifyApplicationDomainMatchesTargetId(application, targetId);
|
verifyApplicationDomainMatchesTargetId(application, targetId);
|
||||||
verifyOptionalAuthInfoForResource(authInfo, application);
|
verifyOptionalAuthInfoForResource(authInfo, application);
|
||||||
LaunchInfoExtension launchInfo = eppInput.getSingleExtension(LaunchInfoExtension.class);
|
LaunchInfoExtension launchInfo = eppInput.getSingleExtension(LaunchInfoExtension.class);
|
||||||
|
@ -87,10 +93,10 @@ public final class DomainApplicationInfoFlow extends Flow {
|
||||||
}
|
}
|
||||||
// We don't support authInfo for applications, so if it's another registrar always fail.
|
// We don't support authInfo for applications, so if it's another registrar always fail.
|
||||||
verifyResourceOwnership(clientId, application);
|
verifyResourceOwnership(clientId, application);
|
||||||
return createOutput(
|
return responseBuilder
|
||||||
SUCCESS,
|
.setResData(getResourceInfo(application))
|
||||||
getResourceInfo(application),
|
.setExtensions(getDomainResponseExtensions(application, launchInfo))
|
||||||
getDomainResponseExtensions(application, launchInfo));
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
DomainApplication getResourceInfo(DomainApplication application) {
|
DomainApplication getResourceInfo(DomainApplication application) {
|
||||||
|
|
|
@ -40,7 +40,6 @@ import static google.registry.flows.domain.DomainFlowUtils.verifyClientUpdateNot
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.verifyNotInPendingDelete;
|
import static google.registry.flows.domain.DomainFlowUtils.verifyNotInPendingDelete;
|
||||||
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.ofy.ObjectifyService.ofy;
|
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
|
@ -50,9 +49,9 @@ import com.googlecode.objectify.Key;
|
||||||
import google.registry.flows.EppException;
|
import google.registry.flows.EppException;
|
||||||
import google.registry.flows.EppException.StatusProhibitsOperationException;
|
import google.registry.flows.EppException.StatusProhibitsOperationException;
|
||||||
import google.registry.flows.ExtensionManager;
|
import google.registry.flows.ExtensionManager;
|
||||||
import google.registry.flows.Flow;
|
|
||||||
import google.registry.flows.FlowModule.ApplicationId;
|
import google.registry.flows.FlowModule.ApplicationId;
|
||||||
import google.registry.flows.FlowModule.ClientId;
|
import google.registry.flows.FlowModule.ClientId;
|
||||||
|
import google.registry.flows.FlowModule.Superuser;
|
||||||
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.model.ImmutableObject;
|
import google.registry.model.ImmutableObject;
|
||||||
|
@ -66,10 +65,12 @@ import google.registry.model.domain.metadata.MetadataExtension;
|
||||||
import google.registry.model.domain.secdns.SecDnsUpdateExtension;
|
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.EppInput;
|
||||||
import google.registry.model.eppinput.ResourceCommand;
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An EPP flow that updates a domain application.
|
* An EPP flow that updates a domain application.
|
||||||
|
@ -101,7 +102,7 @@ import javax.inject.Inject;
|
||||||
* @error {@link DomainFlowUtils.UrgentAttributeNotSupportedException}
|
* @error {@link DomainFlowUtils.UrgentAttributeNotSupportedException}
|
||||||
* @error {@link DomainApplicationUpdateFlow.ApplicationStatusProhibitsUpdateException}
|
* @error {@link DomainApplicationUpdateFlow.ApplicationStatusProhibitsUpdateException}
|
||||||
*/
|
*/
|
||||||
public class DomainApplicationUpdateFlow extends Flow implements TransactionalFlow {
|
public class DomainApplicationUpdateFlow implements TransactionalFlow {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note that CLIENT_UPDATE_PROHIBITED is intentionally not in this list. This is because it
|
* Note that CLIENT_UPDATE_PROHIBITED is intentionally not in this list. This is because it
|
||||||
|
@ -121,15 +122,18 @@ public class DomainApplicationUpdateFlow extends Flow implements TransactionalFl
|
||||||
|
|
||||||
@Inject ResourceCommand resourceCommand;
|
@Inject ResourceCommand resourceCommand;
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
|
@Inject EppInput eppInput;
|
||||||
@Inject Optional<AuthInfo> authInfo;
|
@Inject Optional<AuthInfo> authInfo;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject @TargetId String targetId;
|
@Inject @TargetId String targetId;
|
||||||
@Inject @ApplicationId String applicationId;
|
@Inject @ApplicationId String applicationId;
|
||||||
|
@Inject @Superuser boolean isSuperuser;
|
||||||
@Inject HistoryEntry.Builder historyBuilder;
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject DomainApplicationUpdateFlow() {}
|
@Inject DomainApplicationUpdateFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.register(
|
extensionManager.register(
|
||||||
LaunchUpdateExtension.class,
|
LaunchUpdateExtension.class,
|
||||||
MetadataExtension.class,
|
MetadataExtension.class,
|
||||||
|
@ -137,6 +141,7 @@ public class DomainApplicationUpdateFlow extends Flow implements TransactionalFl
|
||||||
extensionManager.registerAsGroup(FEE_UPDATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
|
extensionManager.registerAsGroup(FEE_UPDATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
|
||||||
extensionManager.validate();
|
extensionManager.validate();
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
|
DateTime now = ofy().getTransactionTime();
|
||||||
Update command = cloneAndLinkReferences((Update) resourceCommand, now);
|
Update command = cloneAndLinkReferences((Update) resourceCommand, now);
|
||||||
DomainApplication existingApplication = verifyExistence(
|
DomainApplication existingApplication = verifyExistence(
|
||||||
DomainApplication.class, applicationId, loadDomainApplication(applicationId, now));
|
DomainApplication.class, applicationId, loadDomainApplication(applicationId, now));
|
||||||
|
@ -144,11 +149,11 @@ public class DomainApplicationUpdateFlow extends Flow implements TransactionalFl
|
||||||
verifyNoDisallowedStatuses(existingApplication, UPDATE_DISALLOWED_STATUSES);
|
verifyNoDisallowedStatuses(existingApplication, UPDATE_DISALLOWED_STATUSES);
|
||||||
verifyOptionalAuthInfoForResource(authInfo, existingApplication);
|
verifyOptionalAuthInfoForResource(authInfo, existingApplication);
|
||||||
verifyUpdateAllowed(existingApplication, command);
|
verifyUpdateAllowed(existingApplication, command);
|
||||||
HistoryEntry historyEntry = buildHistory(existingApplication);
|
HistoryEntry historyEntry = buildHistory(existingApplication, now);
|
||||||
DomainApplication newApplication = updateApplication(existingApplication, command);
|
DomainApplication newApplication = updateApplication(existingApplication, command, now);
|
||||||
validateNewApplication(newApplication);
|
validateNewApplication(newApplication);
|
||||||
ofy().save().<ImmutableObject>entities(newApplication, historyEntry);
|
ofy().save().<ImmutableObject>entities(newApplication, historyEntry);
|
||||||
return createOutput(SUCCESS);
|
return responseBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final void verifyUpdateAllowed(
|
protected final void verifyUpdateAllowed(
|
||||||
|
@ -178,7 +183,7 @@ public class DomainApplicationUpdateFlow extends Flow implements TransactionalFl
|
||||||
tld, add.getNameserverFullyQualifiedHostNames());
|
tld, add.getNameserverFullyQualifiedHostNames());
|
||||||
}
|
}
|
||||||
|
|
||||||
private HistoryEntry buildHistory(DomainApplication existingApplication) {
|
private HistoryEntry buildHistory(DomainApplication existingApplication, DateTime now) {
|
||||||
return historyBuilder
|
return historyBuilder
|
||||||
.setType(HistoryEntry.Type.DOMAIN_APPLICATION_UPDATE)
|
.setType(HistoryEntry.Type.DOMAIN_APPLICATION_UPDATE)
|
||||||
.setModificationTime(now)
|
.setModificationTime(now)
|
||||||
|
@ -187,7 +192,7 @@ public class DomainApplicationUpdateFlow extends Flow implements TransactionalFl
|
||||||
}
|
}
|
||||||
|
|
||||||
private DomainApplication updateApplication(
|
private DomainApplication updateApplication(
|
||||||
DomainApplication application, Update command) throws EppException {
|
DomainApplication application, Update command, DateTime now) throws EppException {
|
||||||
AddRemove add = command.getInnerAdd();
|
AddRemove add = command.getInnerAdd();
|
||||||
AddRemove remove = command.getInnerRemove();
|
AddRemove remove = command.getInnerRemove();
|
||||||
checkSameValuesNotAddedAndRemoved(add.getNameservers(), remove.getNameservers());
|
checkSameValuesNotAddedAndRemoved(add.getNameservers(), remove.getNameservers());
|
||||||
|
|
|
@ -24,12 +24,9 @@ import static google.registry.flows.domain.DomainFlowUtils.validateDomainNameWit
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.verifyNotInPredelegation;
|
import static google.registry.flows.domain.DomainFlowUtils.verifyNotInPredelegation;
|
||||||
import static google.registry.model.EppResourceUtils.checkResourcesExist;
|
import static google.registry.model.EppResourceUtils.checkResourcesExist;
|
||||||
import static google.registry.model.domain.fee.Fee.FEE_CHECK_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER;
|
import static google.registry.model.domain.fee.Fee.FEE_CHECK_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER;
|
||||||
import static google.registry.model.domain.fee.Fee.FEE_EXTENSION_URIS;
|
|
||||||
import static google.registry.model.eppoutput.Result.Code.SUCCESS;
|
|
||||||
import static google.registry.model.index.DomainApplicationIndex.loadActiveApplicationsByDomainName;
|
import static google.registry.model.index.DomainApplicationIndex.loadActiveApplicationsByDomainName;
|
||||||
import static google.registry.model.registry.label.ReservationType.UNRESERVED;
|
import static google.registry.model.registry.label.ReservationType.UNRESERVED;
|
||||||
import static google.registry.pricing.PricingEngineProxy.isDomainPremium;
|
import static google.registry.pricing.PricingEngineProxy.isDomainPremium;
|
||||||
import static google.registry.util.CollectionUtils.nullToEmpty;
|
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.FluentIterable;
|
import com.google.common.collect.FluentIterable;
|
||||||
|
@ -44,6 +41,7 @@ import google.registry.flows.EppException.ParameterValuePolicyErrorException;
|
||||||
import google.registry.flows.ExtensionManager;
|
import google.registry.flows.ExtensionManager;
|
||||||
import google.registry.flows.Flow;
|
import google.registry.flows.Flow;
|
||||||
import google.registry.flows.FlowModule.ClientId;
|
import google.registry.flows.FlowModule.ClientId;
|
||||||
|
import google.registry.flows.FlowModule.Superuser;
|
||||||
import google.registry.model.domain.DomainApplication;
|
import google.registry.model.domain.DomainApplication;
|
||||||
import google.registry.model.domain.DomainCommand.Check;
|
import google.registry.model.domain.DomainCommand.Check;
|
||||||
import google.registry.model.domain.DomainResource;
|
import google.registry.model.domain.DomainResource;
|
||||||
|
@ -51,19 +49,21 @@ import google.registry.model.domain.fee.FeeCheckCommandExtension;
|
||||||
import google.registry.model.domain.fee.FeeCheckCommandExtensionItem;
|
import google.registry.model.domain.fee.FeeCheckCommandExtensionItem;
|
||||||
import google.registry.model.domain.fee.FeeCheckResponseExtensionItem;
|
import google.registry.model.domain.fee.FeeCheckResponseExtensionItem;
|
||||||
import google.registry.model.domain.launch.LaunchCheckExtension;
|
import google.registry.model.domain.launch.LaunchCheckExtension;
|
||||||
|
import google.registry.model.eppinput.EppInput;
|
||||||
import google.registry.model.eppinput.ResourceCommand;
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
import google.registry.model.eppoutput.CheckData.DomainCheck;
|
import google.registry.model.eppoutput.CheckData.DomainCheck;
|
||||||
import google.registry.model.eppoutput.CheckData.DomainCheckData;
|
import google.registry.model.eppoutput.CheckData.DomainCheckData;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
|
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
|
||||||
import google.registry.model.registry.Registry;
|
import google.registry.model.registry.Registry;
|
||||||
import google.registry.model.registry.Registry.TldState;
|
import google.registry.model.registry.Registry.TldState;
|
||||||
import google.registry.model.registry.label.ReservationType;
|
import google.registry.model.registry.label.ReservationType;
|
||||||
import java.util.Collections;
|
import google.registry.util.Clock;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An EPP flow that checks whether a domain can be provisioned.
|
* An EPP flow that checks whether a domain can be provisioned.
|
||||||
|
@ -90,7 +90,7 @@ import javax.inject.Inject;
|
||||||
* @error {@link DomainFlowUtils.UnknownFeeCommandException}
|
* @error {@link DomainFlowUtils.UnknownFeeCommandException}
|
||||||
* @error {@link OnlyCheckedNamesCanBeFeeCheckedException}
|
* @error {@link OnlyCheckedNamesCanBeFeeCheckedException}
|
||||||
*/
|
*/
|
||||||
public final class DomainCheckFlow extends Flow {
|
public final class DomainCheckFlow implements Flow {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The TLD states during which we want to report a domain with pending applications as
|
* The TLD states during which we want to report a domain with pending applications as
|
||||||
|
@ -101,18 +101,23 @@ public final class DomainCheckFlow extends Flow {
|
||||||
|
|
||||||
@Inject ResourceCommand resourceCommand;
|
@Inject ResourceCommand resourceCommand;
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
|
@Inject EppInput eppInput;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject @Config("maxChecks") int maxChecks;
|
@Inject @Config("maxChecks") int maxChecks;
|
||||||
|
@Inject @Superuser boolean isSuperuser;
|
||||||
|
@Inject Clock clock;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject DomainCheckFlow() {}
|
@Inject DomainCheckFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EppOutput run() throws EppException {
|
public EppResponse run() throws EppException {
|
||||||
extensionManager.register(LaunchCheckExtension.class);
|
extensionManager.register(LaunchCheckExtension.class);
|
||||||
extensionManager.registerAsGroup(FEE_CHECK_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
|
extensionManager.registerAsGroup(FEE_CHECK_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
|
||||||
extensionManager.validate();
|
extensionManager.validate();
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
List<String> targetIds = ((Check) resourceCommand).getTargetIds();
|
List<String> targetIds = ((Check) resourceCommand).getTargetIds();
|
||||||
verifyTargetIdCount(targetIds, maxChecks);
|
verifyTargetIdCount(targetIds, maxChecks);
|
||||||
|
DateTime now = clock.nowUtc();
|
||||||
ImmutableMap.Builder<String, InternetDomainName> domains = new ImmutableMap.Builder<>();
|
ImmutableMap.Builder<String, InternetDomainName> domains = new ImmutableMap.Builder<>();
|
||||||
// Only check that the registrar has access to a TLD the first time it is encountered
|
// Only check that the registrar has access to a TLD the first time it is encountered
|
||||||
Set<String> seenTlds = new HashSet<>();
|
Set<String> seenTlds = new HashSet<>();
|
||||||
|
@ -133,17 +138,17 @@ public final class DomainCheckFlow extends Flow {
|
||||||
Set<String> existingIds = checkResourcesExist(DomainResource.class, targetIds, now);
|
Set<String> existingIds = checkResourcesExist(DomainResource.class, targetIds, now);
|
||||||
ImmutableList.Builder<DomainCheck> checks = new ImmutableList.Builder<>();
|
ImmutableList.Builder<DomainCheck> checks = new ImmutableList.Builder<>();
|
||||||
for (String targetId : targetIds) {
|
for (String targetId : targetIds) {
|
||||||
String message = getMessageForCheck(domainNames.get(targetId), existingIds);
|
String message = getMessageForCheck(domainNames.get(targetId), existingIds, now);
|
||||||
checks.add(DomainCheck.create(message == null, targetId, message));
|
checks.add(DomainCheck.create(message == null, targetId, message));
|
||||||
}
|
}
|
||||||
return createOutput(
|
return responseBuilder
|
||||||
SUCCESS,
|
.setResData(DomainCheckData.create(checks.build()))
|
||||||
DomainCheckData.create(checks.build()),
|
.setExtensions(getResponseExtensions(domainNames, now))
|
||||||
getResponseExtensions(domainNames));
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getMessageForCheck(
|
private String getMessageForCheck(
|
||||||
InternetDomainName domainName, Set<String> existingIds) {
|
InternetDomainName domainName, Set<String> existingIds, DateTime now) {
|
||||||
if (existingIds.contains(domainName.toString())) {
|
if (existingIds.contains(domainName.toString())) {
|
||||||
return "In use";
|
return "In use";
|
||||||
}
|
}
|
||||||
|
@ -161,9 +166,7 @@ public final class DomainCheckFlow extends Flow {
|
||||||
if (reservationType == UNRESERVED
|
if (reservationType == UNRESERVED
|
||||||
&& isDomainPremium(domainName.toString(), now)
|
&& isDomainPremium(domainName.toString(), now)
|
||||||
&& registry.getPremiumPriceAckRequired()
|
&& registry.getPremiumPriceAckRequired()
|
||||||
&& Collections.disjoint(
|
&& eppInput.getSingleExtension(FeeCheckCommandExtension.class) == null) {
|
||||||
nullToEmpty(sessionMetadata.getServiceExtensionUris()),
|
|
||||||
FEE_EXTENSION_URIS)) {
|
|
||||||
return "Premium names require EPP ext.";
|
return "Premium names require EPP ext.";
|
||||||
}
|
}
|
||||||
return reservationType.getMessageForCheck();
|
return reservationType.getMessageForCheck();
|
||||||
|
@ -172,7 +175,7 @@ public final class DomainCheckFlow extends Flow {
|
||||||
|
|
||||||
/** Handle the fee check extension. */
|
/** Handle the fee check extension. */
|
||||||
private ImmutableList<? extends ResponseExtension> getResponseExtensions(
|
private ImmutableList<? extends ResponseExtension> getResponseExtensions(
|
||||||
ImmutableMap<String, InternetDomainName> domainNames) throws EppException {
|
ImmutableMap<String, InternetDomainName> domainNames, DateTime now) throws EppException {
|
||||||
FeeCheckCommandExtension<?, ?> feeCheck =
|
FeeCheckCommandExtension<?, ?> feeCheck =
|
||||||
eppInput.getFirstExtensionOfClasses(FEE_CHECK_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
|
eppInput.getFirstExtensionOfClasses(FEE_CHECK_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
|
||||||
if (feeCheck == null) {
|
if (feeCheck == null) {
|
||||||
|
|
|
@ -54,8 +54,8 @@ import google.registry.flows.EppException;
|
||||||
import google.registry.flows.EppException.CommandUseErrorException;
|
import google.registry.flows.EppException.CommandUseErrorException;
|
||||||
import google.registry.flows.EppException.StatusProhibitsOperationException;
|
import google.registry.flows.EppException.StatusProhibitsOperationException;
|
||||||
import google.registry.flows.ExtensionManager;
|
import google.registry.flows.ExtensionManager;
|
||||||
import google.registry.flows.Flow;
|
|
||||||
import google.registry.flows.FlowModule.ClientId;
|
import google.registry.flows.FlowModule.ClientId;
|
||||||
|
import google.registry.flows.FlowModule.Superuser;
|
||||||
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.domain.TldSpecificLogicProxy.EppCommandOperations;
|
import google.registry.flows.domain.TldSpecificLogicProxy.EppCommandOperations;
|
||||||
|
@ -78,10 +78,10 @@ import google.registry.model.domain.metadata.MetadataExtension;
|
||||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||||
import google.registry.model.domain.secdns.SecDnsCreateExtension;
|
import google.registry.model.domain.secdns.SecDnsCreateExtension;
|
||||||
import google.registry.model.eppcommon.AuthInfo;
|
import google.registry.model.eppcommon.AuthInfo;
|
||||||
|
import google.registry.model.eppinput.EppInput;
|
||||||
import google.registry.model.eppinput.ResourceCommand;
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
import google.registry.model.eppoutput.CreateData.DomainCreateData;
|
import google.registry.model.eppoutput.CreateData.DomainCreateData;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.eppoutput.Result;
|
|
||||||
import google.registry.model.index.EppResourceIndex;
|
import google.registry.model.index.EppResourceIndex;
|
||||||
import google.registry.model.index.ForeignKeyIndex;
|
import google.registry.model.index.ForeignKeyIndex;
|
||||||
import google.registry.model.ofy.ObjectifyService;
|
import google.registry.model.ofy.ObjectifyService;
|
||||||
|
@ -149,21 +149,24 @@ import org.joda.time.DateTime;
|
||||||
* @error {@link DomainCreateFlow.NoGeneralRegistrationsInCurrentPhaseException}
|
* @error {@link DomainCreateFlow.NoGeneralRegistrationsInCurrentPhaseException}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class DomainCreateFlow extends Flow implements TransactionalFlow {
|
public class DomainCreateFlow implements TransactionalFlow {
|
||||||
|
|
||||||
private static final Set<TldState> QLP_SMD_ALLOWED_STATES =
|
private static final Set<TldState> QLP_SMD_ALLOWED_STATES =
|
||||||
Sets.immutableEnumSet(TldState.SUNRISE, TldState.SUNRUSH);
|
Sets.immutableEnumSet(TldState.SUNRISE, TldState.SUNRUSH);
|
||||||
|
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
|
@Inject EppInput eppInput;
|
||||||
@Inject AuthInfo authInfo;
|
@Inject AuthInfo authInfo;
|
||||||
@Inject ResourceCommand resourceCommand;
|
@Inject ResourceCommand resourceCommand;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject @TargetId String targetId;
|
@Inject @TargetId String targetId;
|
||||||
|
@Inject @Superuser boolean isSuperuser;
|
||||||
@Inject HistoryEntry.Builder historyBuilder;
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject DomainCreateFlow() {}
|
@Inject DomainCreateFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.register(
|
extensionManager.register(
|
||||||
SecDnsCreateExtension.class,
|
SecDnsCreateExtension.class,
|
||||||
FlagsCreateCommandExtension.class,
|
FlagsCreateCommandExtension.class,
|
||||||
|
@ -172,6 +175,7 @@ public class DomainCreateFlow extends Flow implements TransactionalFlow {
|
||||||
extensionManager.registerAsGroup(FEE_CREATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
|
extensionManager.registerAsGroup(FEE_CREATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
|
||||||
extensionManager.validate();
|
extensionManager.validate();
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
|
DateTime now = ofy().getTransactionTime();
|
||||||
Create command = cloneAndLinkReferences((Create) resourceCommand, now);
|
Create command = cloneAndLinkReferences((Create) resourceCommand, now);
|
||||||
Period period = command.getPeriod();
|
Period period = command.getPeriod();
|
||||||
verifyUnitIsYears(period);
|
verifyUnitIsYears(period);
|
||||||
|
@ -219,17 +223,17 @@ public class DomainCreateFlow extends Flow implements TransactionalFlow {
|
||||||
verifyClaimsNoticeIfAndOnlyIfNeeded(domainName, hasSignedMarks, hasClaimsNotice);
|
verifyClaimsNoticeIfAndOnlyIfNeeded(domainName, hasSignedMarks, hasClaimsNotice);
|
||||||
}
|
}
|
||||||
verifyPremiumNameIsNotBlocked(targetId, now, clientId);
|
verifyPremiumNameIsNotBlocked(targetId, now, clientId);
|
||||||
verifyNoOpenApplications();
|
verifyNoOpenApplications(now);
|
||||||
verifyIsGaOrIsSpecialCase(tldState, isAnchorTenant);
|
verifyIsGaOrIsSpecialCase(tldState, isAnchorTenant);
|
||||||
}
|
}
|
||||||
SecDnsCreateExtension secDnsCreate =
|
SecDnsCreateExtension secDnsCreate =
|
||||||
validateSecDnsExtension(eppInput.getSingleExtension(SecDnsCreateExtension.class));
|
validateSecDnsExtension(eppInput.getSingleExtension(SecDnsCreateExtension.class));
|
||||||
String repoId = createDomainRoid(ObjectifyService.allocateId(), registry.getTldStr());
|
String repoId = createDomainRoid(ObjectifyService.allocateId(), registry.getTldStr());
|
||||||
DateTime registrationExpirationTime = leapSafeAddYears(now, years);
|
DateTime registrationExpirationTime = leapSafeAddYears(now, years);
|
||||||
HistoryEntry historyEntry = buildHistory(repoId, period);
|
HistoryEntry historyEntry = buildHistory(repoId, period, now);
|
||||||
// Bill for the create.
|
// Bill for the create.
|
||||||
BillingEvent.OneTime createBillingEvent =
|
BillingEvent.OneTime createBillingEvent = createOneTimeBillingEvent(
|
||||||
createOneTimeBillingEvent(registry, isAnchorTenant, years, commandOperations, historyEntry);
|
registry, isAnchorTenant, years, commandOperations, historyEntry, now);
|
||||||
// Create a new autorenew billing event and poll message starting at the expiration time.
|
// Create a new autorenew billing event and poll message starting at the expiration time.
|
||||||
BillingEvent.Recurring autorenewBillingEvent =
|
BillingEvent.Recurring autorenewBillingEvent =
|
||||||
createAutorenewBillingEvent(historyEntry, registrationExpirationTime);
|
createAutorenewBillingEvent(historyEntry, registrationExpirationTime);
|
||||||
|
@ -266,7 +270,7 @@ public class DomainCreateFlow extends Flow implements TransactionalFlow {
|
||||||
.setContacts(command.getContacts())
|
.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, now);
|
||||||
entitiesToSave.add(
|
entitiesToSave.add(
|
||||||
newDomain,
|
newDomain,
|
||||||
ForeignKeyIndex.create(newDomain, newDomain.getDeletionTime()),
|
ForeignKeyIndex.create(newDomain, newDomain.getDeletionTime()),
|
||||||
|
@ -274,16 +278,16 @@ public class DomainCreateFlow extends Flow implements TransactionalFlow {
|
||||||
|
|
||||||
// Anchor tenant registrations override LRP, and landrush applications can skip it.
|
// Anchor tenant registrations override LRP, and landrush applications can skip it.
|
||||||
// If a token is passed in outside of an LRP phase, it is simply ignored (i.e. never redeemed).
|
// If a token is passed in outside of an LRP phase, it is simply ignored (i.e. never redeemed).
|
||||||
if (isLrpCreate(registry, isAnchorTenant)) {
|
if (isLrpCreate(registry, isAnchorTenant, now)) {
|
||||||
entitiesToSave.add(
|
entitiesToSave.add(
|
||||||
prepareMarkedLrpTokenEntity(authInfo.getPw().getValue(), domainName, historyEntry));
|
prepareMarkedLrpTokenEntity(authInfo.getPw().getValue(), domainName, historyEntry));
|
||||||
}
|
}
|
||||||
enqueueTasks(hasSignedMarks, hasClaimsNotice, newDomain);
|
enqueueTasks(hasSignedMarks, hasClaimsNotice, newDomain);
|
||||||
ofy().save().entities(entitiesToSave.build());
|
ofy().save().entities(entitiesToSave.build());
|
||||||
return createOutput(
|
return responseBuilder
|
||||||
Result.Code.SUCCESS,
|
.setResData(DomainCreateData.create(targetId, now, registrationExpirationTime))
|
||||||
DomainCreateData.create(targetId, now, registrationExpirationTime),
|
.setExtensions(createResponseExtensions(feeCreate, commandOperations))
|
||||||
createResponseExtensions(feeCreate, commandOperations));
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isAnchorTenant(InternetDomainName domainName) {
|
private boolean isAnchorTenant(InternetDomainName domainName) {
|
||||||
|
@ -301,7 +305,7 @@ public class DomainCreateFlow extends Flow implements TransactionalFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Prohibit creating a domain if there is an open application for the same name. */
|
/** Prohibit creating a domain if there is an open application for the same name. */
|
||||||
private void verifyNoOpenApplications() throws DomainHasOpenApplicationsException {
|
private void verifyNoOpenApplications(DateTime now) throws DomainHasOpenApplicationsException {
|
||||||
for (DomainApplication application : loadActiveApplicationsByDomainName(targetId, now)) {
|
for (DomainApplication application : loadActiveApplicationsByDomainName(targetId, now)) {
|
||||||
if (!application.getApplicationStatus().isFinalStatus()) {
|
if (!application.getApplicationStatus().isFinalStatus()) {
|
||||||
throw new DomainHasOpenApplicationsException();
|
throw new DomainHasOpenApplicationsException();
|
||||||
|
@ -317,7 +321,7 @@ public class DomainCreateFlow extends Flow implements TransactionalFlow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private HistoryEntry buildHistory(String repoId, Period period) {
|
private HistoryEntry buildHistory(String repoId, Period period, DateTime now) {
|
||||||
return historyBuilder
|
return historyBuilder
|
||||||
.setType(HistoryEntry.Type.DOMAIN_CREATE)
|
.setType(HistoryEntry.Type.DOMAIN_CREATE)
|
||||||
.setPeriod(period)
|
.setPeriod(period)
|
||||||
|
@ -331,7 +335,8 @@ public class DomainCreateFlow extends Flow implements TransactionalFlow {
|
||||||
boolean isAnchorTenant,
|
boolean isAnchorTenant,
|
||||||
int years,
|
int years,
|
||||||
EppCommandOperations commandOperations,
|
EppCommandOperations commandOperations,
|
||||||
HistoryEntry historyEntry) {
|
HistoryEntry historyEntry,
|
||||||
|
DateTime now) {
|
||||||
return new BillingEvent.OneTime.Builder()
|
return new BillingEvent.OneTime.Builder()
|
||||||
.setReason(Reason.CREATE)
|
.setReason(Reason.CREATE)
|
||||||
.setTargetId(targetId)
|
.setTargetId(targetId)
|
||||||
|
@ -387,12 +392,12 @@ public class DomainCreateFlow extends Flow implements TransactionalFlow {
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isLrpCreate(Registry registry, boolean isAnchorTenant) {
|
private boolean isLrpCreate(Registry registry, boolean isAnchorTenant, DateTime now) {
|
||||||
return registry.getLrpPeriod().contains(now) && !isAnchorTenant;
|
return registry.getLrpPeriod().contains(now) && !isAnchorTenant;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleExtraFlowLogic(
|
private void handleExtraFlowLogic(
|
||||||
String tld, int years, HistoryEntry historyEntry, DomainResource newDomain)
|
String tld, int years, HistoryEntry historyEntry, DomainResource newDomain, DateTime now)
|
||||||
throws EppException {
|
throws EppException {
|
||||||
Optional<RegistryExtraFlowLogic> extraFlowLogic =
|
Optional<RegistryExtraFlowLogic> extraFlowLogic =
|
||||||
RegistryExtraFlowLogicProxy.newInstanceForTld(tld);
|
RegistryExtraFlowLogicProxy.newInstanceForTld(tld);
|
||||||
|
|
|
@ -40,9 +40,10 @@ import google.registry.dns.DnsQueue;
|
||||||
import google.registry.flows.EppException;
|
import google.registry.flows.EppException;
|
||||||
import google.registry.flows.EppException.AssociationProhibitsOperationException;
|
import google.registry.flows.EppException.AssociationProhibitsOperationException;
|
||||||
import google.registry.flows.ExtensionManager;
|
import google.registry.flows.ExtensionManager;
|
||||||
import google.registry.flows.Flow;
|
|
||||||
import google.registry.flows.FlowModule.ClientId;
|
import google.registry.flows.FlowModule.ClientId;
|
||||||
|
import google.registry.flows.FlowModule.Superuser;
|
||||||
import google.registry.flows.FlowModule.TargetId;
|
import google.registry.flows.FlowModule.TargetId;
|
||||||
|
import google.registry.flows.SessionMetadata;
|
||||||
import google.registry.flows.TransactionalFlow;
|
import google.registry.flows.TransactionalFlow;
|
||||||
import google.registry.model.ImmutableObject;
|
import google.registry.model.ImmutableObject;
|
||||||
import google.registry.model.billing.BillingEvent;
|
import google.registry.model.billing.BillingEvent;
|
||||||
|
@ -61,7 +62,9 @@ import google.registry.model.domain.secdns.SecDnsCreateExtension;
|
||||||
import google.registry.model.eppcommon.AuthInfo;
|
import google.registry.model.eppcommon.AuthInfo;
|
||||||
import google.registry.model.eppcommon.ProtocolDefinition.ServiceExtension;
|
import google.registry.model.eppcommon.ProtocolDefinition.ServiceExtension;
|
||||||
import google.registry.model.eppcommon.StatusValue;
|
import google.registry.model.eppcommon.StatusValue;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppcommon.Trid;
|
||||||
|
import google.registry.model.eppinput.EppInput;
|
||||||
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.poll.PendingActionNotificationResponse.DomainPendingActionNotificationResponse;
|
import google.registry.model.poll.PendingActionNotificationResponse.DomainPendingActionNotificationResponse;
|
||||||
import google.registry.model.poll.PollMessage;
|
import google.registry.model.poll.PollMessage;
|
||||||
import google.registry.model.poll.PollMessage.OneTime;
|
import google.registry.model.poll.PollMessage.OneTime;
|
||||||
|
@ -84,7 +87,7 @@ import org.joda.time.DateTime;
|
||||||
* @error {@link DomainFlowUtils.BadCommandForRegistryPhaseException}
|
* @error {@link DomainFlowUtils.BadCommandForRegistryPhaseException}
|
||||||
* @error {@link DomainFlowUtils.NotAuthorizedForTldException}
|
* @error {@link DomainFlowUtils.NotAuthorizedForTldException}
|
||||||
*/
|
*/
|
||||||
public final class DomainDeleteFlow extends Flow implements TransactionalFlow {
|
public final class DomainDeleteFlow implements TransactionalFlow {
|
||||||
|
|
||||||
private static final ImmutableSet<StatusValue> DISALLOWED_STATUSES = ImmutableSet.of(
|
private static final ImmutableSet<StatusValue> DISALLOWED_STATUSES = ImmutableSet.of(
|
||||||
StatusValue.LINKED,
|
StatusValue.LINKED,
|
||||||
|
@ -93,23 +96,29 @@ public final class DomainDeleteFlow extends Flow implements TransactionalFlow {
|
||||||
StatusValue.SERVER_DELETE_PROHIBITED);
|
StatusValue.SERVER_DELETE_PROHIBITED);
|
||||||
|
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
|
@Inject EppInput eppInput;
|
||||||
|
@Inject SessionMetadata sessionMetadata;
|
||||||
@Inject Optional<AuthInfo> authInfo;
|
@Inject Optional<AuthInfo> authInfo;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject @TargetId String targetId;
|
@Inject @TargetId String targetId;
|
||||||
|
@Inject @Superuser boolean isSuperuser;
|
||||||
@Inject HistoryEntry.Builder historyBuilder;
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
@Inject DnsQueue dnsQueue;
|
@Inject DnsQueue dnsQueue;
|
||||||
|
@Inject Trid trid;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject DomainDeleteFlow() {}
|
@Inject DomainDeleteFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.register(MetadataExtension.class, SecDnsCreateExtension.class);
|
extensionManager.register(MetadataExtension.class, SecDnsCreateExtension.class);
|
||||||
extensionManager.validate();
|
extensionManager.validate();
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
|
DateTime now = ofy().getTransactionTime();
|
||||||
// Loads the target resource if it exists
|
// Loads the target resource if it exists
|
||||||
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
|
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
|
||||||
Registry registry = Registry.get(existingDomain.getTld());
|
Registry registry = Registry.get(existingDomain.getTld());
|
||||||
verifyDeleteAllowed(existingDomain, registry);
|
verifyDeleteAllowed(existingDomain, registry, now);
|
||||||
HistoryEntry historyEntry = buildHistoryEntry(existingDomain);
|
HistoryEntry historyEntry = buildHistoryEntry(existingDomain, now);
|
||||||
Builder builder = (Builder) prepareDeletedResourceAsBuilder(existingDomain, now);
|
Builder builder = (Builder) prepareDeletedResourceAsBuilder(existingDomain, now);
|
||||||
// If the domain is in the Add Grace Period, we delete it immediately, which is already
|
// If the domain is in the Add Grace Period, we delete it immediately, which is already
|
||||||
// reflected in the builder we just prepared. Otherwise we give it a PENDING_DELETE status.
|
// reflected in the builder we just prepared. Otherwise we give it a PENDING_DELETE status.
|
||||||
|
@ -131,7 +140,7 @@ public final class DomainDeleteFlow extends Flow implements TransactionalFlow {
|
||||||
clientId)))
|
clientId)))
|
||||||
.setDeletePollMessage(Key.create(deletePollMessage));
|
.setDeletePollMessage(Key.create(deletePollMessage));
|
||||||
}
|
}
|
||||||
handleExtraFlowLogic(existingDomain, historyEntry);
|
handleExtraFlowLogic(existingDomain, historyEntry, now);
|
||||||
DomainResource newDomain = builder.build();
|
DomainResource newDomain = builder.build();
|
||||||
updateForeignKeyIndexDeletionTime(newDomain);
|
updateForeignKeyIndexDeletionTime(newDomain);
|
||||||
handlePendingTransferOnDelete(existingDomain, newDomain, now, historyEntry);
|
handlePendingTransferOnDelete(existingDomain, newDomain, now, historyEntry);
|
||||||
|
@ -150,13 +159,14 @@ public final class DomainDeleteFlow extends Flow implements TransactionalFlow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ofy().save().<ImmutableObject>entities(newDomain, historyEntry);
|
ofy().save().<ImmutableObject>entities(newDomain, historyEntry);
|
||||||
return createOutput(
|
return responseBuilder
|
||||||
newDomain.getDeletionTime().isAfter(now) ? SUCCESS_WITH_ACTION_PENDING : SUCCESS,
|
.setResultFromCode(
|
||||||
null,
|
newDomain.getDeletionTime().isAfter(now) ? SUCCESS_WITH_ACTION_PENDING : SUCCESS)
|
||||||
getResponseExtensions(existingDomain));
|
.setExtensions(getResponseExtensions(existingDomain, now))
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void verifyDeleteAllowed(DomainResource existingDomain, Registry registry)
|
private void verifyDeleteAllowed(DomainResource existingDomain, Registry registry, DateTime now)
|
||||||
throws EppException {
|
throws EppException {
|
||||||
verifyNoDisallowedStatuses(existingDomain, DISALLOWED_STATUSES);
|
verifyNoDisallowedStatuses(existingDomain, DISALLOWED_STATUSES);
|
||||||
verifyOptionalAuthInfoForResource(authInfo, existingDomain);
|
verifyOptionalAuthInfoForResource(authInfo, existingDomain);
|
||||||
|
@ -170,7 +180,7 @@ public final class DomainDeleteFlow extends Flow implements TransactionalFlow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private HistoryEntry buildHistoryEntry(DomainResource existingResource) {
|
private HistoryEntry buildHistoryEntry(DomainResource existingResource, DateTime now) {
|
||||||
return historyBuilder
|
return historyBuilder
|
||||||
.setType(HistoryEntry.Type.DOMAIN_DELETE)
|
.setType(HistoryEntry.Type.DOMAIN_DELETE)
|
||||||
.setModificationTime(now)
|
.setModificationTime(now)
|
||||||
|
@ -191,8 +201,9 @@ public final class DomainDeleteFlow extends Flow implements TransactionalFlow {
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleExtraFlowLogic(DomainResource existingResource, HistoryEntry historyEntry)
|
private void handleExtraFlowLogic(
|
||||||
throws EppException {
|
DomainResource existingResource, HistoryEntry historyEntry, DateTime now)
|
||||||
|
throws EppException {
|
||||||
Optional<RegistryExtraFlowLogic> extraFlowLogic =
|
Optional<RegistryExtraFlowLogic> extraFlowLogic =
|
||||||
RegistryExtraFlowLogicProxy.newInstanceForDomain(existingResource);
|
RegistryExtraFlowLogicProxy.newInstanceForDomain(existingResource);
|
||||||
if (extraFlowLogic.isPresent()) {
|
if (extraFlowLogic.isPresent()) {
|
||||||
|
@ -203,7 +214,7 @@ public final class DomainDeleteFlow extends Flow implements TransactionalFlow {
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private ImmutableList<FeeTransformResponseExtension> getResponseExtensions(
|
private ImmutableList<FeeTransformResponseExtension> getResponseExtensions(
|
||||||
DomainResource existingDomain) {
|
DomainResource existingDomain, DateTime now) {
|
||||||
FeeTransformResponseExtension.Builder feeResponseBuilder = getDeleteResponseBuilder();
|
FeeTransformResponseExtension.Builder feeResponseBuilder = getDeleteResponseBuilder();
|
||||||
if (feeResponseBuilder == null) {
|
if (feeResponseBuilder == null) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -211,7 +222,7 @@ public final class DomainDeleteFlow extends Flow implements TransactionalFlow {
|
||||||
ImmutableList.Builder<Credit> creditsBuilder = new ImmutableList.Builder<>();
|
ImmutableList.Builder<Credit> creditsBuilder = new ImmutableList.Builder<>();
|
||||||
for (GracePeriod gracePeriod : existingDomain.getGracePeriods()) {
|
for (GracePeriod gracePeriod : existingDomain.getGracePeriods()) {
|
||||||
if (gracePeriod.hasBillingEvent()) {
|
if (gracePeriod.hasBillingEvent()) {
|
||||||
Money cost = getGracePeriodCost(gracePeriod);
|
Money cost = getGracePeriodCost(gracePeriod, now);
|
||||||
creditsBuilder.add(Credit.create(
|
creditsBuilder.add(Credit.create(
|
||||||
cost.negated().getAmount(), FeeType.CREDIT, gracePeriod.getType().getXmlName()));
|
cost.negated().getAmount(), FeeType.CREDIT, gracePeriod.getType().getXmlName()));
|
||||||
feeResponseBuilder.setCurrency(checkNotNull(cost.getCurrencyUnit()));
|
feeResponseBuilder.setCurrency(checkNotNull(cost.getCurrencyUnit()));
|
||||||
|
@ -224,7 +235,7 @@ public final class DomainDeleteFlow extends Flow implements TransactionalFlow {
|
||||||
return ImmutableList.of(feeResponseBuilder.setCredits(credits).build());
|
return ImmutableList.of(feeResponseBuilder.setCredits(credits).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Money getGracePeriodCost(GracePeriod gracePeriod) {
|
private Money getGracePeriodCost(GracePeriod gracePeriod, DateTime now) {
|
||||||
if (gracePeriod.getType() == GracePeriodStatus.AUTO_RENEW) {
|
if (gracePeriod.getType() == GracePeriodStatus.AUTO_RENEW) {
|
||||||
DateTime autoRenewTime =
|
DateTime autoRenewTime =
|
||||||
ofy().load().key(checkNotNull(gracePeriod.getRecurringBillingEvent())).now()
|
ofy().load().key(checkNotNull(gracePeriod.getRecurringBillingEvent())).now()
|
||||||
|
|
|
@ -19,7 +19,6 @@ import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
|
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.addSecDnsExtensionIfPresent;
|
import static google.registry.flows.domain.DomainFlowUtils.addSecDnsExtensionIfPresent;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.handleFeeRequest;
|
import static google.registry.flows.domain.DomainFlowUtils.handleFeeRequest;
|
||||||
import static google.registry.model.eppoutput.Result.Code.SUCCESS;
|
|
||||||
import static google.registry.util.CollectionUtils.forceEmptyToNull;
|
import static google.registry.util.CollectionUtils.forceEmptyToNull;
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
|
@ -41,11 +40,14 @@ import google.registry.model.domain.flags.FlagsInfoResponseExtension;
|
||||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||||
import google.registry.model.domain.rgp.RgpInfoExtension;
|
import google.registry.model.domain.rgp.RgpInfoExtension;
|
||||||
import google.registry.model.eppcommon.AuthInfo;
|
import google.registry.model.eppcommon.AuthInfo;
|
||||||
|
import google.registry.model.eppinput.EppInput;
|
||||||
import google.registry.model.eppinput.ResourceCommand;
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
|
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
|
||||||
|
import google.registry.util.Clock;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An EPP flow that returns information about a domain.
|
* An EPP flow that returns information about a domain.
|
||||||
|
@ -61,26 +63,30 @@ import javax.inject.Inject;
|
||||||
* @error {@link DomainFlowUtils.FeeChecksDontSupportPhasesException}
|
* @error {@link DomainFlowUtils.FeeChecksDontSupportPhasesException}
|
||||||
* @error {@link DomainFlowUtils.RestoresAreAlwaysForOneYearException}
|
* @error {@link DomainFlowUtils.RestoresAreAlwaysForOneYearException}
|
||||||
*/
|
*/
|
||||||
public final class DomainInfoFlow extends Flow {
|
public final class DomainInfoFlow implements Flow {
|
||||||
|
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
|
@Inject ResourceCommand resourceCommand;
|
||||||
|
@Inject EppInput eppInput;
|
||||||
@Inject Optional<AuthInfo> authInfo;
|
@Inject Optional<AuthInfo> authInfo;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject @TargetId String targetId;
|
@Inject @TargetId String targetId;
|
||||||
@Inject ResourceCommand resourceCommand;
|
@Inject Clock clock;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject DomainInfoFlow() {}
|
@Inject DomainInfoFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.register(FeeInfoCommandExtensionV06.class);
|
extensionManager.register(FeeInfoCommandExtensionV06.class);
|
||||||
extensionManager.validate();
|
extensionManager.validate();
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
|
DateTime now = clock.nowUtc();
|
||||||
DomainResource domain = loadAndVerifyExistence(DomainResource.class, targetId, now);
|
DomainResource domain = loadAndVerifyExistence(DomainResource.class, targetId, now);
|
||||||
verifyOptionalAuthInfoForResource(authInfo, domain);
|
verifyOptionalAuthInfoForResource(authInfo, domain);
|
||||||
return createOutput(
|
return responseBuilder
|
||||||
SUCCESS,
|
.setResData(getResourceInfo(domain))
|
||||||
getResourceInfo(domain),
|
.setExtensions(getDomainResponseExtensions(domain, now))
|
||||||
getDomainResponseExtensions(domain));
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private DomainResource getResourceInfo(DomainResource domain) {
|
private DomainResource getResourceInfo(DomainResource domain) {
|
||||||
|
@ -111,8 +117,8 @@ public final class DomainInfoFlow extends Flow {
|
||||||
return info.build();
|
return info.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ImmutableList<ResponseExtension> getDomainResponseExtensions(DomainResource domain)
|
private ImmutableList<ResponseExtension> getDomainResponseExtensions(
|
||||||
throws EppException {
|
DomainResource domain, DateTime now) throws EppException {
|
||||||
ImmutableList.Builder<ResponseExtension> extensions = new ImmutableList.Builder<>();
|
ImmutableList.Builder<ResponseExtension> extensions = new ImmutableList.Builder<>();
|
||||||
addSecDnsExtensionIfPresent(extensions, domain.getDsData());
|
addSecDnsExtensionIfPresent(extensions, domain.getDsData());
|
||||||
ImmutableSet<GracePeriodStatus> gracePeriodStatuses = domain.getGracePeriodStatuses();
|
ImmutableSet<GracePeriodStatus> gracePeriodStatuses = domain.getGracePeriodStatuses();
|
||||||
|
|
|
@ -28,7 +28,6 @@ import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears;
|
||||||
import static google.registry.model.domain.DomainResource.MAX_REGISTRATION_YEARS;
|
import static google.registry.model.domain.DomainResource.MAX_REGISTRATION_YEARS;
|
||||||
import static google.registry.model.domain.DomainResource.extendRegistrationWithCap;
|
import static google.registry.model.domain.DomainResource.extendRegistrationWithCap;
|
||||||
import static google.registry.model.domain.fee.Fee.FEE_RENEW_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER;
|
import static google.registry.model.domain.fee.Fee.FEE_RENEW_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER;
|
||||||
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;
|
||||||
import static google.registry.util.DateTimeUtils.leapSafeAddYears;
|
import static google.registry.util.DateTimeUtils.leapSafeAddYears;
|
||||||
|
|
||||||
|
@ -40,8 +39,8 @@ import google.registry.flows.EppException;
|
||||||
import google.registry.flows.EppException.ObjectPendingTransferException;
|
import google.registry.flows.EppException.ObjectPendingTransferException;
|
||||||
import google.registry.flows.EppException.ParameterValueRangeErrorException;
|
import google.registry.flows.EppException.ParameterValueRangeErrorException;
|
||||||
import google.registry.flows.ExtensionManager;
|
import google.registry.flows.ExtensionManager;
|
||||||
import google.registry.flows.Flow;
|
|
||||||
import google.registry.flows.FlowModule.ClientId;
|
import google.registry.flows.FlowModule.ClientId;
|
||||||
|
import google.registry.flows.FlowModule.Superuser;
|
||||||
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.domain.TldSpecificLogicProxy.EppCommandOperations;
|
import google.registry.flows.domain.TldSpecificLogicProxy.EppCommandOperations;
|
||||||
|
@ -60,8 +59,9 @@ import google.registry.model.domain.metadata.MetadataExtension;
|
||||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||||
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.EppInput;
|
||||||
import google.registry.model.eppinput.ResourceCommand;
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.poll.PollMessage;
|
import google.registry.model.poll.PollMessage;
|
||||||
import google.registry.model.registry.Registry;
|
import google.registry.model.registry.Registry;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
|
@ -97,7 +97,7 @@ import org.joda.time.DateTime;
|
||||||
* @error {@link DomainRenewFlow.ExceedsMaxRegistrationYearsException}
|
* @error {@link DomainRenewFlow.ExceedsMaxRegistrationYearsException}
|
||||||
* @error {@link DomainRenewFlow.IncorrectCurrentExpirationDateException}
|
* @error {@link DomainRenewFlow.IncorrectCurrentExpirationDateException}
|
||||||
*/
|
*/
|
||||||
public final class DomainRenewFlow extends Flow implements TransactionalFlow {
|
public final class DomainRenewFlow implements TransactionalFlow {
|
||||||
|
|
||||||
private static final ImmutableSet<StatusValue> RENEW_DISALLOWED_STATUSES = ImmutableSet.of(
|
private static final ImmutableSet<StatusValue> RENEW_DISALLOWED_STATUSES = ImmutableSet.of(
|
||||||
StatusValue.CLIENT_RENEW_PROHIBITED,
|
StatusValue.CLIENT_RENEW_PROHIBITED,
|
||||||
|
@ -106,18 +106,22 @@ public final class DomainRenewFlow extends Flow implements TransactionalFlow {
|
||||||
|
|
||||||
@Inject ResourceCommand resourceCommand;
|
@Inject ResourceCommand resourceCommand;
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
|
@Inject EppInput eppInput;
|
||||||
@Inject Optional<AuthInfo> authInfo;
|
@Inject Optional<AuthInfo> authInfo;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject @TargetId String targetId;
|
@Inject @TargetId String targetId;
|
||||||
|
@Inject @Superuser boolean isSuperuser;
|
||||||
@Inject HistoryEntry.Builder historyBuilder;
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject DomainRenewFlow() {}
|
@Inject DomainRenewFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.register(MetadataExtension.class);
|
extensionManager.register(MetadataExtension.class);
|
||||||
extensionManager.registerAsGroup(FEE_RENEW_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
|
extensionManager.registerAsGroup(FEE_RENEW_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
|
||||||
extensionManager.validate();
|
extensionManager.validate();
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
|
DateTime now = ofy().getTransactionTime();
|
||||||
Renew command = (Renew) resourceCommand;
|
Renew command = (Renew) resourceCommand;
|
||||||
// Loads the target resource if it exists
|
// Loads the target resource if it exists
|
||||||
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
|
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
|
||||||
|
@ -143,7 +147,7 @@ public final class DomainRenewFlow extends Flow implements TransactionalFlow {
|
||||||
String tld = existingDomain.getTld();
|
String tld = existingDomain.getTld();
|
||||||
// Bill for this explicit renew itself.
|
// Bill for this explicit renew itself.
|
||||||
BillingEvent.OneTime explicitRenewEvent =
|
BillingEvent.OneTime explicitRenewEvent =
|
||||||
createRenewBillingEvent(tld, commandOperations.getTotalCost(), years, historyEntry);
|
createRenewBillingEvent(tld, commandOperations.getTotalCost(), years, historyEntry, now);
|
||||||
// Create a new autorenew billing event and poll message starting at the new expiration time.
|
// Create a new autorenew billing event and poll message starting at the new expiration time.
|
||||||
BillingEvent.Recurring newAutorenewEvent = newAutorenewBillingEvent(existingDomain)
|
BillingEvent.Recurring newAutorenewEvent = newAutorenewBillingEvent(existingDomain)
|
||||||
.setEventTime(newExpirationTime)
|
.setEventTime(newExpirationTime)
|
||||||
|
@ -170,10 +174,10 @@ public final class DomainRenewFlow extends Flow implements TransactionalFlow {
|
||||||
.build();
|
.build();
|
||||||
ofy().save().<Object>entities(
|
ofy().save().<Object>entities(
|
||||||
newDomain, historyEntry, explicitRenewEvent, newAutorenewEvent, newAutorenewPollMessage);
|
newDomain, historyEntry, explicitRenewEvent, newAutorenewEvent, newAutorenewPollMessage);
|
||||||
return createOutput(
|
return responseBuilder
|
||||||
SUCCESS,
|
.setResData(DomainRenewData.create(targetId, newExpirationTime))
|
||||||
DomainRenewData.create(targetId, newExpirationTime),
|
.setExtensions(createResponseExtensions(commandOperations.getTotalCost(), feeRenew))
|
||||||
createResponseExtensions(commandOperations.getTotalCost(), feeRenew));
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void verifyRenewAllowed(
|
private void verifyRenewAllowed(
|
||||||
|
@ -199,7 +203,7 @@ public final class DomainRenewFlow extends Flow implements TransactionalFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
private OneTime createRenewBillingEvent(
|
private OneTime createRenewBillingEvent(
|
||||||
String tld, Money renewCost, int years, HistoryEntry historyEntry) {
|
String tld, Money renewCost, int years, HistoryEntry historyEntry, DateTime now) {
|
||||||
return new BillingEvent.OneTime.Builder()
|
return new BillingEvent.OneTime.Builder()
|
||||||
.setReason(Reason.RENEW)
|
.setReason(Reason.RENEW)
|
||||||
.setTargetId(targetId)
|
.setTargetId(targetId)
|
||||||
|
|
|
@ -26,7 +26,6 @@ import static google.registry.flows.domain.DomainFlowUtils.validateFeeChallenge;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.verifyNotReserved;
|
import static google.registry.flows.domain.DomainFlowUtils.verifyNotReserved;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.verifyPremiumNameIsNotBlocked;
|
import static google.registry.flows.domain.DomainFlowUtils.verifyPremiumNameIsNotBlocked;
|
||||||
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.ofy.ObjectifyService.ofy;
|
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||||
|
|
||||||
|
@ -40,8 +39,8 @@ import google.registry.flows.EppException;
|
||||||
import google.registry.flows.EppException.CommandUseErrorException;
|
import google.registry.flows.EppException.CommandUseErrorException;
|
||||||
import google.registry.flows.EppException.StatusProhibitsOperationException;
|
import google.registry.flows.EppException.StatusProhibitsOperationException;
|
||||||
import google.registry.flows.ExtensionManager;
|
import google.registry.flows.ExtensionManager;
|
||||||
import google.registry.flows.Flow;
|
|
||||||
import google.registry.flows.FlowModule.ClientId;
|
import google.registry.flows.FlowModule.ClientId;
|
||||||
|
import google.registry.flows.FlowModule.Superuser;
|
||||||
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.domain.TldSpecificLogicProxy.EppCommandOperations;
|
import google.registry.flows.domain.TldSpecificLogicProxy.EppCommandOperations;
|
||||||
|
@ -60,8 +59,9 @@ import google.registry.model.domain.metadata.MetadataExtension;
|
||||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||||
import google.registry.model.domain.rgp.RgpUpdateExtension;
|
import google.registry.model.domain.rgp.RgpUpdateExtension;
|
||||||
import google.registry.model.eppcommon.AuthInfo;
|
import google.registry.model.eppcommon.AuthInfo;
|
||||||
|
import google.registry.model.eppinput.EppInput;
|
||||||
import google.registry.model.eppinput.ResourceCommand;
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.poll.PollMessage;
|
import google.registry.model.poll.PollMessage;
|
||||||
import google.registry.model.registry.Registry;
|
import google.registry.model.registry.Registry;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
|
@ -103,37 +103,40 @@ import org.joda.time.DateTime;
|
||||||
* @error {@link DomainRestoreRequestFlow.DomainNotEligibleForRestoreException}
|
* @error {@link DomainRestoreRequestFlow.DomainNotEligibleForRestoreException}
|
||||||
* @error {@link DomainRestoreRequestFlow.RestoreCommandIncludesChangesException}
|
* @error {@link DomainRestoreRequestFlow.RestoreCommandIncludesChangesException}
|
||||||
*/
|
*/
|
||||||
public final class DomainRestoreRequestFlow extends Flow implements TransactionalFlow {
|
public final class DomainRestoreRequestFlow implements TransactionalFlow {
|
||||||
|
|
||||||
@Inject ResourceCommand resourceCommand;
|
@Inject ResourceCommand resourceCommand;
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
|
@Inject EppInput eppInput;
|
||||||
@Inject Optional<AuthInfo> authInfo;
|
@Inject Optional<AuthInfo> authInfo;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject @TargetId String targetId;
|
@Inject @TargetId String targetId;
|
||||||
|
@Inject @Superuser boolean isSuperuser;
|
||||||
@Inject HistoryEntry.Builder historyBuilder;
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
@Inject DnsQueue dnsQueue;
|
@Inject DnsQueue dnsQueue;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject DomainRestoreRequestFlow() {}
|
@Inject DomainRestoreRequestFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.register(MetadataExtension.class, RgpUpdateExtension.class);
|
extensionManager.register(MetadataExtension.class, RgpUpdateExtension.class);
|
||||||
extensionManager.registerAsGroup(FEE_UPDATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
|
extensionManager.registerAsGroup(FEE_UPDATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
|
||||||
extensionManager.validate();
|
extensionManager.validate();
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
Update command = (Update) resourceCommand;
|
Update command = (Update) resourceCommand;
|
||||||
|
DateTime now = ofy().getTransactionTime();
|
||||||
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
|
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
|
||||||
Money restoreCost = Registry.get(existingDomain.getTld()).getStandardRestoreCost();
|
Money restoreCost = Registry.get(existingDomain.getTld()).getStandardRestoreCost();
|
||||||
EppCommandOperations renewCommandOperations = TldSpecificLogicProxy.getRenewPrice(
|
EppCommandOperations renewCommandOperations = TldSpecificLogicProxy.getRenewPrice(
|
||||||
Registry.get(existingDomain.getTld()), targetId, clientId, now, 1, eppInput);
|
Registry.get(existingDomain.getTld()), targetId, clientId, now, 1, eppInput);
|
||||||
FeeTransformCommandExtension feeUpdate = eppInput.getFirstExtensionOfClasses(
|
FeeTransformCommandExtension feeUpdate = eppInput.getFirstExtensionOfClasses(
|
||||||
FEE_UPDATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
|
FEE_UPDATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
|
||||||
verifyRestoreAllowed(
|
Money totalCost = renewCommandOperations.getTotalCost();
|
||||||
command, existingDomain, restoreCost, renewCommandOperations.getTotalCost(), feeUpdate);
|
verifyRestoreAllowed(command, existingDomain, restoreCost, totalCost, feeUpdate, now);
|
||||||
HistoryEntry historyEntry = buildHistory(existingDomain);
|
HistoryEntry historyEntry = buildHistory(existingDomain, now);
|
||||||
ImmutableSet.Builder<ImmutableObject> entitiesToSave = new ImmutableSet.Builder<>();
|
ImmutableSet.Builder<ImmutableObject> entitiesToSave = new ImmutableSet.Builder<>();
|
||||||
entitiesToSave.addAll(
|
entitiesToSave.addAll(
|
||||||
createRestoreAndRenewBillingEvents(
|
createRestoreAndRenewBillingEvents(historyEntry, restoreCost, totalCost, now));
|
||||||
historyEntry, restoreCost, renewCommandOperations.getTotalCost()));
|
|
||||||
// We don't preserve the original expiration time of the domain when we restore, since doing so
|
// We don't preserve the original expiration time of the domain when we restore, since doing so
|
||||||
// would require us to know if they received a grace period refund when they deleted the domain,
|
// would require us to know if they received a grace period refund when they deleted the domain,
|
||||||
// and to charge them for that again. Instead, we just say that all restores get a fresh year of
|
// and to charge them for that again. Instead, we just say that all restores get a fresh year of
|
||||||
|
@ -163,13 +166,12 @@ public final class DomainRestoreRequestFlow extends Flow implements Transactiona
|
||||||
ofy().save().entities(entitiesToSave.build());
|
ofy().save().entities(entitiesToSave.build());
|
||||||
ofy().delete().key(existingDomain.getDeletePollMessage());
|
ofy().delete().key(existingDomain.getDeletePollMessage());
|
||||||
dnsQueue.addDomainRefreshTask(existingDomain.getFullyQualifiedDomainName());
|
dnsQueue.addDomainRefreshTask(existingDomain.getFullyQualifiedDomainName());
|
||||||
return createOutput(
|
return responseBuilder
|
||||||
SUCCESS,
|
.setExtensions(createResponseExtensions(restoreCost, totalCost, feeUpdate))
|
||||||
null,
|
.build();
|
||||||
createResponseExtensions(restoreCost, renewCommandOperations.getTotalCost(), feeUpdate));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private HistoryEntry buildHistory(DomainResource existingDomain) {
|
private HistoryEntry buildHistory(DomainResource existingDomain, DateTime now) {
|
||||||
return historyBuilder
|
return historyBuilder
|
||||||
.setType(HistoryEntry.Type.DOMAIN_RESTORE)
|
.setType(HistoryEntry.Type.DOMAIN_RESTORE)
|
||||||
.setModificationTime(now)
|
.setModificationTime(now)
|
||||||
|
@ -182,7 +184,8 @@ public final class DomainRestoreRequestFlow extends Flow implements Transactiona
|
||||||
DomainResource existingDomain,
|
DomainResource existingDomain,
|
||||||
Money restoreCost,
|
Money restoreCost,
|
||||||
Money renewCost,
|
Money renewCost,
|
||||||
FeeTransformCommandExtension feeUpdate) throws EppException {
|
FeeTransformCommandExtension feeUpdate,
|
||||||
|
DateTime now) throws EppException {
|
||||||
verifyOptionalAuthInfoForResource(authInfo, existingDomain);
|
verifyOptionalAuthInfoForResource(authInfo, existingDomain);
|
||||||
if (!isSuperuser) {
|
if (!isSuperuser) {
|
||||||
verifyResourceOwnership(clientId, existingDomain);
|
verifyResourceOwnership(clientId, existingDomain);
|
||||||
|
@ -202,14 +205,14 @@ public final class DomainRestoreRequestFlow extends Flow implements Transactiona
|
||||||
}
|
}
|
||||||
|
|
||||||
private ImmutableSet<BillingEvent.OneTime> createRestoreAndRenewBillingEvents(
|
private ImmutableSet<BillingEvent.OneTime> createRestoreAndRenewBillingEvents(
|
||||||
HistoryEntry historyEntry, Money restoreCost, Money renewCost) {
|
HistoryEntry historyEntry, Money restoreCost, Money renewCost, DateTime now) {
|
||||||
// Bill for the restore.
|
// Bill for the restore.
|
||||||
BillingEvent.OneTime restoreEvent = createRestoreBillingEvent(historyEntry, restoreCost);
|
BillingEvent.OneTime restoreEvent = createRestoreBillingEvent(historyEntry, restoreCost, now);
|
||||||
// Create a new autorenew billing event and poll message starting at the new expiration time.
|
// Create a new autorenew billing event and poll message starting at the new expiration time.
|
||||||
// Also bill for the 1 year cost of a domain renew. This is to avoid registrants being able to
|
// Also bill for the 1 year cost of a domain renew. This is to avoid registrants being able to
|
||||||
// game the system for premium names by renewing, deleting, and then restoring to get a free
|
// game the system for premium names by renewing, deleting, and then restoring to get a free
|
||||||
// year. Note that this billing event has no grace period; it is effective immediately.
|
// year. Note that this billing event has no grace period; it is effective immediately.
|
||||||
BillingEvent.OneTime renewEvent = createRenewBillingEvent(historyEntry, renewCost);
|
BillingEvent.OneTime renewEvent = createRenewBillingEvent(historyEntry, renewCost, now);
|
||||||
return ImmutableSet.of(restoreEvent, renewEvent);
|
return ImmutableSet.of(restoreEvent, renewEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,21 +232,22 @@ public final class DomainRestoreRequestFlow extends Flow implements Transactiona
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private OneTime createRenewBillingEvent(HistoryEntry historyEntry, Money renewCost) {
|
private OneTime createRenewBillingEvent(
|
||||||
return prepareBillingEvent(historyEntry, renewCost)
|
HistoryEntry historyEntry, Money renewCost, DateTime now) {
|
||||||
|
return prepareBillingEvent(historyEntry, renewCost, now)
|
||||||
.setPeriodYears(1)
|
.setPeriodYears(1)
|
||||||
.setReason(Reason.RENEW)
|
.setReason(Reason.RENEW)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private BillingEvent.OneTime createRestoreBillingEvent(
|
private BillingEvent.OneTime createRestoreBillingEvent(
|
||||||
HistoryEntry historyEntry, Money restoreCost) {
|
HistoryEntry historyEntry, Money restoreCost, DateTime now) {
|
||||||
return prepareBillingEvent(historyEntry, restoreCost)
|
return prepareBillingEvent(historyEntry, restoreCost, now)
|
||||||
.setReason(Reason.RESTORE)
|
.setReason(Reason.RESTORE)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Builder prepareBillingEvent(HistoryEntry historyEntry, Money cost) {
|
private Builder prepareBillingEvent(HistoryEntry historyEntry, Money cost, DateTime now) {
|
||||||
return new BillingEvent.OneTime.Builder()
|
return new BillingEvent.OneTime.Builder()
|
||||||
.setTargetId(targetId)
|
.setTargetId(targetId)
|
||||||
.setClientId(clientId)
|
.setClientId(clientId)
|
||||||
|
|
|
@ -27,7 +27,6 @@ import static google.registry.flows.domain.DomainFlowUtils.createGainingTransfer
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.createTransferResponse;
|
import static google.registry.flows.domain.DomainFlowUtils.createTransferResponse;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime;
|
import static google.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime;
|
||||||
import static google.registry.model.domain.DomainResource.extendRegistrationWithCap;
|
import static google.registry.model.domain.DomainResource.extendRegistrationWithCap;
|
||||||
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;
|
||||||
import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost;
|
import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost;
|
||||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||||
|
@ -38,7 +37,6 @@ import com.google.common.collect.ImmutableSet;
|
||||||
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;
|
||||||
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;
|
||||||
|
@ -51,7 +49,7 @@ import google.registry.model.domain.GracePeriod;
|
||||||
import google.registry.model.domain.metadata.MetadataExtension;
|
import google.registry.model.domain.metadata.MetadataExtension;
|
||||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||||
import google.registry.model.eppcommon.AuthInfo;
|
import google.registry.model.eppcommon.AuthInfo;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.poll.PollMessage;
|
import google.registry.model.poll.PollMessage;
|
||||||
import google.registry.model.registry.Registry;
|
import google.registry.model.registry.Registry;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
|
@ -78,13 +76,14 @@ import org.joda.time.DateTime;
|
||||||
* @error {@link google.registry.flows.exceptions.NotPendingTransferException}
|
* @error {@link google.registry.flows.exceptions.NotPendingTransferException}
|
||||||
* @error {@link DomainFlowUtils.NotAuthorizedForTldException}
|
* @error {@link DomainFlowUtils.NotAuthorizedForTldException}
|
||||||
*/
|
*/
|
||||||
public final class DomainTransferApproveFlow extends Flow implements TransactionalFlow {
|
public final class DomainTransferApproveFlow implements TransactionalFlow {
|
||||||
|
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
@Inject Optional<AuthInfo> authInfo;
|
@Inject Optional<AuthInfo> authInfo;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject @TargetId String targetId;
|
@Inject @TargetId String targetId;
|
||||||
@Inject HistoryEntry.Builder historyBuilder;
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject DomainTransferApproveFlow() {}
|
@Inject DomainTransferApproveFlow() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -92,10 +91,11 @@ public final class DomainTransferApproveFlow extends Flow implements Transaction
|
||||||
* {@link DomainResource#cloneProjectedAtTime} which handles implicit server approvals.
|
* {@link DomainResource#cloneProjectedAtTime} which handles implicit server approvals.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.register(MetadataExtension.class);
|
extensionManager.register(MetadataExtension.class);
|
||||||
extensionManager.validate();
|
extensionManager.validate();
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
|
DateTime now = ofy().getTransactionTime();
|
||||||
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
|
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
|
||||||
verifyOptionalAuthInfoForResource(authInfo, existingDomain);
|
verifyOptionalAuthInfoForResource(authInfo, existingDomain);
|
||||||
verifyHasPendingTransfer(existingDomain);
|
verifyHasPendingTransfer(existingDomain);
|
||||||
|
@ -187,9 +187,9 @@ public final class DomainTransferApproveFlow extends Flow implements Transaction
|
||||||
// Delete the billing event and poll messages that were written in case the transfer would have
|
// Delete the billing event and poll messages that were written in case the transfer would have
|
||||||
// been implicitly server approved.
|
// been implicitly server approved.
|
||||||
ofy().delete().keys(existingDomain.getTransferData().getServerApproveEntities());
|
ofy().delete().keys(existingDomain.getTransferData().getServerApproveEntities());
|
||||||
return createOutput(
|
return responseBuilder
|
||||||
SUCCESS,
|
.setResData(createTransferResponse(
|
||||||
createTransferResponse(
|
targetId, newDomain.getTransferData(), newDomain.getRegistrationExpirationTime()))
|
||||||
targetId, newDomain.getTransferData(), newDomain.getRegistrationExpirationTime()));
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToT
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.createLosingTransferPollMessage;
|
import static google.registry.flows.domain.DomainFlowUtils.createLosingTransferPollMessage;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.createTransferResponse;
|
import static google.registry.flows.domain.DomainFlowUtils.createTransferResponse;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime;
|
import static google.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime;
|
||||||
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;
|
||||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||||
|
|
||||||
|
@ -32,7 +31,6 @@ import com.google.common.base.Optional;
|
||||||
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;
|
||||||
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;
|
||||||
|
@ -40,10 +38,11 @@ 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.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import google.registry.model.transfer.TransferStatus;
|
import google.registry.model.transfer.TransferStatus;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An EPP flow that cancels a pending transfer on a domain.
|
* An EPP flow that cancels a pending transfer on a domain.
|
||||||
|
@ -63,20 +62,22 @@ import javax.inject.Inject;
|
||||||
* @error {@link google.registry.flows.exceptions.NotTransferInitiatorException}
|
* @error {@link google.registry.flows.exceptions.NotTransferInitiatorException}
|
||||||
* @error {@link DomainFlowUtils.NotAuthorizedForTldException}
|
* @error {@link DomainFlowUtils.NotAuthorizedForTldException}
|
||||||
*/
|
*/
|
||||||
public final class DomainTransferCancelFlow extends Flow implements TransactionalFlow {
|
public final class DomainTransferCancelFlow implements TransactionalFlow {
|
||||||
|
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
@Inject Optional<AuthInfo> authInfo;
|
@Inject Optional<AuthInfo> authInfo;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject @TargetId String targetId;
|
@Inject @TargetId String targetId;
|
||||||
@Inject HistoryEntry.Builder historyBuilder;
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject DomainTransferCancelFlow() {}
|
@Inject DomainTransferCancelFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.register(MetadataExtension.class);
|
extensionManager.register(MetadataExtension.class);
|
||||||
extensionManager.validate();
|
extensionManager.validate();
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
|
DateTime now = ofy().getTransactionTime();
|
||||||
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
|
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
|
||||||
verifyOptionalAuthInfoForResource(authInfo, existingDomain);
|
verifyOptionalAuthInfoForResource(authInfo, existingDomain);
|
||||||
verifyHasPendingTransfer(existingDomain);
|
verifyHasPendingTransfer(existingDomain);
|
||||||
|
@ -100,8 +101,8 @@ public final class DomainTransferCancelFlow extends Flow implements Transactiona
|
||||||
// Delete the billing event and poll messages that were written in case the transfer would have
|
// Delete the billing event and poll messages that were written in case the transfer would have
|
||||||
// been implicitly server approved.
|
// been implicitly server approved.
|
||||||
ofy().delete().keys(existingDomain.getTransferData().getServerApproveEntities());
|
ofy().delete().keys(existingDomain.getTransferData().getServerApproveEntities());
|
||||||
return createOutput(
|
return responseBuilder
|
||||||
SUCCESS,
|
.setResData(createTransferResponse(targetId, newDomain.getTransferData(), null))
|
||||||
createTransferResponse(targetId, newDomain.getTransferData(), null));
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@ import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
|
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.createTransferResponse;
|
import static google.registry.flows.domain.DomainFlowUtils.createTransferResponse;
|
||||||
import static google.registry.model.domain.DomainResource.extendRegistrationWithCap;
|
import static google.registry.model.domain.DomainResource.extendRegistrationWithCap;
|
||||||
import static google.registry.model.eppoutput.Result.Code.SUCCESS;
|
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
import google.registry.flows.EppException;
|
import google.registry.flows.EppException;
|
||||||
|
@ -31,9 +30,10 @@ import google.registry.flows.exceptions.NoTransferHistoryToQueryException;
|
||||||
import google.registry.flows.exceptions.NotAuthorizedToViewTransferException;
|
import google.registry.flows.exceptions.NotAuthorizedToViewTransferException;
|
||||||
import google.registry.model.domain.DomainResource;
|
import google.registry.model.domain.DomainResource;
|
||||||
import google.registry.model.eppcommon.AuthInfo;
|
import google.registry.model.eppcommon.AuthInfo;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.transfer.TransferData;
|
import google.registry.model.transfer.TransferData;
|
||||||
import google.registry.model.transfer.TransferStatus;
|
import google.registry.model.transfer.TransferStatus;
|
||||||
|
import google.registry.util.Clock;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
|
@ -52,18 +52,21 @@ import org.joda.time.DateTime;
|
||||||
* @error {@link google.registry.flows.exceptions.NoTransferHistoryToQueryException}
|
* @error {@link google.registry.flows.exceptions.NoTransferHistoryToQueryException}
|
||||||
* @error {@link google.registry.flows.exceptions.NotAuthorizedToViewTransferException}
|
* @error {@link google.registry.flows.exceptions.NotAuthorizedToViewTransferException}
|
||||||
*/
|
*/
|
||||||
public final class DomainTransferQueryFlow extends Flow {
|
public final class DomainTransferQueryFlow implements Flow {
|
||||||
|
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
@Inject Optional<AuthInfo> authInfo;
|
@Inject Optional<AuthInfo> authInfo;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject @TargetId String targetId;
|
@Inject @TargetId String targetId;
|
||||||
|
@Inject Clock clock;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject DomainTransferQueryFlow() {}
|
@Inject DomainTransferQueryFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.validate(); // There are no legal extensions for this flow.
|
extensionManager.validate(); // There are no legal extensions for this flow.
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
|
DateTime now = clock.nowUtc();
|
||||||
DomainResource domain = loadAndVerifyExistence(DomainResource.class, targetId, now);
|
DomainResource domain = loadAndVerifyExistence(DomainResource.class, targetId, now);
|
||||||
verifyOptionalAuthInfoForResource(authInfo, domain);
|
verifyOptionalAuthInfoForResource(authInfo, domain);
|
||||||
// Most of the fields on the transfer response are required, so there's no way to return valid
|
// Most of the fields on the transfer response are required, so there's no way to return valid
|
||||||
|
@ -88,6 +91,8 @@ public final class DomainTransferQueryFlow extends Flow {
|
||||||
domain.getRegistrationExpirationTime(),
|
domain.getRegistrationExpirationTime(),
|
||||||
transferData.getExtendedRegistrationYears());
|
transferData.getExtendedRegistrationYears());
|
||||||
}
|
}
|
||||||
return createOutput(SUCCESS, createTransferResponse(targetId, transferData, newExpirationTime));
|
return responseBuilder
|
||||||
|
.setResData(createTransferResponse(targetId, transferData, newExpirationTime))
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToT
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.createGainingTransferPollMessage;
|
import static google.registry.flows.domain.DomainFlowUtils.createGainingTransferPollMessage;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.createTransferResponse;
|
import static google.registry.flows.domain.DomainFlowUtils.createTransferResponse;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime;
|
import static google.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime;
|
||||||
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;
|
||||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||||
|
|
||||||
|
@ -32,7 +31,6 @@ import com.google.common.base.Optional;
|
||||||
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;
|
||||||
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;
|
||||||
|
@ -40,10 +38,11 @@ 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.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import google.registry.model.transfer.TransferStatus;
|
import google.registry.model.transfer.TransferStatus;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An EPP flow that rejects a pending transfer on a domain.
|
* An EPP flow that rejects a pending transfer on a domain.
|
||||||
|
@ -63,20 +62,22 @@ import javax.inject.Inject;
|
||||||
* @error {@link google.registry.flows.exceptions.NotPendingTransferException}
|
* @error {@link google.registry.flows.exceptions.NotPendingTransferException}
|
||||||
* @error {@link DomainFlowUtils.NotAuthorizedForTldException}
|
* @error {@link DomainFlowUtils.NotAuthorizedForTldException}
|
||||||
*/
|
*/
|
||||||
public final class DomainTransferRejectFlow extends Flow implements TransactionalFlow {
|
public final class DomainTransferRejectFlow implements TransactionalFlow {
|
||||||
|
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
@Inject Optional<AuthInfo> authInfo;
|
@Inject Optional<AuthInfo> authInfo;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject @TargetId String targetId;
|
@Inject @TargetId String targetId;
|
||||||
@Inject HistoryEntry.Builder historyBuilder;
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject DomainTransferRejectFlow() {}
|
@Inject DomainTransferRejectFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.register(MetadataExtension.class);
|
extensionManager.register(MetadataExtension.class);
|
||||||
extensionManager.validate();
|
extensionManager.validate();
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
|
DateTime now = ofy().getTransactionTime();
|
||||||
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
|
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
|
||||||
HistoryEntry historyEntry = historyBuilder
|
HistoryEntry historyEntry = historyBuilder
|
||||||
.setType(HistoryEntry.Type.DOMAIN_TRANSFER_REJECT)
|
.setType(HistoryEntry.Type.DOMAIN_TRANSFER_REJECT)
|
||||||
|
@ -100,8 +101,8 @@ public final class DomainTransferRejectFlow extends Flow implements Transactiona
|
||||||
// Delete the billing event and poll messages that were written in case the transfer would have
|
// Delete the billing event and poll messages that were written in case the transfer would have
|
||||||
// been implicitly server approved.
|
// been implicitly server approved.
|
||||||
ofy().delete().keys(existingDomain.getTransferData().getServerApproveEntities());
|
ofy().delete().keys(existingDomain.getTransferData().getServerApproveEntities());
|
||||||
return createOutput(
|
return responseBuilder
|
||||||
SUCCESS,
|
.setResData(createTransferResponse(targetId, newDomain.getTransferData(), null))
|
||||||
createTransferResponse(targetId, newDomain.getTransferData(), null));
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,8 +41,8 @@ import com.google.common.collect.ImmutableSet;
|
||||||
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;
|
||||||
import google.registry.flows.Flow;
|
|
||||||
import google.registry.flows.FlowModule.ClientId;
|
import google.registry.flows.FlowModule.ClientId;
|
||||||
|
import google.registry.flows.FlowModule.Superuser;
|
||||||
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.AlreadyPendingTransferException;
|
import google.registry.flows.exceptions.AlreadyPendingTransferException;
|
||||||
|
@ -61,8 +61,10 @@ import google.registry.model.domain.flags.FlagsTransferCommandExtension;
|
||||||
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.eppcommon.Trid;
|
||||||
|
import google.registry.model.eppinput.EppInput;
|
||||||
import google.registry.model.eppinput.ResourceCommand;
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.poll.PollMessage;
|
import google.registry.model.poll.PollMessage;
|
||||||
import google.registry.model.registry.Registry;
|
import google.registry.model.registry.Registry;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
|
@ -106,7 +108,7 @@ import org.joda.time.Duration;
|
||||||
* @error {@link DomainFlowUtils.PremiumNameBlockedException}
|
* @error {@link DomainFlowUtils.PremiumNameBlockedException}
|
||||||
* @error {@link DomainFlowUtils.UnsupportedFeeAttributeException}
|
* @error {@link DomainFlowUtils.UnsupportedFeeAttributeException}
|
||||||
*/
|
*/
|
||||||
public final class DomainTransferRequestFlow extends Flow implements TransactionalFlow {
|
public final class DomainTransferRequestFlow implements TransactionalFlow {
|
||||||
|
|
||||||
private static final ImmutableSet<StatusValue> DISALLOWED_STATUSES = ImmutableSet.of(
|
private static final ImmutableSet<StatusValue> DISALLOWED_STATUSES = ImmutableSet.of(
|
||||||
StatusValue.CLIENT_TRANSFER_PROHIBITED,
|
StatusValue.CLIENT_TRANSFER_PROHIBITED,
|
||||||
|
@ -115,22 +117,27 @@ public final class DomainTransferRequestFlow extends Flow implements Transaction
|
||||||
|
|
||||||
@Inject ResourceCommand resourceCommand;
|
@Inject ResourceCommand resourceCommand;
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
|
@Inject EppInput eppInput;
|
||||||
@Inject Optional<AuthInfo> authInfo;
|
@Inject Optional<AuthInfo> authInfo;
|
||||||
@Inject @ClientId String gainingClientId;
|
@Inject @ClientId String gainingClientId;
|
||||||
@Inject @TargetId String targetId;
|
@Inject @TargetId String targetId;
|
||||||
|
@Inject @Superuser boolean isSuperuser;
|
||||||
@Inject HistoryEntry.Builder historyBuilder;
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
|
@Inject Trid trid;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject DomainTransferRequestFlow() {}
|
@Inject DomainTransferRequestFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.register(FlagsTransferCommandExtension.class, MetadataExtension.class);
|
extensionManager.register(FlagsTransferCommandExtension.class, MetadataExtension.class);
|
||||||
extensionManager.registerAsGroup(FEE_TRANSFER_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
|
extensionManager.registerAsGroup(FEE_TRANSFER_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
|
||||||
extensionManager.validate();
|
extensionManager.validate();
|
||||||
validateClientIsLoggedIn(gainingClientId);
|
validateClientIsLoggedIn(gainingClientId);
|
||||||
Period period = ((Transfer) resourceCommand).getPeriod();
|
Period period = ((Transfer) resourceCommand).getPeriod();
|
||||||
int years = period.getValue();
|
int years = period.getValue();
|
||||||
|
DateTime now = ofy().getTransactionTime();
|
||||||
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
|
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
|
||||||
verifyTransferAllowed(existingDomain, period);
|
verifyTransferAllowed(existingDomain, period, now);
|
||||||
String tld = existingDomain.getTld();
|
String tld = existingDomain.getTld();
|
||||||
Registry registry = Registry.get(tld);
|
Registry registry = Registry.get(tld);
|
||||||
// The cost of the renewal implied by a transfer.
|
// The cost of the renewal implied by a transfer.
|
||||||
|
@ -139,7 +146,7 @@ public final class DomainTransferRequestFlow extends Flow implements Transaction
|
||||||
FeeTransformCommandExtension feeTransfer = eppInput.getFirstExtensionOfClasses(
|
FeeTransformCommandExtension feeTransfer = eppInput.getFirstExtensionOfClasses(
|
||||||
FEE_TRANSFER_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
|
FEE_TRANSFER_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
|
||||||
validateFeeChallenge(targetId, tld, now, feeTransfer, renewCost);
|
validateFeeChallenge(targetId, tld, now, feeTransfer, renewCost);
|
||||||
HistoryEntry historyEntry = buildHistory(period, existingDomain);
|
HistoryEntry historyEntry = buildHistory(period, existingDomain, now);
|
||||||
DateTime automaticTransferTime = now.plus(registry.getAutomaticTransferLength());
|
DateTime automaticTransferTime = now.plus(registry.getAutomaticTransferLength());
|
||||||
// The new expiration time if there is a server approval.
|
// The new expiration time if there is a server approval.
|
||||||
DateTime serverApproveNewExpirationTime = extendRegistrationWithCap(
|
DateTime serverApproveNewExpirationTime = extendRegistrationWithCap(
|
||||||
|
@ -152,10 +159,11 @@ public final class DomainTransferRequestFlow extends Flow implements Transaction
|
||||||
historyEntry,
|
historyEntry,
|
||||||
existingDomain,
|
existingDomain,
|
||||||
renewCost,
|
renewCost,
|
||||||
years);
|
years,
|
||||||
|
now);
|
||||||
// Create the transfer data that represents the pending transfer.
|
// Create the transfer data that represents the pending transfer.
|
||||||
TransferData pendingTransferData = createPendingTransferData(
|
TransferData pendingTransferData = createPendingTransferData(
|
||||||
createTransferDataBuilder(existingDomain, automaticTransferTime, years),
|
createTransferDataBuilder(existingDomain, automaticTransferTime, years, now),
|
||||||
serverApproveEntities);
|
serverApproveEntities);
|
||||||
// Create a poll message to notify the losing registrar that a transfer was requested.
|
// Create a poll message to notify the losing registrar that a transfer was requested.
|
||||||
PollMessage requestPollMessage = createLosingTransferPollMessage(
|
PollMessage requestPollMessage = createLosingTransferPollMessage(
|
||||||
|
@ -166,7 +174,7 @@ public final class DomainTransferRequestFlow extends Flow implements Transaction
|
||||||
// cloneProjectedAtTime() will replace these old autorenew entities with the server approve ones
|
// cloneProjectedAtTime() will replace these old autorenew entities with the server approve ones
|
||||||
// that we've created in this flow and stored in pendingTransferData.
|
// that we've created in this flow and stored in pendingTransferData.
|
||||||
updateAutorenewRecurrenceEndTime(existingDomain, automaticTransferTime);
|
updateAutorenewRecurrenceEndTime(existingDomain, automaticTransferTime);
|
||||||
handleExtraFlowLogic(years, existingDomain, historyEntry);
|
handleExtraFlowLogic(years, existingDomain, historyEntry, now);
|
||||||
DomainResource newDomain = existingDomain.asBuilder()
|
DomainResource newDomain = existingDomain.asBuilder()
|
||||||
.setTransferData(pendingTransferData)
|
.setTransferData(pendingTransferData)
|
||||||
.addStatusValue(StatusValue.PENDING_TRANSFER)
|
.addStatusValue(StatusValue.PENDING_TRANSFER)
|
||||||
|
@ -177,13 +185,14 @@ public final class DomainTransferRequestFlow extends Flow implements Transaction
|
||||||
.addAll(serverApproveEntities)
|
.addAll(serverApproveEntities)
|
||||||
.build())
|
.build())
|
||||||
.now();
|
.now();
|
||||||
return createOutput(
|
return responseBuilder
|
||||||
SUCCESS_WITH_ACTION_PENDING,
|
.setResultFromCode(SUCCESS_WITH_ACTION_PENDING)
|
||||||
createResponse(period, existingDomain, newDomain),
|
.setResData(createResponse(period, existingDomain, newDomain, now))
|
||||||
createResponseExtensions(renewCost, feeTransfer));
|
.setExtensions(createResponseExtensions(renewCost, feeTransfer))
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void verifyTransferAllowed(DomainResource existingDomain, Period period)
|
private void verifyTransferAllowed(DomainResource existingDomain, Period period, DateTime now)
|
||||||
throws EppException {
|
throws EppException {
|
||||||
verifyNoDisallowedStatuses(existingDomain, DISALLOWED_STATUSES);
|
verifyNoDisallowedStatuses(existingDomain, DISALLOWED_STATUSES);
|
||||||
verifyRequiredAuthInfoForResourceTransfer(authInfo, existingDomain);
|
verifyRequiredAuthInfoForResourceTransfer(authInfo, existingDomain);
|
||||||
|
@ -202,7 +211,7 @@ public final class DomainTransferRequestFlow extends Flow implements Transaction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private HistoryEntry buildHistory(Period period, DomainResource existingResource) {
|
private HistoryEntry buildHistory(Period period, DomainResource existingResource, DateTime now) {
|
||||||
return historyBuilder
|
return historyBuilder
|
||||||
.setType(HistoryEntry.Type.DOMAIN_TRANSFER_REQUEST)
|
.setType(HistoryEntry.Type.DOMAIN_TRANSFER_REQUEST)
|
||||||
.setPeriod(period)
|
.setPeriod(period)
|
||||||
|
@ -231,10 +240,11 @@ public final class DomainTransferRequestFlow extends Flow implements Transaction
|
||||||
HistoryEntry historyEntry,
|
HistoryEntry historyEntry,
|
||||||
DomainResource existingDomain,
|
DomainResource existingDomain,
|
||||||
Money renewCost,
|
Money renewCost,
|
||||||
int years) {
|
int years,
|
||||||
|
DateTime now) {
|
||||||
// Create a TransferData for the server-approve case to use for the speculative poll messages.
|
// Create a TransferData for the server-approve case to use for the speculative poll messages.
|
||||||
TransferData serverApproveTransferData =
|
TransferData serverApproveTransferData =
|
||||||
createTransferDataBuilder(existingDomain, automaticTransferTime, years)
|
createTransferDataBuilder(existingDomain, automaticTransferTime, years, now)
|
||||||
.setTransferStatus(TransferStatus.SERVER_APPROVED)
|
.setTransferStatus(TransferStatus.SERVER_APPROVED)
|
||||||
.build();
|
.build();
|
||||||
Registry registry = Registry.get(existingDomain.getTld());
|
Registry registry = Registry.get(existingDomain.getTld());
|
||||||
|
@ -333,9 +343,7 @@ public final class DomainTransferRequestFlow extends Flow implements Transaction
|
||||||
}
|
}
|
||||||
|
|
||||||
private Builder createTransferDataBuilder(
|
private Builder createTransferDataBuilder(
|
||||||
DomainResource existingDomain,
|
DomainResource existingDomain, DateTime automaticTransferTime, int years, DateTime now) {
|
||||||
DateTime automaticTransferTime,
|
|
||||||
int years) {
|
|
||||||
return new TransferData.Builder()
|
return new TransferData.Builder()
|
||||||
.setTransferRequestTrid(trid)
|
.setTransferRequestTrid(trid)
|
||||||
.setTransferRequestTime(now)
|
.setTransferRequestTime(now)
|
||||||
|
@ -366,17 +374,23 @@ public final class DomainTransferRequestFlow extends Flow implements Transaction
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleExtraFlowLogic(
|
private void handleExtraFlowLogic(
|
||||||
int years, DomainResource existingDomain, HistoryEntry historyEntry) throws EppException {
|
int years, DomainResource existingDomain, HistoryEntry historyEntry, DateTime now)
|
||||||
|
throws EppException {
|
||||||
Optional<RegistryExtraFlowLogic> extraFlowLogic =
|
Optional<RegistryExtraFlowLogic> extraFlowLogic =
|
||||||
RegistryExtraFlowLogicProxy.newInstanceForDomain(existingDomain);
|
RegistryExtraFlowLogicProxy.newInstanceForDomain(existingDomain);
|
||||||
if (extraFlowLogic.isPresent()) {
|
if (extraFlowLogic.isPresent()) {
|
||||||
extraFlowLogic.get().performAdditionalDomainTransferLogic(
|
extraFlowLogic.get().performAdditionalDomainTransferLogic(
|
||||||
existingDomain, gainingClientId, now, years, eppInput, historyEntry);
|
existingDomain,
|
||||||
|
gainingClientId,
|
||||||
|
now,
|
||||||
|
years,
|
||||||
|
eppInput,
|
||||||
|
historyEntry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private DomainTransferResponse createResponse(
|
private DomainTransferResponse createResponse(
|
||||||
Period period, DomainResource existingDomain, DomainResource newDomain) {
|
Period period, DomainResource existingDomain, DomainResource newDomain, DateTime now) {
|
||||||
// If the registration were approved this instant, this is what the new expiration would be,
|
// If the registration were approved this instant, this is what the new expiration would be,
|
||||||
// because we cap at 10 years from the moment of approval. This is different than the server
|
// because we cap at 10 years from the moment of approval. This is different than the server
|
||||||
// approval new expiration time, which is capped at 10 years from the server approve time.
|
// approval new expiration time, which is capped at 10 years from the server approve time.
|
||||||
|
|
|
@ -38,7 +38,6 @@ import static google.registry.flows.domain.DomainFlowUtils.validateRequiredConta
|
||||||
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.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.ofy.ObjectifyService.ofy;
|
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
import static google.registry.util.DateTimeUtils.earliestOf;
|
import static google.registry.util.DateTimeUtils.earliestOf;
|
||||||
|
|
||||||
|
@ -49,8 +48,8 @@ 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;
|
||||||
import google.registry.flows.ExtensionManager;
|
import google.registry.flows.ExtensionManager;
|
||||||
import google.registry.flows.Flow;
|
|
||||||
import google.registry.flows.FlowModule.ClientId;
|
import google.registry.flows.FlowModule.ClientId;
|
||||||
|
import google.registry.flows.FlowModule.Superuser;
|
||||||
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.domain.DomainFlowUtils.FeesRequiredForNonFreeUpdateException;
|
import google.registry.flows.domain.DomainFlowUtils.FeesRequiredForNonFreeUpdateException;
|
||||||
|
@ -70,8 +69,9 @@ import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||||
import google.registry.model.domain.secdns.SecDnsUpdateExtension;
|
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.EppInput;
|
||||||
import google.registry.model.eppinput.ResourceCommand;
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.registry.Registry;
|
import google.registry.model.registry.Registry;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -121,7 +121,7 @@ import org.joda.time.DateTime;
|
||||||
* @error {@link DomainFlowUtils.TooManyNameserversException}
|
* @error {@link DomainFlowUtils.TooManyNameserversException}
|
||||||
* @error {@link DomainFlowUtils.UrgentAttributeNotSupportedException}
|
* @error {@link DomainFlowUtils.UrgentAttributeNotSupportedException}
|
||||||
*/
|
*/
|
||||||
public final class DomainUpdateFlow extends Flow implements TransactionalFlow {
|
public final class DomainUpdateFlow implements TransactionalFlow {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note that CLIENT_UPDATE_PROHIBITED is intentionally not in this list. This is because it
|
* Note that CLIENT_UPDATE_PROHIBITED is intentionally not in this list. This is because it
|
||||||
|
@ -134,15 +134,18 @@ public final class DomainUpdateFlow extends Flow implements TransactionalFlow {
|
||||||
|
|
||||||
@Inject ResourceCommand resourceCommand;
|
@Inject ResourceCommand resourceCommand;
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
|
@Inject EppInput eppInput;
|
||||||
@Inject Optional<AuthInfo> authInfo;
|
@Inject Optional<AuthInfo> authInfo;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject @TargetId String targetId;
|
@Inject @TargetId String targetId;
|
||||||
|
@Inject @Superuser boolean isSuperuser;
|
||||||
@Inject HistoryEntry.Builder historyBuilder;
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
@Inject DnsQueue dnsQueue;
|
@Inject DnsQueue dnsQueue;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject DomainUpdateFlow() {}
|
@Inject DomainUpdateFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EppOutput run() throws EppException {
|
public EppResponse run() throws EppException {
|
||||||
extensionManager.register(
|
extensionManager.register(
|
||||||
FlagsUpdateCommandExtension.class,
|
FlagsUpdateCommandExtension.class,
|
||||||
MetadataExtension.class,
|
MetadataExtension.class,
|
||||||
|
@ -150,37 +153,38 @@ public final class DomainUpdateFlow extends Flow implements TransactionalFlow {
|
||||||
extensionManager.registerAsGroup(FEE_UPDATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
|
extensionManager.registerAsGroup(FEE_UPDATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
|
||||||
extensionManager.validate();
|
extensionManager.validate();
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
|
DateTime now = ofy().getTransactionTime();
|
||||||
Update command = cloneAndLinkReferences((Update) resourceCommand, now);
|
Update command = cloneAndLinkReferences((Update) resourceCommand, now);
|
||||||
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
|
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
|
||||||
verifyUpdateAllowed(command, existingDomain);
|
verifyUpdateAllowed(command, existingDomain, now);
|
||||||
HistoryEntry historyEntry = buildHistoryEntry(existingDomain);
|
HistoryEntry historyEntry = buildHistoryEntry(existingDomain, now);
|
||||||
DomainResource newDomain = performUpdate(command, existingDomain);
|
DomainResource newDomain = performUpdate(command, existingDomain, now);
|
||||||
// If the new domain is in the sunrush add grace period and is now publishable to DNS because we
|
// If the new domain is in the sunrush add grace period and is now publishable to DNS because we
|
||||||
// have added nameserver or removed holds, we have to convert it to a standard add grace period.
|
// have added nameserver or removed holds, we have to convert it to a standard add grace period.
|
||||||
if (newDomain.shouldPublishToDns()) {
|
if (newDomain.shouldPublishToDns()) {
|
||||||
for (GracePeriod gracePeriod : newDomain.getGracePeriods()) {
|
for (GracePeriod gracePeriod : newDomain.getGracePeriods()) {
|
||||||
if (gracePeriod.isSunrushAddGracePeriod()) {
|
if (gracePeriod.isSunrushAddGracePeriod()) {
|
||||||
newDomain = convertSunrushAddToAdd(newDomain, gracePeriod, historyEntry);
|
newDomain = convertSunrushAddToAdd(newDomain, gracePeriod, historyEntry, now);
|
||||||
break; // There can only be one sunrush add grace period.
|
break; // There can only be one sunrush add grace period.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
validateNewState(newDomain);
|
validateNewState(newDomain);
|
||||||
dnsQueue.addDomainRefreshTask(targetId);
|
dnsQueue.addDomainRefreshTask(targetId);
|
||||||
handleExtraFlowLogic(existingDomain, historyEntry);
|
handleExtraFlowLogic(existingDomain, historyEntry, now);
|
||||||
ImmutableList.Builder<ImmutableObject> entitiesToSave = new ImmutableList.Builder<>();
|
ImmutableList.Builder<ImmutableObject> entitiesToSave = new ImmutableList.Builder<>();
|
||||||
entitiesToSave.add(newDomain, historyEntry);
|
entitiesToSave.add(newDomain, historyEntry);
|
||||||
Optional<BillingEvent.OneTime> statusUpdateBillingEvent =
|
Optional<BillingEvent.OneTime> statusUpdateBillingEvent =
|
||||||
createBillingEventForStatusUpdates(existingDomain, newDomain, historyEntry);
|
createBillingEventForStatusUpdates(existingDomain, newDomain, historyEntry, now);
|
||||||
if (statusUpdateBillingEvent.isPresent()) {
|
if (statusUpdateBillingEvent.isPresent()) {
|
||||||
entitiesToSave.add(statusUpdateBillingEvent.get());
|
entitiesToSave.add(statusUpdateBillingEvent.get());
|
||||||
}
|
}
|
||||||
ofy().save().entities(entitiesToSave.build());
|
ofy().save().entities(entitiesToSave.build());
|
||||||
return createOutput(SUCCESS);
|
return responseBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Fail if the object doesn't exist or was deleted. */
|
/** Fail if the object doesn't exist or was deleted. */
|
||||||
private void verifyUpdateAllowed(Update command, DomainResource existingDomain)
|
private void verifyUpdateAllowed(Update command, DomainResource existingDomain, DateTime now)
|
||||||
throws EppException {
|
throws EppException {
|
||||||
verifyNoDisallowedStatuses(existingDomain, UPDATE_DISALLOWED_STATUSES);
|
verifyNoDisallowedStatuses(existingDomain, UPDATE_DISALLOWED_STATUSES);
|
||||||
verifyOptionalAuthInfoForResource(authInfo, existingDomain);
|
verifyOptionalAuthInfoForResource(authInfo, existingDomain);
|
||||||
|
@ -219,7 +223,7 @@ public final class DomainUpdateFlow extends Flow implements TransactionalFlow {
|
||||||
tld, add.getNameserverFullyQualifiedHostNames());
|
tld, add.getNameserverFullyQualifiedHostNames());
|
||||||
}
|
}
|
||||||
|
|
||||||
private HistoryEntry buildHistoryEntry(DomainResource existingDomain) {
|
private HistoryEntry buildHistoryEntry(DomainResource existingDomain, DateTime now) {
|
||||||
return historyBuilder
|
return historyBuilder
|
||||||
.setType(HistoryEntry.Type.DOMAIN_UPDATE)
|
.setType(HistoryEntry.Type.DOMAIN_UPDATE)
|
||||||
.setModificationTime(now)
|
.setModificationTime(now)
|
||||||
|
@ -227,7 +231,7 @@ public final class DomainUpdateFlow extends Flow implements TransactionalFlow {
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private DomainResource performUpdate(Update command, DomainResource domain)
|
private DomainResource performUpdate(Update command, DomainResource domain, DateTime now)
|
||||||
throws EppException {
|
throws EppException {
|
||||||
AddRemove add = command.getInnerAdd();
|
AddRemove add = command.getInnerAdd();
|
||||||
AddRemove remove = command.getInnerRemove();
|
AddRemove remove = command.getInnerRemove();
|
||||||
|
@ -255,12 +259,12 @@ public final class DomainUpdateFlow extends Flow implements TransactionalFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
private DomainResource convertSunrushAddToAdd(
|
private DomainResource convertSunrushAddToAdd(
|
||||||
DomainResource newDomain, GracePeriod gracePeriod, HistoryEntry historyEntry) {
|
DomainResource newDomain, GracePeriod gracePeriod, HistoryEntry historyEntry, DateTime now) {
|
||||||
// Cancel the billing event for the sunrush add and replace it with a new billing event.
|
// Cancel the billing event for the sunrush add and replace it with a new billing event.
|
||||||
BillingEvent.Cancellation billingEventCancellation =
|
BillingEvent.Cancellation billingEventCancellation =
|
||||||
BillingEvent.Cancellation.forGracePeriod(gracePeriod, historyEntry, targetId);
|
BillingEvent.Cancellation.forGracePeriod(gracePeriod, historyEntry, targetId);
|
||||||
BillingEvent.OneTime billingEvent =
|
BillingEvent.OneTime billingEvent =
|
||||||
createBillingEventForSunrushConversion(newDomain, historyEntry, gracePeriod);
|
createBillingEventForSunrushConversion(newDomain, historyEntry, gracePeriod, now);
|
||||||
ofy().save().entities(billingEvent, billingEventCancellation);
|
ofy().save().entities(billingEvent, billingEventCancellation);
|
||||||
// Modify the grace periods on the domain.
|
// Modify the grace periods on the domain.
|
||||||
return newDomain.asBuilder()
|
return newDomain.asBuilder()
|
||||||
|
@ -270,7 +274,10 @@ public final class DomainUpdateFlow extends Flow implements TransactionalFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
private BillingEvent.OneTime createBillingEventForSunrushConversion(
|
private BillingEvent.OneTime createBillingEventForSunrushConversion(
|
||||||
DomainResource existingDomain, HistoryEntry historyEntry, GracePeriod sunrushAddGracePeriod) {
|
DomainResource existingDomain,
|
||||||
|
HistoryEntry historyEntry,
|
||||||
|
GracePeriod sunrushAddGracePeriod,
|
||||||
|
DateTime now) {
|
||||||
// Compute the expiration time of the add grace period. We will not allow it to be after the
|
// Compute the expiration time of the add grace period. We will not allow it to be after the
|
||||||
// sunrush add grace period expiration time (i.e. you can't get extra add grace period by
|
// sunrush add grace period expiration time (i.e. you can't get extra add grace period by
|
||||||
// setting a nameserver).
|
// setting a nameserver).
|
||||||
|
@ -304,7 +311,10 @@ public final class DomainUpdateFlow extends Flow implements TransactionalFlow {
|
||||||
|
|
||||||
/** Some status updates cost money. Bill only once no matter how many of them are changed. */
|
/** Some status updates cost money. Bill only once no matter how many of them are changed. */
|
||||||
private Optional<BillingEvent.OneTime> createBillingEventForStatusUpdates(
|
private Optional<BillingEvent.OneTime> createBillingEventForStatusUpdates(
|
||||||
DomainResource existingDomain, DomainResource newDomain, HistoryEntry historyEntry) {
|
DomainResource existingDomain,
|
||||||
|
DomainResource newDomain,
|
||||||
|
HistoryEntry historyEntry,
|
||||||
|
DateTime now) {
|
||||||
MetadataExtension metadataExtension = eppInput.getSingleExtension(MetadataExtension.class);
|
MetadataExtension metadataExtension = eppInput.getSingleExtension(MetadataExtension.class);
|
||||||
if (metadataExtension != null && metadataExtension.getRequestedByRegistrar()) {
|
if (metadataExtension != null && metadataExtension.getRequestedByRegistrar()) {
|
||||||
for (StatusValue statusValue
|
for (StatusValue statusValue
|
||||||
|
@ -326,8 +336,8 @@ public final class DomainUpdateFlow extends Flow implements TransactionalFlow {
|
||||||
return Optional.absent();
|
return Optional.absent();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleExtraFlowLogic(DomainResource existingDomain, HistoryEntry historyEntry)
|
private void handleExtraFlowLogic(
|
||||||
throws EppException {
|
DomainResource existingDomain, HistoryEntry historyEntry, DateTime now) throws EppException {
|
||||||
Optional<RegistryExtraFlowLogic> extraFlowLogic =
|
Optional<RegistryExtraFlowLogic> extraFlowLogic =
|
||||||
RegistryExtraFlowLogicProxy.newInstanceForDomain(existingDomain);
|
RegistryExtraFlowLogicProxy.newInstanceForDomain(existingDomain);
|
||||||
if (extraFlowLogic.isPresent()) {
|
if (extraFlowLogic.isPresent()) {
|
||||||
|
|
|
@ -17,7 +17,6 @@ package google.registry.flows.host;
|
||||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyTargetIdCount;
|
import static google.registry.flows.ResourceFlowUtils.verifyTargetIdCount;
|
||||||
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.config.ConfigModule.Config;
|
import google.registry.config.ConfigModule.Config;
|
||||||
|
@ -28,9 +27,10 @@ import google.registry.flows.FlowModule.ClientId;
|
||||||
import google.registry.model.eppinput.ResourceCommand;
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
import google.registry.model.eppoutput.CheckData.HostCheck;
|
import google.registry.model.eppoutput.CheckData.HostCheck;
|
||||||
import google.registry.model.eppoutput.CheckData.HostCheckData;
|
import google.registry.model.eppoutput.CheckData.HostCheckData;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.host.HostCommand.Check;
|
import google.registry.model.host.HostCommand.Check;
|
||||||
import google.registry.model.host.HostResource;
|
import google.registry.model.host.HostResource;
|
||||||
|
import google.registry.util.Clock;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -42,26 +42,28 @@ import javax.inject.Inject;
|
||||||
*
|
*
|
||||||
* @error {@link google.registry.flows.exceptions.TooManyResourceChecksException}
|
* @error {@link google.registry.flows.exceptions.TooManyResourceChecksException}
|
||||||
*/
|
*/
|
||||||
public final class HostCheckFlow extends Flow {
|
public final class HostCheckFlow implements Flow {
|
||||||
|
|
||||||
@Inject ResourceCommand resourceCommand;
|
@Inject ResourceCommand resourceCommand;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
@Inject @Config("maxChecks") int maxChecks;
|
@Inject @Config("maxChecks") int maxChecks;
|
||||||
|
@Inject Clock clock;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject HostCheckFlow() {}
|
@Inject HostCheckFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.validate(); // There are no legal extensions for this flow.
|
extensionManager.validate(); // There are no legal extensions for this flow.
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
List<String> targetIds = ((Check) resourceCommand).getTargetIds();
|
List<String> targetIds = ((Check) resourceCommand).getTargetIds();
|
||||||
verifyTargetIdCount(targetIds, maxChecks);
|
verifyTargetIdCount(targetIds, maxChecks);
|
||||||
Set<String> existingIds = checkResourcesExist(HostResource.class, targetIds, now);
|
Set<String> existingIds = checkResourcesExist(HostResource.class, targetIds, clock.nowUtc());
|
||||||
ImmutableList.Builder<HostCheck> checks = new ImmutableList.Builder<>();
|
ImmutableList.Builder<HostCheck> checks = new ImmutableList.Builder<>();
|
||||||
for (String id : targetIds) {
|
for (String id : targetIds) {
|
||||||
boolean unused = !existingIds.contains(id);
|
boolean unused = !existingIds.contains(id);
|
||||||
checks.add(HostCheck.create(unused, id, unused ? null : "In use"));
|
checks.add(HostCheck.create(unused, id, unused ? null : "In use"));
|
||||||
}
|
}
|
||||||
return createOutput(SUCCESS, HostCheckData.create(checks.build()));
|
return responseBuilder.setResData(HostCheckData.create(checks.build())).build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ import static google.registry.flows.host.HostFlowUtils.lookupSuperordinateDomain
|
||||||
import static google.registry.flows.host.HostFlowUtils.validateHostName;
|
import static google.registry.flows.host.HostFlowUtils.validateHostName;
|
||||||
import static google.registry.flows.host.HostFlowUtils.verifyDomainIsSameRegistrar;
|
import static google.registry.flows.host.HostFlowUtils.verifyDomainIsSameRegistrar;
|
||||||
import static google.registry.model.EppResourceUtils.createContactHostRoid;
|
import static google.registry.model.EppResourceUtils.createContactHostRoid;
|
||||||
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;
|
||||||
import static google.registry.util.CollectionUtils.isNullOrEmpty;
|
import static google.registry.util.CollectionUtils.isNullOrEmpty;
|
||||||
import static google.registry.util.CollectionUtils.union;
|
import static google.registry.util.CollectionUtils.union;
|
||||||
|
@ -33,7 +32,6 @@ import google.registry.flows.EppException;
|
||||||
import google.registry.flows.EppException.ParameterValueRangeErrorException;
|
import google.registry.flows.EppException.ParameterValueRangeErrorException;
|
||||||
import google.registry.flows.EppException.RequiredParameterMissingException;
|
import google.registry.flows.EppException.RequiredParameterMissingException;
|
||||||
import google.registry.flows.ExtensionManager;
|
import google.registry.flows.ExtensionManager;
|
||||||
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;
|
||||||
|
@ -42,7 +40,7 @@ import google.registry.model.domain.DomainResource;
|
||||||
import google.registry.model.domain.metadata.MetadataExtension;
|
import google.registry.model.domain.metadata.MetadataExtension;
|
||||||
import google.registry.model.eppinput.ResourceCommand;
|
import google.registry.model.eppinput.ResourceCommand;
|
||||||
import google.registry.model.eppoutput.CreateData.HostCreateData;
|
import google.registry.model.eppoutput.CreateData.HostCreateData;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.host.HostCommand.Create;
|
import google.registry.model.host.HostCommand.Create;
|
||||||
import google.registry.model.host.HostResource;
|
import google.registry.model.host.HostResource;
|
||||||
import google.registry.model.host.HostResource.Builder;
|
import google.registry.model.host.HostResource.Builder;
|
||||||
|
@ -51,6 +49,7 @@ 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;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An EPP flow that creates a new host.
|
* An EPP flow that creates a new host.
|
||||||
|
@ -70,7 +69,7 @@ import javax.inject.Inject;
|
||||||
* @error {@link SubordinateHostMustHaveIpException}
|
* @error {@link SubordinateHostMustHaveIpException}
|
||||||
* @error {@link UnexpectedExternalHostIpException}
|
* @error {@link UnexpectedExternalHostIpException}
|
||||||
*/
|
*/
|
||||||
public final class HostCreateFlow extends Flow implements TransactionalFlow {
|
public final class HostCreateFlow implements TransactionalFlow {
|
||||||
|
|
||||||
@Inject ResourceCommand resourceCommand;
|
@Inject ResourceCommand resourceCommand;
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
|
@ -78,14 +77,16 @@ public final class HostCreateFlow extends Flow implements TransactionalFlow {
|
||||||
@Inject @TargetId String targetId;
|
@Inject @TargetId String targetId;
|
||||||
@Inject HistoryEntry.Builder historyBuilder;
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
@Inject DnsQueue dnsQueue;
|
@Inject DnsQueue dnsQueue;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject HostCreateFlow() {}
|
@Inject HostCreateFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.register(MetadataExtension.class);
|
extensionManager.register(MetadataExtension.class);
|
||||||
extensionManager.validate();
|
extensionManager.validate();
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
Create command = (Create) resourceCommand;
|
Create command = (Create) resourceCommand;
|
||||||
|
DateTime now = ofy().getTransactionTime();
|
||||||
verifyResourceDoesNotExist(HostResource.class, targetId, now);
|
verifyResourceDoesNotExist(HostResource.class, targetId, now);
|
||||||
// The superordinate domain of the host object if creating an in-bailiwick host, or null if
|
// The superordinate domain of the host object if creating an in-bailiwick host, or null if
|
||||||
// creating an external host. This is looked up before we actually create the Host object so
|
// creating an external host. This is looked up before we actually create the Host object so
|
||||||
|
@ -130,7 +131,7 @@ public final class HostCreateFlow extends Flow implements TransactionalFlow {
|
||||||
dnsQueue.addHostRefreshTask(targetId);
|
dnsQueue.addHostRefreshTask(targetId);
|
||||||
}
|
}
|
||||||
ofy().save().entities(entitiesToSave);
|
ofy().save().entities(entitiesToSave);
|
||||||
return createOutput(SUCCESS, HostCreateData.create(targetId, now));
|
return responseBuilder.setResData(HostCreateData.create(targetId, now)).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Subordinate hosts must have an ip address. */
|
/** Subordinate hosts must have an ip address. */
|
||||||
|
|
|
@ -29,8 +29,8 @@ import com.google.common.collect.ImmutableSet;
|
||||||
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;
|
||||||
import google.registry.flows.Flow;
|
|
||||||
import google.registry.flows.FlowModule.ClientId;
|
import google.registry.flows.FlowModule.ClientId;
|
||||||
|
import google.registry.flows.FlowModule.Superuser;
|
||||||
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;
|
||||||
|
@ -38,10 +38,11 @@ import google.registry.model.domain.DomainBase;
|
||||||
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.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.host.HostResource;
|
import google.registry.model.host.HostResource;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An EPP flow that deletes a host.
|
* An EPP flow that deletes a host.
|
||||||
|
@ -57,7 +58,7 @@ import javax.inject.Inject;
|
||||||
* @error {@link google.registry.flows.exceptions.ResourceStatusProhibitsOperationException}
|
* @error {@link google.registry.flows.exceptions.ResourceStatusProhibitsOperationException}
|
||||||
* @error {@link google.registry.flows.exceptions.ResourceToDeleteIsReferencedException}
|
* @error {@link google.registry.flows.exceptions.ResourceToDeleteIsReferencedException}
|
||||||
*/
|
*/
|
||||||
public final class HostDeleteFlow extends Flow implements TransactionalFlow {
|
public final class HostDeleteFlow implements TransactionalFlow {
|
||||||
|
|
||||||
private static final ImmutableSet<StatusValue> DISALLOWED_STATUSES = ImmutableSet.of(
|
private static final ImmutableSet<StatusValue> DISALLOWED_STATUSES = ImmutableSet.of(
|
||||||
StatusValue.LINKED,
|
StatusValue.LINKED,
|
||||||
|
@ -76,15 +77,18 @@ public final class HostDeleteFlow extends Flow implements TransactionalFlow {
|
||||||
@Inject Optional<AuthInfo> authInfo;
|
@Inject Optional<AuthInfo> authInfo;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject @TargetId String targetId;
|
@Inject @TargetId String targetId;
|
||||||
|
@Inject @Superuser boolean isSuperuser;
|
||||||
@Inject HistoryEntry.Builder historyBuilder;
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
@Inject AsyncFlowEnqueuer asyncFlowEnqueuer;
|
@Inject AsyncFlowEnqueuer asyncFlowEnqueuer;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject HostDeleteFlow() {}
|
@Inject HostDeleteFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.register(MetadataExtension.class);
|
extensionManager.register(MetadataExtension.class);
|
||||||
extensionManager.validate();
|
extensionManager.validate();
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
|
DateTime now = ofy().getTransactionTime();
|
||||||
failfastForAsyncDelete(targetId, now, HostResource.class, GET_NAMESERVERS);
|
failfastForAsyncDelete(targetId, now, HostResource.class, GET_NAMESERVERS);
|
||||||
HostResource existingHost = loadAndVerifyExistence(HostResource.class, targetId, now);
|
HostResource existingHost = loadAndVerifyExistence(HostResource.class, targetId, now);
|
||||||
verifyNoDisallowedStatuses(existingHost, DISALLOWED_STATUSES);
|
verifyNoDisallowedStatuses(existingHost, DISALLOWED_STATUSES);
|
||||||
|
@ -100,6 +104,6 @@ public final class HostDeleteFlow extends Flow implements TransactionalFlow {
|
||||||
.setModificationTime(now)
|
.setModificationTime(now)
|
||||||
.setParent(Key.create(existingHost));
|
.setParent(Key.create(existingHost));
|
||||||
ofy().save().<Object>entities(newHost, historyBuilder.build());
|
ofy().save().<Object>entities(newHost, historyBuilder.build());
|
||||||
return createOutput(SUCCESS_WITH_ACTION_PENDING);
|
return responseBuilder.setResultFromCode(SUCCESS_WITH_ACTION_PENDING).build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@ import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
|
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
|
||||||
import static google.registry.model.EppResourceUtils.cloneResourceWithLinkedStatus;
|
import static google.registry.model.EppResourceUtils.cloneResourceWithLinkedStatus;
|
||||||
import static google.registry.model.eppoutput.Result.Code.SUCCESS;
|
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
import google.registry.flows.EppException;
|
import google.registry.flows.EppException;
|
||||||
|
@ -27,9 +26,11 @@ 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.model.eppcommon.AuthInfo;
|
import google.registry.model.eppcommon.AuthInfo;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.host.HostResource;
|
import google.registry.model.host.HostResource;
|
||||||
|
import google.registry.util.Clock;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An EPP flow that returns information about a host.
|
* An EPP flow that returns information about a host.
|
||||||
|
@ -39,20 +40,23 @@ import javax.inject.Inject;
|
||||||
*
|
*
|
||||||
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException}
|
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException}
|
||||||
*/
|
*/
|
||||||
public final class HostInfoFlow extends Flow {
|
public final class HostInfoFlow implements Flow {
|
||||||
|
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject @TargetId String targetId;
|
@Inject @TargetId String targetId;
|
||||||
@Inject Optional<AuthInfo> authInfo;
|
@Inject Optional<AuthInfo> authInfo;
|
||||||
|
@Inject Clock clock;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject HostInfoFlow() {}
|
@Inject HostInfoFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EppOutput run() throws EppException {
|
public EppResponse run() throws EppException {
|
||||||
extensionManager.validate(); // There are no legal extensions for this flow.
|
extensionManager.validate(); // There are no legal extensions for this flow.
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
|
DateTime now = clock.nowUtc();
|
||||||
HostResource host = loadAndVerifyExistence(HostResource.class, targetId, now);
|
HostResource host = loadAndVerifyExistence(HostResource.class, targetId, now);
|
||||||
verifyOptionalAuthInfoForResource(authInfo, host);
|
verifyOptionalAuthInfoForResource(authInfo, host);
|
||||||
return createOutput(SUCCESS, cloneResourceWithLinkedStatus(host, now));
|
return responseBuilder.setResData(cloneResourceWithLinkedStatus(host, now)).build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,6 @@ import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
|
||||||
import static google.registry.flows.host.HostFlowUtils.lookupSuperordinateDomain;
|
import static google.registry.flows.host.HostFlowUtils.lookupSuperordinateDomain;
|
||||||
import static google.registry.flows.host.HostFlowUtils.validateHostName;
|
import static google.registry.flows.host.HostFlowUtils.validateHostName;
|
||||||
import static google.registry.flows.host.HostFlowUtils.verifyDomainIsSameRegistrar;
|
import static google.registry.flows.host.HostFlowUtils.verifyDomainIsSameRegistrar;
|
||||||
import static google.registry.model.eppoutput.Result.Code.SUCCESS;
|
|
||||||
import static google.registry.model.index.ForeignKeyIndex.loadAndGetKey;
|
import static google.registry.model.index.ForeignKeyIndex.loadAndGetKey;
|
||||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
import static google.registry.util.CollectionUtils.isNullOrEmpty;
|
import static google.registry.util.CollectionUtils.isNullOrEmpty;
|
||||||
|
@ -41,8 +40,8 @@ import google.registry.flows.EppException.ParameterValueRangeErrorException;
|
||||||
import google.registry.flows.EppException.RequiredParameterMissingException;
|
import google.registry.flows.EppException.RequiredParameterMissingException;
|
||||||
import google.registry.flows.EppException.StatusProhibitsOperationException;
|
import google.registry.flows.EppException.StatusProhibitsOperationException;
|
||||||
import google.registry.flows.ExtensionManager;
|
import google.registry.flows.ExtensionManager;
|
||||||
import google.registry.flows.Flow;
|
|
||||||
import google.registry.flows.FlowModule.ClientId;
|
import google.registry.flows.FlowModule.ClientId;
|
||||||
|
import google.registry.flows.FlowModule.Superuser;
|
||||||
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;
|
||||||
|
@ -53,7 +52,7 @@ 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.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
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.AddRemove;
|
||||||
import google.registry.model.host.HostCommand.Update.Change;
|
import google.registry.model.host.HostCommand.Update.Change;
|
||||||
|
@ -62,6 +61,7 @@ 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;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An EPP flow that updates a host.
|
* An EPP flow that updates a host.
|
||||||
|
@ -91,7 +91,7 @@ import javax.inject.Inject;
|
||||||
* @error {@link RenameHostToExternalRemoveIpException}
|
* @error {@link RenameHostToExternalRemoveIpException}
|
||||||
* @error {@link RenameHostToSubordinateRequiresIpException}
|
* @error {@link RenameHostToSubordinateRequiresIpException}
|
||||||
*/
|
*/
|
||||||
public final class HostUpdateFlow extends Flow implements TransactionalFlow {
|
public final class HostUpdateFlow implements TransactionalFlow {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note that CLIENT_UPDATE_PROHIBITED is intentionally not in this list. This is because it
|
* Note that CLIENT_UPDATE_PROHIBITED is intentionally not in this list. This is because it
|
||||||
|
@ -107,19 +107,22 @@ public final class HostUpdateFlow extends Flow implements TransactionalFlow {
|
||||||
@Inject Optional<AuthInfo> authInfo;
|
@Inject Optional<AuthInfo> authInfo;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject @TargetId String targetId;
|
@Inject @TargetId String targetId;
|
||||||
|
@Inject @Superuser boolean isSuperuser;
|
||||||
@Inject HistoryEntry.Builder historyBuilder;
|
@Inject HistoryEntry.Builder historyBuilder;
|
||||||
@Inject AsyncFlowEnqueuer asyncFlowEnqueuer;
|
@Inject AsyncFlowEnqueuer asyncFlowEnqueuer;
|
||||||
@Inject DnsQueue dnsQueue;
|
@Inject DnsQueue dnsQueue;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject HostUpdateFlow() {}
|
@Inject HostUpdateFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.register(MetadataExtension.class);
|
extensionManager.register(MetadataExtension.class);
|
||||||
extensionManager.validate();
|
extensionManager.validate();
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
Update command = (Update) resourceCommand;
|
Update command = (Update) resourceCommand;
|
||||||
Change change = command.getInnerChange();
|
Change change = command.getInnerChange();
|
||||||
String suppliedNewHostName = change.getFullyQualifiedHostName();
|
String suppliedNewHostName = change.getFullyQualifiedHostName();
|
||||||
|
DateTime now = ofy().getTransactionTime();
|
||||||
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;
|
||||||
|
@ -169,7 +172,7 @@ public final class HostUpdateFlow extends Flow implements TransactionalFlow {
|
||||||
.setParent(Key.create(existingHost))
|
.setParent(Key.create(existingHost))
|
||||||
.build());
|
.build());
|
||||||
ofy().save().entities(entitiesToSave.build());
|
ofy().save().entities(entitiesToSave.build());
|
||||||
return createOutput(SUCCESS);
|
return responseBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void verifyUpdateAllowed(
|
private void verifyUpdateAllowed(
|
||||||
|
|
|
@ -91,7 +91,7 @@ import java.util.Set;
|
||||||
public class FlowPicker {
|
public class FlowPicker {
|
||||||
|
|
||||||
/** Marker class for unimplemented flows. */
|
/** Marker class for unimplemented flows. */
|
||||||
private abstract static class UnimplementedFlow extends Flow {}
|
private abstract static class UnimplementedFlow implements Flow {}
|
||||||
|
|
||||||
/** A function type that takes an {@link EppInput} and returns a {@link Flow} class. */
|
/** A function type that takes an {@link EppInput} and returns a {@link Flow} class. */
|
||||||
private abstract static class FlowProvider {
|
private abstract static class FlowProvider {
|
||||||
|
|
|
@ -17,7 +17,6 @@ package google.registry.flows.poll;
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||||
import static google.registry.flows.poll.PollFlowUtils.getPollMessagesQuery;
|
import static google.registry.flows.poll.PollFlowUtils.getPollMessagesQuery;
|
||||||
import static google.registry.model.eppoutput.Result.Code.SUCCESS;
|
|
||||||
import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_NO_MESSAGES;
|
import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_NO_MESSAGES;
|
||||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
import static google.registry.util.DateTimeUtils.isBeforeOrAt;
|
import static google.registry.util.DateTimeUtils.isBeforeOrAt;
|
||||||
|
@ -30,11 +29,10 @@ import google.registry.flows.EppException.ObjectDoesNotExistException;
|
||||||
import google.registry.flows.EppException.ParameterValueSyntaxErrorException;
|
import google.registry.flows.EppException.ParameterValueSyntaxErrorException;
|
||||||
import google.registry.flows.EppException.RequiredParameterMissingException;
|
import google.registry.flows.EppException.RequiredParameterMissingException;
|
||||||
import google.registry.flows.ExtensionManager;
|
import google.registry.flows.ExtensionManager;
|
||||||
import google.registry.flows.Flow;
|
|
||||||
import google.registry.flows.FlowModule.ClientId;
|
import google.registry.flows.FlowModule.ClientId;
|
||||||
import google.registry.flows.FlowModule.PollMessageId;
|
import google.registry.flows.FlowModule.PollMessageId;
|
||||||
import google.registry.flows.TransactionalFlow;
|
import google.registry.flows.TransactionalFlow;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.poll.MessageQueueInfo;
|
import google.registry.model.poll.MessageQueueInfo;
|
||||||
import google.registry.model.poll.PollMessage;
|
import google.registry.model.poll.PollMessage;
|
||||||
import google.registry.model.poll.PollMessageExternalKeyConverter;
|
import google.registry.model.poll.PollMessageExternalKeyConverter;
|
||||||
|
@ -55,15 +53,16 @@ import org.joda.time.DateTime;
|
||||||
* @error {@link PollAckFlow.MissingMessageIdException}
|
* @error {@link PollAckFlow.MissingMessageIdException}
|
||||||
* @error {@link PollAckFlow.NotAuthorizedToAckMessageException}
|
* @error {@link PollAckFlow.NotAuthorizedToAckMessageException}
|
||||||
*/
|
*/
|
||||||
public class PollAckFlow extends Flow implements TransactionalFlow {
|
public class PollAckFlow implements TransactionalFlow {
|
||||||
|
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject @PollMessageId String messageId;
|
@Inject @PollMessageId String messageId;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject PollAckFlow() {}
|
@Inject PollAckFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.validate(); // There are no legal extensions for this flow.
|
extensionManager.validate(); // There are no legal extensions for this flow.
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
if (messageId.isEmpty()) {
|
if (messageId.isEmpty()) {
|
||||||
|
@ -78,6 +77,8 @@ public class PollAckFlow extends Flow implements TransactionalFlow {
|
||||||
throw new InvalidMessageIdException(messageId);
|
throw new InvalidMessageIdException(messageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final DateTime now = ofy().getTransactionTime();
|
||||||
|
|
||||||
// Load the message to be acked. If a message is queued to be delivered in the future, we treat
|
// Load the message to be acked. If a message is queued to be delivered in the future, we treat
|
||||||
// it as if it doesn't exist yet.
|
// it as if it doesn't exist yet.
|
||||||
PollMessage pollMessage = ofy().load().key(pollMessageKey).now();
|
PollMessage pollMessage = ofy().load().key(pollMessageKey).now();
|
||||||
|
@ -128,17 +129,14 @@ public class PollAckFlow extends Flow implements TransactionalFlow {
|
||||||
messageCount--;
|
messageCount--;
|
||||||
}
|
}
|
||||||
if (messageCount <= 0) {
|
if (messageCount <= 0) {
|
||||||
return createOutput(SUCCESS_WITH_NO_MESSAGES);
|
return responseBuilder.setResultFromCode(SUCCESS_WITH_NO_MESSAGES).build();
|
||||||
}
|
}
|
||||||
return createOutput(
|
return responseBuilder
|
||||||
SUCCESS,
|
.setMessageQueueInfo(new MessageQueueInfo.Builder()
|
||||||
null, // responseData
|
.setQueueLength(messageCount)
|
||||||
null, // responseExtensions
|
.setMessageId(messageId)
|
||||||
MessageQueueInfo.create(
|
.build())
|
||||||
null, // eventTime
|
.build();
|
||||||
null, // msg
|
|
||||||
messageCount,
|
|
||||||
messageId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Registrar is not authorized to ack this message. */
|
/** Registrar is not authorized to ack this message. */
|
||||||
|
|
|
@ -27,11 +27,13 @@ import google.registry.flows.ExtensionManager;
|
||||||
import google.registry.flows.Flow;
|
import google.registry.flows.Flow;
|
||||||
import google.registry.flows.FlowModule.ClientId;
|
import google.registry.flows.FlowModule.ClientId;
|
||||||
import google.registry.flows.FlowModule.PollMessageId;
|
import google.registry.flows.FlowModule.PollMessageId;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.poll.MessageQueueInfo;
|
import google.registry.model.poll.MessageQueueInfo;
|
||||||
import google.registry.model.poll.PollMessage;
|
import google.registry.model.poll.PollMessage;
|
||||||
import google.registry.model.poll.PollMessageExternalKeyConverter;
|
import google.registry.model.poll.PollMessageExternalKeyConverter;
|
||||||
|
import google.registry.util.Clock;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An EPP flow for requesting {@link PollMessage}s.
|
* An EPP flow for requesting {@link PollMessage}s.
|
||||||
|
@ -44,34 +46,39 @@ import javax.inject.Inject;
|
||||||
*
|
*
|
||||||
* @error {@link PollRequestFlow.UnexpectedMessageIdException}
|
* @error {@link PollRequestFlow.UnexpectedMessageIdException}
|
||||||
*/
|
*/
|
||||||
public class PollRequestFlow extends Flow {
|
public class PollRequestFlow implements Flow {
|
||||||
|
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
@Inject @PollMessageId String messageId;
|
@Inject @PollMessageId String messageId;
|
||||||
|
@Inject Clock clock;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject PollRequestFlow() {}
|
@Inject PollRequestFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.validate(); // There are no legal extensions for this flow.
|
extensionManager.validate(); // There are no legal extensions for this flow.
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
if (!messageId.isEmpty()) {
|
if (!messageId.isEmpty()) {
|
||||||
throw new UnexpectedMessageIdException();
|
throw new UnexpectedMessageIdException();
|
||||||
}
|
}
|
||||||
// Return the oldest message from the queue.
|
// Return the oldest message from the queue.
|
||||||
|
DateTime now = clock.nowUtc();
|
||||||
PollMessage pollMessage = getPollMessagesQuery(clientId, now).first().now();
|
PollMessage pollMessage = getPollMessagesQuery(clientId, now).first().now();
|
||||||
if (pollMessage == null) {
|
if (pollMessage == null) {
|
||||||
return createOutput(SUCCESS_WITH_NO_MESSAGES);
|
return responseBuilder.setResultFromCode(SUCCESS_WITH_NO_MESSAGES).build();
|
||||||
}
|
}
|
||||||
return createOutput(
|
return responseBuilder
|
||||||
SUCCESS_WITH_ACK_MESSAGE,
|
.setResultFromCode(SUCCESS_WITH_ACK_MESSAGE)
|
||||||
forceEmptyToNull(pollMessage.getResponseData()),
|
.setMessageQueueInfo(new MessageQueueInfo.Builder()
|
||||||
forceEmptyToNull(pollMessage.getResponseExtensions()),
|
.setQueueDate(pollMessage.getEventTime())
|
||||||
MessageQueueInfo.create(
|
.setMsg(pollMessage.getMsg())
|
||||||
pollMessage.getEventTime(),
|
.setQueueLength(getPollMessagesQuery(clientId, now).count())
|
||||||
pollMessage.getMsg(),
|
.setMessageId(PollMessage.EXTERNAL_KEY_CONVERTER.convert(Key.create(pollMessage)))
|
||||||
getPollMessagesQuery(clientId, now).count(),
|
.build())
|
||||||
PollMessage.EXTERNAL_KEY_CONVERTER.convert(Key.create(pollMessage))));
|
.setMultipleResData(forceEmptyToNull(pollMessage.getResponseData()))
|
||||||
|
.setExtensions(forceEmptyToNull(pollMessage.getResponseExtensions()))
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Unexpected message id. */
|
/** Unexpected message id. */
|
||||||
|
|
|
@ -17,19 +17,20 @@ package google.registry.flows.session;
|
||||||
import google.registry.flows.EppException;
|
import google.registry.flows.EppException;
|
||||||
import google.registry.flows.ExtensionManager;
|
import google.registry.flows.ExtensionManager;
|
||||||
import google.registry.flows.Flow;
|
import google.registry.flows.Flow;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
|
||||||
import google.registry.model.eppoutput.Greeting;
|
import google.registry.model.eppoutput.Greeting;
|
||||||
|
import google.registry.util.Clock;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
/** A flow for an Epp "hello". */
|
/** A flow for an Epp "hello". */
|
||||||
public class HelloFlow extends Flow {
|
public class HelloFlow implements Flow {
|
||||||
|
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
|
@Inject Clock clock;
|
||||||
@Inject HelloFlow() {}
|
@Inject HelloFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EppOutput run() throws EppException {
|
public Greeting run() throws EppException {
|
||||||
extensionManager.validate(); // There are no legal extensions for this flow.
|
extensionManager.validate(); // There are no legal extensions for this flow.
|
||||||
return EppOutput.create(Greeting.create(now));
|
return Greeting.create(clock.nowUtc());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,13 +30,15 @@ import google.registry.flows.EppException.UnimplementedOptionException;
|
||||||
import google.registry.flows.ExtensionManager;
|
import google.registry.flows.ExtensionManager;
|
||||||
import google.registry.flows.Flow;
|
import google.registry.flows.Flow;
|
||||||
import google.registry.flows.FlowModule.ClientId;
|
import google.registry.flows.FlowModule.ClientId;
|
||||||
|
import google.registry.flows.SessionMetadata;
|
||||||
|
import google.registry.flows.TransportCredentials;
|
||||||
import google.registry.model.eppcommon.ProtocolDefinition;
|
import google.registry.model.eppcommon.ProtocolDefinition;
|
||||||
import google.registry.model.eppcommon.ProtocolDefinition.ServiceExtension;
|
import google.registry.model.eppcommon.ProtocolDefinition.ServiceExtension;
|
||||||
|
import google.registry.model.eppinput.EppInput;
|
||||||
import google.registry.model.eppinput.EppInput.Login;
|
import google.registry.model.eppinput.EppInput.Login;
|
||||||
import google.registry.model.eppinput.EppInput.Options;
|
import google.registry.model.eppinput.EppInput.Options;
|
||||||
import google.registry.model.eppinput.EppInput.Services;
|
import google.registry.model.eppinput.EppInput.Services;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.eppoutput.Result.Code;
|
|
||||||
import google.registry.model.registrar.Registrar;
|
import google.registry.model.registrar.Registrar;
|
||||||
import google.registry.util.FormattingLogger;
|
import google.registry.util.FormattingLogger;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -62,7 +64,7 @@ import javax.inject.Inject;
|
||||||
* @error {@link LoginFlow.RegistrarAccountNotActiveException}
|
* @error {@link LoginFlow.RegistrarAccountNotActiveException}
|
||||||
* @error {@link LoginFlow.UnsupportedLanguageException}
|
* @error {@link LoginFlow.UnsupportedLanguageException}
|
||||||
*/
|
*/
|
||||||
public class LoginFlow extends Flow {
|
public class LoginFlow implements Flow {
|
||||||
|
|
||||||
private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass();
|
private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass();
|
||||||
|
|
||||||
|
@ -70,12 +72,16 @@ public class LoginFlow extends Flow {
|
||||||
private static final int MAX_FAILED_LOGIN_ATTEMPTS_PER_CONNECTION = 3;
|
private static final int MAX_FAILED_LOGIN_ATTEMPTS_PER_CONNECTION = 3;
|
||||||
|
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
|
@Inject EppInput eppInput;
|
||||||
|
@Inject SessionMetadata sessionMetadata;
|
||||||
|
@Inject TransportCredentials credentials;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject LoginFlow() {}
|
@Inject LoginFlow() {}
|
||||||
|
|
||||||
/** Run the flow and log errors. */
|
/** Run the flow and log errors. */
|
||||||
@Override
|
@Override
|
||||||
public final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
try {
|
try {
|
||||||
return runWithoutLogging();
|
return runWithoutLogging();
|
||||||
} catch (EppException e) {
|
} catch (EppException e) {
|
||||||
|
@ -85,7 +91,7 @@ public class LoginFlow extends Flow {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Run the flow without bothering to log errors. The {@link #run} method will do that for us. */
|
/** Run the flow without bothering to log errors. The {@link #run} method will do that for us. */
|
||||||
public final EppOutput runWithoutLogging() throws EppException {
|
public final EppResponse runWithoutLogging() throws EppException {
|
||||||
extensionManager.validate(); // There are no legal extensions for this flow.
|
extensionManager.validate(); // There are no legal extensions for this flow.
|
||||||
Login login = (Login) eppInput.getCommandWrapper().getCommand();
|
Login login = (Login) eppInput.getCommandWrapper().getCommand();
|
||||||
if (!clientId.isEmpty()) {
|
if (!clientId.isEmpty()) {
|
||||||
|
@ -137,7 +143,7 @@ public class LoginFlow extends Flow {
|
||||||
sessionMetadata.resetFailedLoginAttempts();
|
sessionMetadata.resetFailedLoginAttempts();
|
||||||
sessionMetadata.setClientId(login.getClientId());
|
sessionMetadata.setClientId(login.getClientId());
|
||||||
sessionMetadata.setServiceExtensionUris(serviceExtensionUrisBuilder.build());
|
sessionMetadata.setServiceExtensionUris(serviceExtensionUrisBuilder.build());
|
||||||
return createOutput(Code.SUCCESS);
|
return responseBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Registrar with this client ID could not be found. */
|
/** Registrar with this client ID could not be found. */
|
||||||
|
|
|
@ -21,7 +21,8 @@ import google.registry.flows.EppException;
|
||||||
import google.registry.flows.ExtensionManager;
|
import google.registry.flows.ExtensionManager;
|
||||||
import google.registry.flows.Flow;
|
import google.registry.flows.Flow;
|
||||||
import google.registry.flows.FlowModule.ClientId;
|
import google.registry.flows.FlowModule.ClientId;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.flows.SessionMetadata;
|
||||||
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,17 +30,19 @@ import javax.inject.Inject;
|
||||||
*
|
*
|
||||||
* @error {@link google.registry.flows.FlowUtils.NotLoggedInException}
|
* @error {@link google.registry.flows.FlowUtils.NotLoggedInException}
|
||||||
*/
|
*/
|
||||||
public class LogoutFlow extends Flow {
|
public class LogoutFlow implements Flow {
|
||||||
|
|
||||||
@Inject ExtensionManager extensionManager;
|
@Inject ExtensionManager extensionManager;
|
||||||
@Inject @ClientId String clientId;
|
@Inject @ClientId String clientId;
|
||||||
|
@Inject SessionMetadata sessionMetadata;
|
||||||
|
@Inject EppResponse.Builder responseBuilder;
|
||||||
@Inject LogoutFlow() {}
|
@Inject LogoutFlow() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final EppOutput run() throws EppException {
|
public final EppResponse run() throws EppException {
|
||||||
extensionManager.validate(); // There are no legal extensions for this flow.
|
extensionManager.validate(); // There are no legal extensions for this flow.
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
sessionMetadata.invalidate();
|
sessionMetadata.invalidate();
|
||||||
return createOutput(SUCCESS_AND_CLOSE);
|
return responseBuilder.setResultFromCode(SUCCESS_AND_CLOSE).build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,6 +197,10 @@ public class EppResponse extends ImmutableObject implements ResponseOrGreeting {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder setResultFromCode(Result.Code resultCode) {
|
||||||
|
return setResult(Result.create(resultCode));
|
||||||
|
}
|
||||||
|
|
||||||
public Builder setResult(Result result) {
|
public Builder setResult(Result result) {
|
||||||
getInstance().result = result;
|
getInstance().result = result;
|
||||||
return this;
|
return this;
|
||||||
|
@ -207,11 +211,19 @@ public class EppResponse extends ImmutableObject implements ResponseOrGreeting {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setResData(@Nullable ImmutableList<? extends ResponseData> resData) {
|
public Builder setResData(ResponseData onlyResData) {
|
||||||
|
return setMultipleResData(ImmutableList.of(onlyResData));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setMultipleResData(@Nullable ImmutableList<? extends ResponseData> resData) {
|
||||||
getInstance().resData = resData;
|
getInstance().resData = resData;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder setOnlyExtension(ResponseExtension onlyExtension) {
|
||||||
|
return setExtensions(ImmutableList.of(onlyExtension));
|
||||||
|
}
|
||||||
|
|
||||||
public Builder setExtensions(@Nullable ImmutableList<? extends ResponseExtension> extensions) {
|
public Builder setExtensions(@Nullable ImmutableList<? extends ResponseExtension> extensions) {
|
||||||
getInstance().extensions = extensions;
|
getInstance().extensions = extensions;
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -14,10 +14,11 @@
|
||||||
|
|
||||||
package google.registry.model.poll;
|
package google.registry.model.poll;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import google.registry.model.Buildable;
|
||||||
import google.registry.model.ImmutableObject;
|
import google.registry.model.ImmutableObject;
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import javax.xml.bind.annotation.XmlAttribute;
|
import javax.xml.bind.annotation.XmlAttribute;
|
||||||
import javax.xml.bind.annotation.XmlElement;
|
import javax.xml.bind.annotation.XmlElement;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
|
@ -40,32 +41,34 @@ public class MessageQueueInfo extends ImmutableObject {
|
||||||
@XmlAttribute(name = "id")
|
@XmlAttribute(name = "id")
|
||||||
String messageId;
|
String messageId;
|
||||||
|
|
||||||
public DateTime getQueueDate() {
|
/** A builder for constructing a {@link MessageQueueInfo}, since it's immutable. */
|
||||||
return queueDate;
|
public static class Builder extends Buildable.Builder<MessageQueueInfo> {
|
||||||
}
|
public Builder setQueueDate(DateTime queueDate) {
|
||||||
|
getInstance().queueDate = queueDate;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public String getMsg() {
|
public Builder setMsg(String msg) {
|
||||||
return msg;
|
getInstance().msg = msg;
|
||||||
}
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public Integer getQueueLength() {
|
public Builder setQueueLength(int queueLength) {
|
||||||
return queueLength;
|
checkArgument(queueLength >= 0);
|
||||||
}
|
getInstance().queueLength = queueLength;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public String getMessageId() {
|
public Builder setMessageId(String messageId) {
|
||||||
return messageId;
|
getInstance().messageId = messageId;
|
||||||
}
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public static MessageQueueInfo create(
|
@Override
|
||||||
@Nullable DateTime queueDate,
|
public MessageQueueInfo build() {
|
||||||
@Nullable String msg,
|
checkNotNull(getInstance().messageId);
|
||||||
Integer queueLength,
|
checkNotNull(getInstance().queueLength);
|
||||||
String messageId) {
|
return super.build();
|
||||||
MessageQueueInfo instance = new MessageQueueInfo();
|
}
|
||||||
instance.queueDate = queueDate;
|
|
||||||
instance.msg = msg;
|
|
||||||
instance.queueLength = checkNotNull(queueLength);
|
|
||||||
instance.messageId = checkNotNull(messageId);
|
|
||||||
return instance;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@ import static com.google.common.truth.Truth.assertThat;
|
||||||
import static google.registry.testing.TestDataHelper.loadFileWithSubstitutions;
|
import static google.registry.testing.TestDataHelper.loadFileWithSubstitutions;
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
import com.google.appengine.api.users.User;
|
import com.google.appengine.api.users.User;
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
|
@ -31,8 +30,6 @@ import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.testing.TestLogHandler;
|
import com.google.common.testing.TestLogHandler;
|
||||||
import google.registry.model.eppcommon.Trid;
|
import google.registry.model.eppcommon.Trid;
|
||||||
import google.registry.model.eppinput.EppInput;
|
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
|
||||||
import google.registry.model.eppoutput.EppResponse;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.monitoring.whitebox.EppMetric;
|
import google.registry.monitoring.whitebox.EppMetric;
|
||||||
import google.registry.testing.AppEngineRule;
|
import google.registry.testing.AppEngineRule;
|
||||||
|
@ -66,27 +63,23 @@ public class FlowRunnerTest extends ShardableTestCase {
|
||||||
public void before() {
|
public void before() {
|
||||||
Logger.getLogger(FlowRunner.class.getCanonicalName()).addHandler(handler);
|
Logger.getLogger(FlowRunner.class.getCanonicalName()).addHandler(handler);
|
||||||
|
|
||||||
final EppOutput eppOutput = mock(EppOutput.class);
|
final EppResponse eppResponse = mock(EppResponse.class);
|
||||||
EppResponse eppResponse = mock(EppResponse.class);
|
|
||||||
when(eppOutput.getResponse()).thenReturn(eppResponse);
|
|
||||||
|
|
||||||
flowRunner.clientId = "TheRegistrar";
|
flowRunner.clientId = "TheRegistrar";
|
||||||
flowRunner.clock = new FakeClock();
|
|
||||||
flowRunner.credentials = new PasswordOnlyTransportCredentials();
|
flowRunner.credentials = new PasswordOnlyTransportCredentials();
|
||||||
flowRunner.eppInput = new EppInput();
|
|
||||||
flowRunner.eppRequestSource = EppRequestSource.UNIT_TEST;
|
flowRunner.eppRequestSource = EppRequestSource.UNIT_TEST;
|
||||||
flowRunner.flowProvider =
|
flowRunner.flowProvider =
|
||||||
Providers.<Flow>of(
|
Providers.<Flow>of(
|
||||||
new Flow() {
|
new Flow() {
|
||||||
@Override
|
@Override
|
||||||
protected EppOutput run() {
|
public EppResponse run() {
|
||||||
return eppOutput;
|
return eppResponse;
|
||||||
}});
|
}});
|
||||||
flowRunner.inputXmlBytes = "<xml/>".getBytes(UTF_8);
|
flowRunner.inputXmlBytes = "<xml/>".getBytes(UTF_8);
|
||||||
flowRunner.isDryRun = false;
|
flowRunner.isDryRun = false;
|
||||||
flowRunner.isSuperuser = false;
|
flowRunner.isSuperuser = false;
|
||||||
flowRunner.isTransactional = false;
|
flowRunner.isTransactional = false;
|
||||||
flowRunner.metric = EppMetric.builderForRequest("request-id-1", flowRunner.clock);
|
flowRunner.metric = EppMetric.builderForRequest("request-id-1", new FakeClock());
|
||||||
flowRunner.sessionMetadata =
|
flowRunner.sessionMetadata =
|
||||||
new StatelessRequestSessionMetadata("TheRegistrar", ImmutableSet.<String>of());
|
new StatelessRequestSessionMetadata("TheRegistrar", ImmutableSet.<String>of());
|
||||||
flowRunner.trid = Trid.create("client-123", "server-456");
|
flowRunner.trid = Trid.create("client-123", "server-456");
|
||||||
|
|
|
@ -52,7 +52,6 @@ import google.registry.model.eppcommon.StatusValue;
|
||||||
import google.registry.model.eppcommon.Trid;
|
import google.registry.model.eppcommon.Trid;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppOutput;
|
||||||
import google.registry.model.eppoutput.EppResponse;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.eppoutput.Result;
|
|
||||||
import google.registry.model.eppoutput.Result.Code;
|
import google.registry.model.eppoutput.Result.Code;
|
||||||
import google.registry.model.host.HostResource;
|
import google.registry.model.host.HostResource;
|
||||||
import google.registry.model.ofy.RequestCapturingAsyncDatastoreService;
|
import google.registry.model.ofy.RequestCapturingAsyncDatastoreService;
|
||||||
|
@ -443,8 +442,8 @@ public class DomainResourceTest extends EntityTestCase {
|
||||||
int numPreviousReads = RequestCapturingAsyncDatastoreService.getReads().size();
|
int numPreviousReads = RequestCapturingAsyncDatastoreService.getReads().size();
|
||||||
EppXmlTransformer.marshal(
|
EppXmlTransformer.marshal(
|
||||||
EppOutput.create(new EppResponse.Builder()
|
EppOutput.create(new EppResponse.Builder()
|
||||||
.setResult(Result.create(Code.SUCCESS))
|
.setResultFromCode(Code.SUCCESS)
|
||||||
.setResData(ImmutableList.of(domain))
|
.setResData(domain)
|
||||||
.setTrid(Trid.create(null, "abc"))
|
.setTrid(Trid.create(null, "abc"))
|
||||||
.build()),
|
.build()),
|
||||||
ValidationMode.STRICT);
|
ValidationMode.STRICT);
|
||||||
|
|
|
@ -1,48 +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.model.poll;
|
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
|
||||||
|
|
||||||
import com.google.common.testing.NullPointerTester;
|
|
||||||
import com.google.common.testing.NullPointerTester.Visibility;
|
|
||||||
import org.joda.time.DateTime;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runners.JUnit4;
|
|
||||||
|
|
||||||
/** Unit tests for {@link MessageQueueInfo}. */
|
|
||||||
@RunWith(JUnit4.class)
|
|
||||||
public final class MessageQueueInfoTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDeadCodeWeDontWantToDelete() throws Exception {
|
|
||||||
MessageQueueInfo mp = new MessageQueueInfo();
|
|
||||||
mp.queueDate = DateTime.parse("1984-12-18TZ");
|
|
||||||
assertThat(mp.getQueueDate()).isEqualTo(DateTime.parse("1984-12-18TZ"));
|
|
||||||
mp.msg = "sloth";
|
|
||||||
assertThat(mp.getMsg()).isEqualTo("sloth");
|
|
||||||
mp.queueLength = 123;
|
|
||||||
assertThat(mp.getQueueLength()).isEqualTo(123);
|
|
||||||
mp.messageId = "adorable";
|
|
||||||
assertThat(mp.getMessageId()).isEqualTo("adorable");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testNullness() {
|
|
||||||
NullPointerTester tester = new NullPointerTester();
|
|
||||||
tester.testStaticMethods(MessageQueueInfo.class, Visibility.PROTECTED);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -17,7 +17,6 @@ package google.registry.model.translators;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import google.registry.flows.EppXmlTransformer;
|
import google.registry.flows.EppXmlTransformer;
|
||||||
import google.registry.model.eppcommon.StatusValue;
|
import google.registry.model.eppcommon.StatusValue;
|
||||||
|
@ -51,9 +50,9 @@ public class StatusValueAdapterTest {
|
||||||
String marshalled = new String(
|
String marshalled = new String(
|
||||||
EppXmlTransformer.marshal(
|
EppXmlTransformer.marshal(
|
||||||
EppOutput.create(new EppResponse.Builder()
|
EppOutput.create(new EppResponse.Builder()
|
||||||
.setResData(ImmutableList.of(new HostResource.Builder()
|
.setResData(new HostResource.Builder()
|
||||||
.addStatusValue(StatusValue.CLIENT_UPDATE_PROHIBITED)
|
.addStatusValue(StatusValue.CLIENT_UPDATE_PROHIBITED)
|
||||||
.build()))
|
.build())
|
||||||
.build()),
|
.build()),
|
||||||
ValidationMode.LENIENT),
|
ValidationMode.LENIENT),
|
||||||
UTF_8);
|
UTF_8);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue