Remove LoggedInFlow

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=137444791
This commit is contained in:
cgoldfeder 2016-10-27 14:52:50 -07:00 committed by Ben McIlwain
parent 8b068250d6
commit b84d7f1fb5
50 changed files with 763 additions and 429 deletions

View file

@ -0,0 +1,163 @@
// Copyright 2016 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.flows;
import static com.google.common.collect.Sets.difference;
import static com.google.common.collect.Sets.intersection;
import static google.registry.model.domain.fee.Fee.FEE_EXTENSION_URIS;
import static google.registry.model.eppcommon.ProtocolDefinition.ServiceExtension.getCommandExtensionUri;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableSet;
import google.registry.flows.EppException.CommandUseErrorException;
import google.registry.flows.EppException.SyntaxErrorException;
import google.registry.flows.EppException.UnimplementedExtensionException;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.exceptions.OnlyToolCanPassMetadataException;
import google.registry.model.domain.metadata.MetadataExtension;
import google.registry.model.eppinput.EppInput;
import google.registry.model.eppinput.EppInput.CommandExtension;
import google.registry.util.FormattingLogger;
import java.util.Collection;
import java.util.Set;
import javax.inject.Inject;
/**
* Helper to validate extensions on an EPP command.
*
* <p>This class checks that the declared extension URIs in an EPP request as well as the actually
* supplied extensions in the XML are compatible with the extensions supported by a flow.
*/
public final class ExtensionManager {
private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass();
/** Blacklist of extension URIs that cause an error if they are used without being declared. */
private static final ImmutableSet<String> UNDECLARED_URIS_BLACKLIST = FEE_EXTENSION_URIS;
private final ImmutableSet.Builder<Class<? extends CommandExtension>> implementedBuilder =
new ImmutableSet.Builder<>();
private final ImmutableSet.Builder<ImmutableSet<?>> implementedGroupsBuilder =
new ImmutableSet.Builder<>();
@Inject EppInput eppInput;
@Inject SessionMetadata sessionMetadata;
@Inject @ClientId String clientId;
@Inject Class<? extends Flow> flowClass;
@Inject EppRequestSource eppRequestSource;
@Inject ExtensionManager() {}
@SafeVarargs
public final void register(Class<? extends CommandExtension>... extension) {
implementedBuilder.add(extension);
}
public <T extends CommandExtension> void registerAsGroup(
Collection<Class<? extends T>> extensions) {
implementedBuilder.addAll(extensions);
implementedGroupsBuilder.add(ImmutableSet.copyOf(extensions));
}
public void validate() throws EppException {
ImmutableSet.Builder<Class<? extends CommandExtension>> suppliedBuilder =
new ImmutableSet.Builder<>();
for (CommandExtension extension : eppInput.getCommandWrapper().getExtensions()) {
suppliedBuilder.add(extension.getClass());
}
ImmutableSet<Class<? extends CommandExtension>> suppliedExtensions = suppliedBuilder.build();
ImmutableSet<Class<? extends CommandExtension>> implementedExtensions =
implementedBuilder.build();
ImmutableSet<ImmutableSet<?>> implementedExtensionGroups =
implementedGroupsBuilder.build();
checkForDuplicateExtensions(suppliedExtensions, implementedExtensionGroups);
checkForUndeclaredExtensions(suppliedExtensions);
checkForRestrictedExtensions(suppliedExtensions);
checkForUnimplementedExtensions(suppliedExtensions, implementedExtensions);
}
private void checkForDuplicateExtensions(
ImmutableSet<Class<? extends CommandExtension>> suppliedExtensions,
ImmutableSet<ImmutableSet<?>> implementedExtensionGroups)
throws UnsupportedRepeatedExtensionException {
if (suppliedExtensions.size() < eppInput.getCommandWrapper().getExtensions().size()) {
throw new UnsupportedRepeatedExtensionException();
}
// No more than one extension in an extension group can be present.
for (ImmutableSet<?> group : implementedExtensionGroups) {
if (intersection(suppliedExtensions, group).size() > 1) {
throw new UnsupportedRepeatedExtensionException();
}
}
}
private void checkForUndeclaredExtensions(
ImmutableSet<Class<? extends CommandExtension>> suppliedExtensions)
throws UndeclaredServiceExtensionException {
ImmutableSet.Builder<String> suppliedUris = new ImmutableSet.Builder<>();
for (Class<? extends CommandExtension> extension : suppliedExtensions) {
suppliedUris.add(getCommandExtensionUri(extension));
}
Set<String> declaredUris = sessionMetadata.getServiceExtensionUris();
Set<String> undeclaredUris = difference(suppliedUris.build(), declaredUris);
if (undeclaredUris.isEmpty()) {
return;
}
Set<String> undeclaredUrisThatError = intersection(undeclaredUris, UNDECLARED_URIS_BLACKLIST);
if (!undeclaredUrisThatError.isEmpty()) {
throw new UndeclaredServiceExtensionException(undeclaredUrisThatError);
}
logger.infofmt(
"Client %s is attempting to run %s without declaring URIs %s on login",
clientId,
flowClass.getSimpleName(),
undeclaredUris);
}
private void checkForRestrictedExtensions(
ImmutableSet<Class<? extends CommandExtension>> suppliedExtensions)
throws OnlyToolCanPassMetadataException {
if (suppliedExtensions.contains(MetadataExtension.class)
&& !eppRequestSource.equals(EppRequestSource.TOOL)) {
throw new OnlyToolCanPassMetadataException();
}
}
private void checkForUnimplementedExtensions(
ImmutableSet<Class<? extends CommandExtension>> suppliedExtensions,
ImmutableSet<Class<? extends CommandExtension>> implementedExtensions)
throws UnimplementedExtensionException {
Set<Class<? extends CommandExtension>> unimplementedExtensions =
difference(suppliedExtensions, implementedExtensions);
if (!unimplementedExtensions.isEmpty()) {
logger.infofmt("Unimplemented extensions: %s", unimplementedExtensions);
throw new UnimplementedExtensionException();
}
}
/** Unsupported repetition of an extension. */
static class UnsupportedRepeatedExtensionException extends SyntaxErrorException {
public UnsupportedRepeatedExtensionException() {
super("Unsupported repetition of an extension");
}
}
/** Service extension(s) must be declared at login. */
public static class UndeclaredServiceExtensionException extends CommandUseErrorException {
public UndeclaredServiceExtensionException(Set<String> undeclaredUris) {
super(String.format("Service extension(s) must be declared at login: %s",
Joiner.on(", ").join(undeclaredUris)));
}
}
}

View file

@ -15,20 +15,14 @@
package google.registry.flows;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import google.registry.model.eppcommon.Trid;
import google.registry.model.eppinput.EppInput;
import google.registry.model.eppinput.EppInput.CommandExtension;
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 java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.annotation.Nullable;
import org.joda.time.DateTime;
@ -49,9 +43,6 @@ public abstract class Flow {
/** Whether this flow is being run in a superuser mode that can skip some checks. */
protected boolean isSuperuser;
/** The collection of allowed extensions for the flow. */
private Set<Class<? extends CommandExtension>> validExtensions = new HashSet<>();
/** Flows can override this for custom initialization. */
@SuppressWarnings("unused")
protected void initFlow() throws EppException {}
@ -107,27 +98,6 @@ public abstract class Flow {
this.now = now;
this.isSuperuser = isSuperuser;
initFlow();
validExtensions = ImmutableSet.copyOf(validExtensions);
return this;
}
/**
* Add an extension class as a valid extension for a flow.
* Must be called in the init series of methods, as the validExtensions
* becomes immutable once init is complete.
*/
@SafeVarargs
protected final void registerExtensions(Class<? extends CommandExtension>... extensions) {
Collections.addAll(validExtensions, extensions);
}
protected final <E extends CommandExtension>
void registerExtensions(List<Class<? extends E>> extensions) {
validExtensions.addAll(extensions);
}
/** Get the legal command extension types for this flow. */
protected final Set<Class<? extends CommandExtension>> getValidRequestExtensions() {
return ImmutableSet.copyOf(validExtensions);
}
}

View file

@ -21,7 +21,6 @@ import com.google.common.base.Optional;
import com.google.common.base.Strings;
import dagger.Module;
import dagger.Provides;
import google.registry.flows.exceptions.OnlyToolCanPassMetadataException;
import google.registry.flows.picker.FlowPicker;
import google.registry.model.domain.launch.ApplicationIdTargetExtension;
import google.registry.model.domain.metadata.MetadataExtension;
@ -230,7 +229,6 @@ public class FlowModule {
@InputXml byte[] inputXmlBytes,
@Superuser boolean isSuperuser,
@ClientId String clientId,
EppRequestSource eppRequestSource,
EppInput eppInput) {
HistoryEntry.Builder historyBuilder = new HistoryEntry.Builder()
.setTrid(trid)
@ -239,9 +237,6 @@ public class FlowModule {
.setClientId(clientId);
MetadataExtension metadataExtension = eppInput.getSingleExtension(MetadataExtension.class);
if (metadataExtension != null) {
if (!eppRequestSource.equals(EppRequestSource.TOOL)) {
throw new EppExceptionInProviderException(new OnlyToolCanPassMetadataException());
}
historyBuilder
.setReason(metadataExtension.getReason())
.setRequestedByRegistrar(metadataExtension.getRequestedByRegistrar());

View file

@ -0,0 +1,37 @@
// Copyright 2016 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.flows;
import google.registry.flows.EppException.CommandUseErrorException;
/** Static utility functions for flows. */
public final class FlowUtils {
private FlowUtils() {}
/** Validate that there is a logged in client. */
public static void validateClientIsLoggedIn(String clientId) throws EppException {
if (clientId.isEmpty()) {
throw new NotLoggedInException();
}
}
/** Registrar is not logged in. */
public static class NotLoggedInException extends CommandUseErrorException {
public NotLoggedInException() {
super("Registrar is not logged in.");
}
}
}

View file

@ -48,7 +48,7 @@ public class HttpSessionMetadata implements SessionMetadata {
@Override
@SuppressWarnings("unchecked")
public Set<String> getServiceExtensionUris() {
return (Set<String>) session.getAttribute(SERVICE_EXTENSIONS);
return nullToEmpty((Set<String>) session.getAttribute(SERVICE_EXTENSIONS));
}
@Override

View file

@ -1,140 +0,0 @@
// Copyright 2016 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.flows;
import static com.google.common.base.Verify.verifyNotNull;
import static com.google.common.collect.Sets.difference;
import static com.google.common.collect.Sets.intersection;
import static google.registry.model.domain.fee.Fee.FEE_EXTENSION_URIS;
import static google.registry.model.registry.Registries.getTlds;
import static google.registry.util.CollectionUtils.nullToEmpty;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableSet;
import google.registry.flows.EppException.CommandUseErrorException;
import google.registry.flows.EppException.SyntaxErrorException;
import google.registry.flows.EppException.UnimplementedExtensionException;
import google.registry.flows.FlowModule.ClientId;
import google.registry.model.eppcommon.ProtocolDefinition;
import google.registry.model.eppinput.EppInput.CommandExtension;
import google.registry.model.registrar.Registrar;
import google.registry.util.FormattingLogger;
import java.util.Set;
import javax.inject.Inject;
/** A flow that requires being logged in. */
public abstract class LoggedInFlow extends Flow {
static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass();
/**
* A blacklist of service extension URIs that will cause an error if they are used without being
* declared on login.
*/
private static final ImmutableSet<String> UNDECLARED_URIS_BLACKLIST = FEE_EXTENSION_URIS;
/**
* The TLDs on which the logged-in registrar is allowed access domains.
*/
private ImmutableSet<String> allowedTlds;
@Inject @ClientId String clientId;
protected ImmutableSet<String> getAllowedTlds() {
return allowedTlds;
}
@Override
public final void initFlow() throws EppException {
if (clientId.isEmpty()) {
throw new NotLoggedInException();
}
// Validate that the extensions in the input match what this flow expects.
ImmutableSet<Class<? extends CommandExtension>> extensionClasses = FluentIterable
.from(eppInput.getCommandWrapper().getExtensions())
.transform(new Function<CommandExtension, Class<? extends CommandExtension>>() {
@Override
public Class<? extends CommandExtension> apply(CommandExtension extension) {
return extension.getClass();
}})
.toSet();
if (extensionClasses.size() != eppInput.getCommandWrapper().getExtensions().size()) {
throw new UnsupportedRepeatedExtensionException();
}
// Validate that we did not receive any undeclared extensions.
ImmutableSet<String> extensionUris = FluentIterable
.from(extensionClasses)
.transform(new Function<Class<? extends CommandExtension>, String>() {
@Override
public String apply(Class<? extends CommandExtension> clazz) {
return ProtocolDefinition.ServiceExtension.getCommandExtensionUri(clazz);
}})
.toSet();
Set<String> undeclaredUris = difference(
extensionUris, nullToEmpty(sessionMetadata.getServiceExtensionUris()));
if (!undeclaredUris.isEmpty()) {
Set<String> undeclaredUrisThatError = intersection(undeclaredUris, UNDECLARED_URIS_BLACKLIST);
if (!undeclaredUrisThatError.isEmpty()) {
throw new UndeclaredServiceExtensionException(undeclaredUrisThatError);
} else {
logger.infofmt(
"Client (%s) is attempting to run flow (%s) without declaring URIs %s on login",
clientId, getClass().getSimpleName(), undeclaredUris);
}
}
if (isSuperuser) {
allowedTlds = getTlds();
} else {
Registrar registrar = verifyNotNull(
Registrar.loadByClientId(clientId),
"Could not load registrar %s", clientId);
allowedTlds = registrar.getAllowedTlds();
}
initLoggedInFlow();
Set<Class<? extends CommandExtension>> unimplementedExtensions =
difference(extensionClasses, getValidRequestExtensions());
if (!unimplementedExtensions.isEmpty()) {
logger.infofmt("Unimplemented extensions: %s", unimplementedExtensions);
throw new UnimplementedExtensionException();
}
}
@SuppressWarnings("unused")
protected void initLoggedInFlow() throws EppException {}
/** Registrar is not logged in. */
public static class NotLoggedInException extends CommandUseErrorException {
public NotLoggedInException() {
super("Registrar is not logged in.");
}
}
/** Unsupported repetition of an extension. */
static class UnsupportedRepeatedExtensionException extends SyntaxErrorException {
public UnsupportedRepeatedExtensionException() {
super("Unsupported repetition of an extension");
}
}
/** Service extension(s) must be declared at login. */
public static class UndeclaredServiceExtensionException extends CommandUseErrorException {
public UndeclaredServiceExtensionException(Set<String> undeclaredUris) {
super(String.format("Service extension(s) must be declared at login: %s",
Joiner.on(", ").join(undeclaredUris)));
}
}
}

View file

@ -65,8 +65,10 @@ import java.util.List;
import java.util.Set;
import org.joda.time.DateTime;
/** Static utility functions for resource transfer flows. */
public class ResourceFlowUtils {
/** Static utility functions for resource flows. */
public final class ResourceFlowUtils {
private ResourceFlowUtils() {}
/** Statuses for which an exDate should be added to transfer responses. */
private static final ImmutableSet<TransferStatus> ADD_EXDATE_STATUSES = Sets.immutableEnumSet(

View file

@ -14,6 +14,7 @@
package google.registry.flows.contact;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.verifyTargetIdCount;
import static google.registry.model.EppResourceUtils.checkResourcesExist;
import static google.registry.model.eppoutput.Result.Code.SUCCESS;
@ -21,7 +22,9 @@ import static google.registry.model.eppoutput.Result.Code.SUCCESS;
import com.google.common.collect.ImmutableList;
import google.registry.config.ConfigModule.Config;
import google.registry.flows.EppException;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.model.contact.ContactCommand.Check;
import google.registry.model.contact.ContactResource;
import google.registry.model.eppinput.ResourceCommand;
@ -39,14 +42,18 @@ import javax.inject.Inject;
*
* @error {@link google.registry.flows.exceptions.TooManyResourceChecksException}
*/
public final class ContactCheckFlow extends LoggedInFlow {
public final class ContactCheckFlow extends Flow {
@Inject ResourceCommand resourceCommand;
@Inject @ClientId String clientId;
@Inject ExtensionManager extensionManager;
@Inject @Config("maxChecks") int maxChecks;
@Inject ContactCheckFlow() {}
@Override
public final EppOutput run() throws EppException {
extensionManager.validate(); // There are no legal extensions for this flow.
validateClientIsLoggedIn(clientId);
List<String> targetIds = ((Check) resourceCommand).getTargetIds();
verifyTargetIdCount(targetIds, maxChecks);
Set<String> existingIds = checkResourcesExist(ContactResource.class, targetIds, now);

View file

@ -14,6 +14,7 @@
package google.registry.flows.contact;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.verifyResourceDoesNotExist;
import static google.registry.flows.contact.ContactFlowUtils.validateAsciiPostalInfo;
import static google.registry.flows.contact.ContactFlowUtils.validateContactAgainstPolicy;
@ -23,9 +24,10 @@ import static google.registry.model.ofy.ObjectifyService.ofy;
import com.googlecode.objectify.Key;
import google.registry.flows.EppException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow;
import google.registry.model.contact.ContactCommand.Create;
import google.registry.model.contact.ContactResource;
@ -47,21 +49,20 @@ import javax.inject.Inject;
* @error {@link ContactFlowUtils.BadInternationalizedPostalInfoException}
* @error {@link ContactFlowUtils.DeclineContactDisclosureFieldDisallowedPolicyException}
*/
public final class ContactCreateFlow extends LoggedInFlow implements TransactionalFlow {
public final class ContactCreateFlow extends Flow implements TransactionalFlow {
@Inject ResourceCommand resourceCommand;
@Inject ExtensionManager extensionManager;
@Inject @ClientId String clientId;
@Inject @TargetId String targetId;
@Inject HistoryEntry.Builder historyBuilder;
@Inject ContactCreateFlow() {}
@Override
protected final void initLoggedInFlow() throws EppException {
registerExtensions(MetadataExtension.class);
}
@Override
protected final EppOutput run() throws EppException {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
Create command = (Create) resourceCommand;
verifyResourceDoesNotExist(ContactResource.class, targetId, now);
Builder builder = new Builder();

View file

@ -14,6 +14,7 @@
package google.registry.flows.contact;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.failfastForAsyncDelete;
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
@ -27,9 +28,10 @@ import com.google.common.base.Optional;
import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
import google.registry.flows.EppException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow;
import google.registry.flows.async.AsyncFlowEnqueuer;
import google.registry.model.contact.ContactResource;
@ -55,7 +57,7 @@ import javax.inject.Inject;
* @error {@link google.registry.flows.exceptions.ResourceStatusProhibitsOperationException}
* @error {@link google.registry.flows.exceptions.ResourceToDeleteIsReferencedException}
*/
public final class ContactDeleteFlow extends LoggedInFlow implements TransactionalFlow {
public final class ContactDeleteFlow extends Flow implements TransactionalFlow {
private static final ImmutableSet<StatusValue> DISALLOWED_STATUSES = ImmutableSet.of(
StatusValue.LINKED,
@ -70,20 +72,19 @@ public final class ContactDeleteFlow extends LoggedInFlow implements Transaction
return domain.getReferencedContacts();
}};
@Inject AsyncFlowEnqueuer asyncFlowEnqueuer;
@Inject ExtensionManager extensionManager;
@Inject @ClientId String clientId;
@Inject @TargetId String targetId;
@Inject Optional<AuthInfo> authInfo;
@Inject HistoryEntry.Builder historyBuilder;
@Inject AsyncFlowEnqueuer asyncFlowEnqueuer;
@Inject ContactDeleteFlow() {}
@Override
protected final void initLoggedInFlow() throws EppException {
registerExtensions(MetadataExtension.class);
}
@Override
public final EppOutput run() throws EppException {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
failfastForAsyncDelete(targetId, now, ContactResource.class, GET_REFERENCED_CONTACTS);
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
verifyNoDisallowedStatuses(existingContact, DISALLOWED_STATUSES);

View file

@ -14,6 +14,7 @@
package google.registry.flows.contact;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
import static google.registry.model.EppResourceUtils.cloneResourceWithLinkedStatus;
@ -21,9 +22,10 @@ import static google.registry.model.eppoutput.Result.Code.SUCCESS;
import com.google.common.base.Optional;
import google.registry.flows.EppException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow;
import google.registry.model.contact.ContactResource;
import google.registry.model.eppcommon.AuthInfo;
import google.registry.model.eppoutput.EppOutput;
@ -39,8 +41,9 @@ import javax.inject.Inject;
*
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException}
*/
public final class ContactInfoFlow extends LoggedInFlow {
public final class ContactInfoFlow extends Flow {
@Inject ExtensionManager extensionManager;
@Inject @ClientId String clientId;
@Inject @TargetId String targetId;
@Inject Optional<AuthInfo> authInfo;
@ -48,6 +51,8 @@ public final class ContactInfoFlow extends LoggedInFlow {
@Override
public final EppOutput run() throws EppException {
extensionManager.validate(); // There are no legal extensions for this flow.
validateClientIsLoggedIn(clientId);
ContactResource contact = loadAndVerifyExistence(ContactResource.class, targetId, now);
verifyOptionalAuthInfoForResource(authInfo, contact);
if (!clientId.equals(contact.getCurrentSponsorClientId()) && !authInfo.isPresent()) {

View file

@ -14,6 +14,7 @@
package google.registry.flows.contact;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.approvePendingTransfer;
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
@ -26,9 +27,10 @@ import static google.registry.model.ofy.ObjectifyService.ofy;
import com.google.common.base.Optional;
import com.googlecode.objectify.Key;
import google.registry.flows.EppException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow;
import google.registry.flows.exceptions.NotPendingTransferException;
import google.registry.model.contact.ContactResource;
@ -55,26 +57,25 @@ import javax.inject.Inject;
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException}
* @error {@link google.registry.flows.exceptions.NotPendingTransferException}
*/
public final class ContactTransferApproveFlow extends LoggedInFlow implements TransactionalFlow {
public final class ContactTransferApproveFlow extends Flow implements TransactionalFlow {
@Inject ResourceCommand resourceCommand;
@Inject ExtensionManager extensionManager;
@Inject @ClientId String clientId;
@Inject @TargetId String targetId;
@Inject Optional<AuthInfo> authInfo;
@Inject HistoryEntry.Builder historyBuilder;
@Inject ContactTransferApproveFlow() {}
@Override
protected final void initLoggedInFlow() throws EppException {
registerExtensions(MetadataExtension.class);
}
/**
* <p>The logic in this flow, which handles client approvals, very closely parallels the logic in
* {@link ContactResource#cloneProjectedAtTime} which handles implicit server approvals.
*/
@Override
public final EppOutput run() throws EppException {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
verifyOptionalAuthInfoForResource(authInfo, existingContact);
TransferData transferData = existingContact.getTransferData();

View file

@ -14,6 +14,7 @@
package google.registry.flows.contact;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.denyPendingTransfer;
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
@ -25,9 +26,10 @@ import static google.registry.model.ofy.ObjectifyService.ofy;
import com.google.common.base.Optional;
import com.googlecode.objectify.Key;
import google.registry.flows.EppException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow;
import google.registry.flows.exceptions.NotPendingTransferException;
import google.registry.flows.exceptions.NotTransferInitiatorException;
@ -55,22 +57,21 @@ import javax.inject.Inject;
* @error {@link google.registry.flows.exceptions.NotPendingTransferException}
* @error {@link google.registry.flows.exceptions.NotTransferInitiatorException}
*/
public final class ContactTransferCancelFlow extends LoggedInFlow implements TransactionalFlow {
public final class ContactTransferCancelFlow extends Flow implements TransactionalFlow {
@Inject ResourceCommand resourceCommand;
@Inject ExtensionManager extensionManager;
@Inject Optional<AuthInfo> authInfo;
@Inject @ClientId String clientId;
@Inject @TargetId String targetId;
@Inject HistoryEntry.Builder historyBuilder;
@Inject ContactTransferCancelFlow() {}
@Override
protected final void initLoggedInFlow() throws EppException {
registerExtensions(MetadataExtension.class);
}
@Override
protected final EppOutput run() throws EppException {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
verifyOptionalAuthInfoForResource(authInfo, existingContact);
TransferData transferData = existingContact.getTransferData();

View file

@ -14,6 +14,7 @@
package google.registry.flows.contact;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse;
@ -21,9 +22,10 @@ import static google.registry.model.eppoutput.Result.Code.SUCCESS;
import com.google.common.base.Optional;
import google.registry.flows.EppException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.exceptions.NoTransferHistoryToQueryException;
import google.registry.flows.exceptions.NotAuthorizedToViewTransferException;
import google.registry.model.contact.ContactResource;
@ -46,8 +48,9 @@ import javax.inject.Inject;
* @error {@link google.registry.flows.exceptions.NoTransferHistoryToQueryException}
* @error {@link google.registry.flows.exceptions.NotAuthorizedToViewTransferException}
*/
public final class ContactTransferQueryFlow extends LoggedInFlow {
public final class ContactTransferQueryFlow extends Flow {
@Inject ExtensionManager extensionManager;
@Inject Optional<AuthInfo> authInfo;
@Inject @ClientId String clientId;
@Inject @TargetId String targetId;
@ -55,6 +58,8 @@ public final class ContactTransferQueryFlow extends LoggedInFlow {
@Override
public final EppOutput run() throws EppException {
extensionManager.validate(); // There are no legal extensions for this flow.
validateClientIsLoggedIn(clientId);
ContactResource contact = loadAndVerifyExistence(ContactResource.class, targetId, now);
verifyOptionalAuthInfoForResource(authInfo, contact);
// Most of the fields on the transfer response are required, so there's no way to return valid

View file

@ -14,6 +14,7 @@
package google.registry.flows.contact;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.denyPendingTransfer;
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
@ -26,9 +27,10 @@ import static google.registry.model.ofy.ObjectifyService.ofy;
import com.google.common.base.Optional;
import com.googlecode.objectify.Key;
import google.registry.flows.EppException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow;
import google.registry.flows.exceptions.NotPendingTransferException;
import google.registry.model.contact.ContactResource;
@ -54,21 +56,20 @@ import javax.inject.Inject;
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException}
* @error {@link google.registry.flows.exceptions.NotPendingTransferException}
*/
public final class ContactTransferRejectFlow extends LoggedInFlow implements TransactionalFlow {
public final class ContactTransferRejectFlow extends Flow implements TransactionalFlow {
@Inject ExtensionManager extensionManager;
@Inject Optional<AuthInfo> authInfo;
@Inject @ClientId String clientId;
@Inject @TargetId String targetId;
@Inject HistoryEntry.Builder historyBuilder;
@Inject ContactTransferRejectFlow() {}
@Override
protected final void initLoggedInFlow() throws EppException {
registerExtensions(MetadataExtension.class);
}
@Override
protected final EppOutput run() throws EppException {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
verifyOptionalAuthInfoForResource(authInfo, existingContact);
TransferData transferData = existingContact.getTransferData();

View file

@ -14,6 +14,7 @@
package google.registry.flows.contact;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
import static google.registry.flows.ResourceFlowUtils.verifyRequiredAuthInfoForResourceTransfer;
@ -28,9 +29,10 @@ import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
import google.registry.config.ConfigModule.Config;
import google.registry.flows.EppException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow;
import google.registry.flows.exceptions.AlreadyPendingTransferException;
import google.registry.flows.exceptions.ObjectAlreadySponsoredException;
@ -62,13 +64,14 @@ import org.joda.time.Duration;
* @error {@link google.registry.flows.exceptions.MissingTransferRequestAuthInfoException}
* @error {@link google.registry.flows.exceptions.ObjectAlreadySponsoredException}
*/
public final class ContactTransferRequestFlow extends LoggedInFlow implements TransactionalFlow {
public final class ContactTransferRequestFlow extends Flow implements TransactionalFlow {
private static final ImmutableSet<StatusValue> DISALLOWED_STATUSES = ImmutableSet.of(
StatusValue.CLIENT_TRANSFER_PROHIBITED,
StatusValue.PENDING_DELETE,
StatusValue.SERVER_TRANSFER_PROHIBITED);
@Inject ExtensionManager extensionManager;
@Inject Optional<AuthInfo> authInfo;
@Inject @ClientId String gainingClientId;
@Inject @TargetId String targetId;
@ -76,13 +79,11 @@ public final class ContactTransferRequestFlow extends LoggedInFlow implements Tr
@Inject HistoryEntry.Builder historyBuilder;
@Inject ContactTransferRequestFlow() {}
@Override
protected final void initLoggedInFlow() throws EppException {
registerExtensions(MetadataExtension.class);
}
@Override
protected final EppOutput run() throws EppException {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateClientIsLoggedIn(gainingClientId);
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
verifyRequiredAuthInfoForResourceTransfer(authInfo, existingContact);
// Verify that the resource does not already have a pending transfer.

View file

@ -14,6 +14,7 @@
package google.registry.flows.contact;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
@ -28,9 +29,10 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.googlecode.objectify.Key;
import google.registry.flows.EppException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow;
import google.registry.flows.exceptions.AddRemoveSameValueEppException;
import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException;
@ -59,7 +61,7 @@ import javax.inject.Inject;
* @error {@link ContactFlowUtils.BadInternationalizedPostalInfoException}
* @error {@link ContactFlowUtils.DeclineContactDisclosureFieldDisallowedPolicyException}
*/
public final class ContactUpdateFlow extends LoggedInFlow implements TransactionalFlow {
public final class ContactUpdateFlow extends Flow implements TransactionalFlow {
/**
* Note that CLIENT_UPDATE_PROHIBITED is intentionally not in this list. This is because it
@ -71,19 +73,18 @@ public final class ContactUpdateFlow extends LoggedInFlow implements Transaction
StatusValue.SERVER_UPDATE_PROHIBITED);
@Inject ResourceCommand resourceCommand;
@Inject ExtensionManager extensionManager;
@Inject Optional<AuthInfo> authInfo;
@Inject @ClientId String clientId;
@Inject @TargetId String targetId;
@Inject HistoryEntry.Builder historyBuilder;
@Inject ContactUpdateFlow() {}
@Override
protected final void initLoggedInFlow() throws EppException {
registerExtensions(MetadataExtension.class);
}
@Override
public final EppOutput run() throws EppException {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
Update command = (Update) resourceCommand;
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
verifyOptionalAuthInfoForResource(authInfo, existingContact);

View file

@ -14,6 +14,7 @@
package google.registry.flows.domain;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.verifyTargetIdCount;
import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld;
import static google.registry.flows.domain.DomainFlowUtils.validateDomainName;
@ -29,7 +30,9 @@ import com.google.common.net.InternetDomainName;
import google.registry.config.ConfigModule.Config;
import google.registry.flows.EppException;
import google.registry.flows.EppException.CommandUseErrorException;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.model.domain.DomainCommand.Check;
import google.registry.model.domain.launch.LaunchCheckExtension;
import google.registry.model.domain.launch.LaunchCheckResponseExtension;
@ -55,19 +58,19 @@ import javax.inject.Inject;
* @error {@link DomainFlowUtils.TldDoesNotExistException}
* @error {@link ClaimsCheckNotAllowedInSunrise}
*/
public final class ClaimsCheckFlow extends LoggedInFlow {
public final class ClaimsCheckFlow extends Flow {
@Inject ExtensionManager extensionManager;
@Inject ResourceCommand resourceCommand;
@Inject @ClientId String clientId;
@Inject @Config("maxChecks") int maxChecks;
@Inject ClaimsCheckFlow() {}
@Override
protected final void initLoggedInFlow() throws EppException {
registerExtensions(LaunchCheckExtension.class);
}
@Override
public EppOutput run() throws EppException {
extensionManager.register(LaunchCheckExtension.class);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
List<String> targetIds = ((Check) resourceCommand).getTargetIds();
verifyTargetIdCount(targetIds, maxChecks);
Set<String> seenTlds = new HashSet<>();
@ -78,7 +81,7 @@ public final class ClaimsCheckFlow extends LoggedInFlow {
String tld = domainName.parent().toString();
// Only validate access to a TLD the first time it is encountered.
if (seenTlds.add(tld)) {
checkAllowedAccessToTld(getAllowedTlds(), tld);
checkAllowedAccessToTld(clientId, tld);
Registry registry = Registry.get(tld);
if (!isSuperuser) {
verifyNotInPredelegation(registry, now);

View file

@ -16,6 +16,7 @@ package google.registry.flows.domain;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.getOnlyElement;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.verifyResourceDoesNotExist;
import static google.registry.flows.domain.DomainFlowUtils.cloneAndLinkReferences;
import static google.registry.flows.domain.DomainFlowUtils.createFeeCreateResponse;
@ -46,9 +47,10 @@ import google.registry.flows.EppException;
import google.registry.flows.EppException.AuthorizationErrorException;
import google.registry.flows.EppException.ObjectDoesNotExistException;
import google.registry.flows.EppException.StatusProhibitsOperationException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow;
import google.registry.flows.domain.TldSpecificLogicProxy.EppCommandOperations;
import google.registry.model.ImmutableObject;
@ -95,13 +97,14 @@ import org.joda.time.DateTime;
* @error {@link DomainAllocateFlow.MissingApplicationException}
* @error {@link DomainAllocateFlow.OnlySuperuserCanAllocateException}
*/
public class DomainAllocateFlow extends LoggedInFlow implements TransactionalFlow {
public class DomainAllocateFlow extends Flow implements TransactionalFlow {
private static final String COLLISION_MESSAGE =
"Domain on the name collision list was allocated. But by policy, the domain will not be "
+ "delegated. Please visit https://www.icann.org/namecollision for more information on name "
+ "collision.";
@Inject ExtensionManager extensionManager;
@Inject AuthInfo authInfo;
@Inject ResourceCommand resourceCommand;
@Inject @ClientId String clientId;
@ -110,17 +113,15 @@ public class DomainAllocateFlow extends LoggedInFlow implements TransactionalFlo
@Inject DomainAllocateFlow() {}
@Override
protected final void initLoggedInFlow() throws EppException {
registerExtensions(FEE_CREATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
registerExtensions(
public final EppOutput run() throws EppException {
extensionManager.register(
SecDnsCreateExtension.class,
FlagsCreateCommandExtension.class,
MetadataExtension.class,
AllocateCreateExtension.class);
}
@Override
public final EppOutput run() throws EppException {
extensionManager.registerAsGroup(FEE_CREATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
verifyIsSuperuser();
Create command = cloneAndLinkReferences((Create) resourceCommand, now);
failfastForCreate(targetId, now);

View file

@ -15,6 +15,7 @@
package google.registry.flows.domain;
import static com.google.common.collect.Iterables.getOnlyElement;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.verifyResourceDoesNotExist;
import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld;
import static google.registry.flows.domain.DomainFlowUtils.cloneAndLinkReferences;
@ -54,9 +55,10 @@ import google.registry.flows.EppException;
import google.registry.flows.EppException.CommandUseErrorException;
import google.registry.flows.EppException.ObjectAlreadyExistsException;
import google.registry.flows.EppException.RequiredParameterMissingException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow;
import google.registry.flows.domain.TldSpecificLogicProxy.EppCommandOperations;
import google.registry.model.ImmutableObject;
@ -151,8 +153,9 @@ import javax.inject.Inject;
* @error {@link DomainFlowUtils.UnsupportedFeeAttributeException}
* @error {@link DomainFlowUtils.UnsupportedMarkTypeException}
*/
public final class DomainApplicationCreateFlow extends LoggedInFlow implements TransactionalFlow {
public final class DomainApplicationCreateFlow extends Flow implements TransactionalFlow {
@Inject ExtensionManager extensionManager;
@Inject AuthInfo authInfo;
@Inject ResourceCommand resourceCommand;
@Inject @ClientId String clientId;
@ -161,17 +164,15 @@ public final class DomainApplicationCreateFlow extends LoggedInFlow implements T
@Inject DomainApplicationCreateFlow() {}
@Override
protected final void initLoggedInFlow() throws EppException {
registerExtensions(FEE_CREATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
registerExtensions(
public final EppOutput run() throws EppException {
extensionManager.register(
SecDnsCreateExtension.class,
FlagsCreateCommandExtension.class,
MetadataExtension.class,
LaunchCreateExtension.class);
}
@Override
public final EppOutput run() throws EppException {
extensionManager.registerAsGroup(FEE_CREATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
Create command = cloneAndLinkReferences((Create) resourceCommand, now);
failfastForCreate(targetId, now);
// Fail if the domain is already registered (e.g. this is a landrush application but the domain
@ -182,7 +183,7 @@ public final class DomainApplicationCreateFlow extends LoggedInFlow implements T
InternetDomainName domainName = validateDomainName(targetId);
String idnTableName = validateDomainNameWithIdnTables(domainName);
String tld = domainName.parent().toString();
checkAllowedAccessToTld(getAllowedTlds(), tld);
checkAllowedAccessToTld(clientId, tld);
Registry registry = Registry.get(tld);
EppCommandOperations commandOperations = TldSpecificLogicProxy.getCreatePrice(
registry, targetId, clientId, now, command.getPeriod().getValue(), eppInput);

View file

@ -14,6 +14,7 @@
package google.registry.flows.domain;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.handlePendingTransferOnDelete;
import static google.registry.flows.ResourceFlowUtils.prepareDeletedResourceAsBuilder;
import static google.registry.flows.ResourceFlowUtils.updateForeignKeyIndexDeletionTime;
@ -32,10 +33,11 @@ import com.google.common.base.Optional;
import com.googlecode.objectify.Key;
import google.registry.flows.EppException;
import google.registry.flows.EppException.StatusProhibitsOperationException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ApplicationId;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow;
import google.registry.model.domain.DomainApplication;
import google.registry.model.domain.launch.LaunchDeleteExtension;
@ -60,8 +62,9 @@ import javax.inject.Inject;
* @error {@link DomainFlowUtils.LaunchPhaseMismatchException}
* @error {@link DomainFlowUtils.NotAuthorizedForTldException}
*/
public final class DomainApplicationDeleteFlow extends LoggedInFlow implements TransactionalFlow {
public final class DomainApplicationDeleteFlow extends Flow implements TransactionalFlow {
@Inject ExtensionManager extensionManager;
@Inject Optional<AuthInfo> authInfo;
@Inject @ClientId String clientId;
@Inject @TargetId String targetId;
@ -69,20 +72,17 @@ public final class DomainApplicationDeleteFlow extends LoggedInFlow implements T
@Inject HistoryEntry.Builder historyBuilder;
@Inject DomainApplicationDeleteFlow() {}
@Override
protected final void initLoggedInFlow() throws EppException {
registerExtensions(MetadataExtension.class);
registerExtensions(LaunchDeleteExtension.class);
}
@Override
public final EppOutput run() throws EppException {
extensionManager.register(MetadataExtension.class, LaunchDeleteExtension.class);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
DomainApplication existingApplication = verifyExistence(
DomainApplication.class, applicationId, loadDomainApplication(applicationId, now));
verifyApplicationDomainMatchesTargetId(existingApplication, targetId);
verifyOptionalAuthInfoForResource(authInfo, existingApplication);
String tld = existingApplication.getTld();
checkAllowedAccessToTld(getAllowedTlds(), tld);
checkAllowedAccessToTld(clientId, tld);
if (!isSuperuser) {
Registry registry = Registry.get(tld);
verifyRegistryStateAllowsLaunchFlows(registry, now);

View file

@ -15,6 +15,7 @@
package google.registry.flows.domain;
import static google.registry.flows.EppXmlTransformer.unmarshal;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.verifyExistence;
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
@ -28,10 +29,11 @@ import com.google.common.collect.ImmutableList;
import google.registry.flows.EppException;
import google.registry.flows.EppException.ParameterValuePolicyErrorException;
import google.registry.flows.EppException.RequiredParameterMissingException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ApplicationId;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow;
import google.registry.model.domain.DomainApplication;
import google.registry.model.domain.DomainCommand.Info;
import google.registry.model.domain.launch.LaunchInfoExtension;
@ -57,22 +59,21 @@ import javax.inject.Inject;
* @error {@link DomainApplicationInfoFlow.ApplicationLaunchPhaseMismatchException}
* @error {@link MissingApplicationIdException}
*/
public final class DomainApplicationInfoFlow extends LoggedInFlow {
public final class DomainApplicationInfoFlow extends Flow {
@Inject ResourceCommand resourceCommand;
@Inject ExtensionManager extensionManager;
@Inject Optional<AuthInfo> authInfo;
@Inject @ClientId String clientId;
@Inject @TargetId String targetId;
@Inject @ApplicationId String applicationId;
@Inject DomainApplicationInfoFlow() {}
@Override
protected final void initLoggedInFlow() throws EppException {
registerExtensions(LaunchInfoExtension.class);
}
@Override
public final EppOutput run() throws EppException {
extensionManager.register(LaunchInfoExtension.class);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
if (applicationId.isEmpty()) {
throw new MissingApplicationIdException();
}

View file

@ -16,6 +16,7 @@ package google.registry.flows.domain;
import static com.google.common.base.CaseFormat.LOWER_CAMEL;
import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.verifyExistence;
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
@ -45,10 +46,11 @@ import com.google.common.collect.Sets;
import com.googlecode.objectify.Key;
import google.registry.flows.EppException;
import google.registry.flows.EppException.StatusProhibitsOperationException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ApplicationId;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow;
import google.registry.flows.exceptions.AddRemoveSameValueEppException;
import google.registry.model.ImmutableObject;
@ -97,7 +99,7 @@ import javax.inject.Inject;
* @error {@link DomainFlowUtils.UrgentAttributeNotSupportedException}
* @error {@link DomainApplicationUpdateFlow.ApplicationStatusProhibitsUpdateException}
*/
public class DomainApplicationUpdateFlow extends LoggedInFlow implements TransactionalFlow {
public class DomainApplicationUpdateFlow extends Flow implements TransactionalFlow {
/**
* Note that CLIENT_UPDATE_PROHIBITED is intentionally not in this list. This is because it
@ -116,6 +118,7 @@ public class DomainApplicationUpdateFlow extends LoggedInFlow implements Transac
ApplicationStatus.ALLOCATED);
@Inject ResourceCommand resourceCommand;
@Inject ExtensionManager extensionManager;
@Inject Optional<AuthInfo> authInfo;
@Inject @ClientId String clientId;
@Inject @TargetId String targetId;
@ -123,15 +126,15 @@ public class DomainApplicationUpdateFlow extends LoggedInFlow implements Transac
@Inject HistoryEntry.Builder historyBuilder;
@Inject DomainApplicationUpdateFlow() {}
@Override
protected final void initLoggedInFlow() throws EppException {
registerExtensions(FEE_UPDATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
registerExtensions(
MetadataExtension.class, LaunchUpdateExtension.class, SecDnsUpdateExtension.class);
}
@Override
public final EppOutput run() throws EppException {
extensionManager.register(
LaunchUpdateExtension.class,
MetadataExtension.class,
SecDnsUpdateExtension.class);
extensionManager.registerAsGroup(FEE_UPDATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
Update command = cloneAndLinkReferences((Update) resourceCommand, now);
DomainApplication existingApplication = verifyExistence(
DomainApplication.class, applicationId, loadDomainApplication(applicationId, now));
@ -154,7 +157,7 @@ public class DomainApplicationUpdateFlow extends LoggedInFlow implements Transac
verifyStatusChangesAreClientSettable(command);
}
String tld = existingApplication.getTld();
checkAllowedAccessToTld(getAllowedTlds(), tld);
checkAllowedAccessToTld(clientId, tld);
if (UPDATE_DISALLOWED_APPLICATION_STATUSES
.contains(existingApplication.getApplicationStatus())) {
throw new ApplicationStatusProhibitsUpdateException(

View file

@ -14,6 +14,7 @@
package google.registry.flows.domain;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.verifyTargetIdCount;
import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld;
import static google.registry.flows.domain.DomainFlowUtils.getReservationType;
@ -40,8 +41,9 @@ import com.google.common.net.InternetDomainName;
import google.registry.config.ConfigModule.Config;
import google.registry.flows.EppException;
import google.registry.flows.EppException.ParameterValuePolicyErrorException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.LoggedInFlow;
import google.registry.model.domain.DomainApplication;
import google.registry.model.domain.DomainCommand.Check;
import google.registry.model.domain.DomainResource;
@ -88,7 +90,7 @@ import javax.inject.Inject;
* @error {@link DomainFlowUtils.UnknownFeeCommandException}
* @error {@link OnlyCheckedNamesCanBeFeeCheckedException}
*/
public final class DomainCheckFlow extends LoggedInFlow {
public final class DomainCheckFlow extends Flow {
/**
* The TLD states during which we want to report a domain with pending applications as
@ -98,18 +100,17 @@ public final class DomainCheckFlow extends LoggedInFlow {
Sets.immutableEnumSet(TldState.GENERAL_AVAILABILITY, TldState.QUIET_PERIOD);
@Inject ResourceCommand resourceCommand;
@Inject ExtensionManager extensionManager;
@Inject @ClientId String clientId;
@Inject @Config("maxChecks") int maxChecks;
@Inject DomainCheckFlow() {}
@Override
protected final void initLoggedInFlow() throws EppException {
registerExtensions(LaunchCheckExtension.class);
registerExtensions(FEE_CHECK_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
}
@Override
public EppOutput run() throws EppException {
extensionManager.register(LaunchCheckExtension.class);
extensionManager.registerAsGroup(FEE_CHECK_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
List<String> targetIds = ((Check) resourceCommand).getTargetIds();
verifyTargetIdCount(targetIds, maxChecks);
ImmutableMap.Builder<String, InternetDomainName> domains = new ImmutableMap.Builder<>();
@ -122,7 +123,7 @@ public final class DomainCheckFlow extends LoggedInFlow {
domains.put(targetId, domainName);
String tld = domainName.parent().toString();
if (seenTlds.add(tld)) {
checkAllowedAccessToTld(getAllowedTlds(), tld);
checkAllowedAccessToTld(clientId, tld);
if (!isSuperuser) {
verifyNotInPredelegation(Registry.get(tld), now);
}

View file

@ -14,6 +14,7 @@
package google.registry.flows.domain;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.verifyResourceDoesNotExist;
import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld;
import static google.registry.flows.domain.DomainFlowUtils.cloneAndLinkReferences;
@ -52,9 +53,10 @@ import google.registry.dns.DnsQueue;
import google.registry.flows.EppException;
import google.registry.flows.EppException.CommandUseErrorException;
import google.registry.flows.EppException.StatusProhibitsOperationException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow;
import google.registry.flows.domain.TldSpecificLogicProxy.EppCommandOperations;
import google.registry.model.ImmutableObject;
@ -99,7 +101,7 @@ import org.joda.time.DateTime;
* @error {@link google.registry.flows.exceptions.OnlyToolCanPassMetadataException}
* @error {@link google.registry.flows.exceptions.ResourceAlreadyExistsException}
* @error {@link google.registry.flows.EppException.UnimplementedExtensionException}
* @error {@link google.registry.flows.LoggedInFlow.UndeclaredServiceExtensionException}
* @error {@link google.registry.flows.ExtensionManager.UndeclaredServiceExtensionException}
* @error {@link google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException}
* @error {@link DomainCreateFlow.SignedMarksNotAcceptedInCurrentPhaseException}
* @error {@link DomainFlowUtils.AcceptedTooLongAgoException}
@ -147,11 +149,12 @@ import org.joda.time.DateTime;
* @error {@link DomainCreateFlow.NoGeneralRegistrationsInCurrentPhaseException}
*/
public class DomainCreateFlow extends LoggedInFlow implements TransactionalFlow {
public class DomainCreateFlow extends Flow implements TransactionalFlow {
private static final Set<TldState> QLP_SMD_ALLOWED_STATES =
Sets.immutableEnumSet(TldState.SUNRISE, TldState.SUNRUSH);
@Inject ExtensionManager extensionManager;
@Inject AuthInfo authInfo;
@Inject ResourceCommand resourceCommand;
@Inject @ClientId String clientId;
@ -160,17 +163,15 @@ public class DomainCreateFlow extends LoggedInFlow implements TransactionalFlow
@Inject DomainCreateFlow() {}
@Override
protected final void initLoggedInFlow() throws EppException {
registerExtensions(FEE_CREATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
registerExtensions(
public final EppOutput run() throws EppException {
extensionManager.register(
SecDnsCreateExtension.class,
FlagsCreateCommandExtension.class,
MetadataExtension.class,
LaunchCreateExtension.class);
}
@Override
public final EppOutput run() throws EppException {
extensionManager.registerAsGroup(FEE_CREATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
Create command = cloneAndLinkReferences((Create) resourceCommand, now);
Period period = command.getPeriod();
verifyUnitIsYears(period);
@ -204,7 +205,7 @@ public class DomainCreateFlow extends LoggedInFlow implements TransactionalFlow
// notice without specifying a claims key, ignore the registry phase, and override blocks on
// registering premium domains.
if (!isSuperuser) {
checkAllowedAccessToTld(getAllowedTlds(), registry.getTldStr());
checkAllowedAccessToTld(clientId, registry.getTldStr());
if (launchCreate != null) {
verifyLaunchPhaseMatchesRegistryPhase(registry, launchCreate, now);
}

View file

@ -15,6 +15,7 @@
package google.registry.flows.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.handlePendingTransferOnDelete;
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
import static google.registry.flows.ResourceFlowUtils.prepareDeletedResourceAsBuilder;
@ -38,9 +39,10 @@ import com.googlecode.objectify.Key;
import google.registry.dns.DnsQueue;
import google.registry.flows.EppException;
import google.registry.flows.EppException.AssociationProhibitsOperationException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow;
import google.registry.model.ImmutableObject;
import google.registry.model.billing.BillingEvent;
@ -55,7 +57,7 @@ import google.registry.model.domain.fee11.FeeDeleteResponseExtensionV11;
import google.registry.model.domain.fee12.FeeDeleteResponseExtensionV12;
import google.registry.model.domain.metadata.MetadataExtension;
import google.registry.model.domain.rgp.GracePeriodStatus;
import google.registry.model.domain.secdns.SecDnsUpdateExtension;
import google.registry.model.domain.secdns.SecDnsCreateExtension;
import google.registry.model.eppcommon.AuthInfo;
import google.registry.model.eppcommon.ProtocolDefinition.ServiceExtension;
import google.registry.model.eppcommon.StatusValue;
@ -82,7 +84,7 @@ import org.joda.time.DateTime;
* @error {@link DomainFlowUtils.BadCommandForRegistryPhaseException}
* @error {@link DomainFlowUtils.NotAuthorizedForTldException}
*/
public final class DomainDeleteFlow extends LoggedInFlow implements TransactionalFlow {
public final class DomainDeleteFlow extends Flow implements TransactionalFlow {
private static final ImmutableSet<StatusValue> DISALLOWED_STATUSES = ImmutableSet.of(
StatusValue.LINKED,
@ -90,6 +92,7 @@ public final class DomainDeleteFlow extends LoggedInFlow implements Transactiona
StatusValue.PENDING_DELETE,
StatusValue.SERVER_DELETE_PROHIBITED);
@Inject ExtensionManager extensionManager;
@Inject Optional<AuthInfo> authInfo;
@Inject @ClientId String clientId;
@Inject @TargetId String targetId;
@ -97,15 +100,11 @@ public final class DomainDeleteFlow extends LoggedInFlow implements Transactiona
@Inject DnsQueue dnsQueue;
@Inject DomainDeleteFlow() {}
@Override
@SuppressWarnings("unchecked")
protected final void initLoggedInFlow() throws EppException {
registerExtensions(MetadataExtension.class);
registerExtensions(SecDnsUpdateExtension.class);
}
@Override
public final EppOutput run() throws EppException {
extensionManager.register(MetadataExtension.class, SecDnsCreateExtension.class);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
// Loads the target resource if it exists
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
Registry registry = Registry.get(existingDomain.getTld());
@ -165,7 +164,7 @@ public final class DomainDeleteFlow extends LoggedInFlow implements Transactiona
verifyResourceOwnership(clientId, existingDomain);
verifyNotInPredelegation(registry, now);
}
checkAllowedAccessToTld(getAllowedTlds(), registry.getTld().toString());
checkAllowedAccessToTld(clientId, registry.getTld().toString());
if (!existingDomain.getSubordinateHosts().isEmpty()) {
throw new DomainToDeleteHasHostsException();
}

View file

@ -247,9 +247,9 @@ public class DomainFlowUtils {
}
/** Check if the registrar running the flow has access to the TLD in question. */
public static void checkAllowedAccessToTld(Set<String> allowedTlds, String tld)
public static void checkAllowedAccessToTld(String clientId, String tld)
throws EppException {
if (!allowedTlds.contains(tld)) {
if (!Registrar.loadByClientId(clientId).getAllowedTlds().contains(tld)) {
throw new DomainFlowUtils.NotAuthorizedForTldException(tld);
}
}

View file

@ -14,6 +14,7 @@
package google.registry.flows.domain;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
import static google.registry.flows.domain.DomainFlowUtils.addSecDnsExtensionIfPresent;
@ -26,9 +27,10 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.net.InternetDomainName;
import google.registry.flows.EppException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow;
import google.registry.model.domain.DomainCommand.Info;
import google.registry.model.domain.DomainCommand.Info.HostsRequest;
import google.registry.model.domain.DomainResource;
@ -59,21 +61,20 @@ import javax.inject.Inject;
* @error {@link DomainFlowUtils.FeeChecksDontSupportPhasesException}
* @error {@link DomainFlowUtils.RestoresAreAlwaysForOneYearException}
*/
public final class DomainInfoFlow extends LoggedInFlow {
public final class DomainInfoFlow extends Flow {
@Inject ExtensionManager extensionManager;
@Inject Optional<AuthInfo> authInfo;
@Inject @ClientId String clientId;
@Inject @TargetId String targetId;
@Inject ResourceCommand resourceCommand;
@Inject DomainInfoFlow() {}
@Override
protected void initLoggedInFlow() throws EppException {
registerExtensions(FeeInfoCommandExtensionV06.class);
}
@Override
public final EppOutput run() throws EppException {
extensionManager.register(FeeInfoCommandExtensionV06.class);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
DomainResource domain = loadAndVerifyExistence(DomainResource.class, targetId, now);
verifyOptionalAuthInfoForResource(authInfo, domain);
return createOutput(

View file

@ -14,6 +14,7 @@
package google.registry.flows.domain;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
@ -38,9 +39,10 @@ import com.googlecode.objectify.Key;
import google.registry.flows.EppException;
import google.registry.flows.EppException.ObjectPendingTransferException;
import google.registry.flows.EppException.ParameterValueRangeErrorException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow;
import google.registry.flows.domain.TldSpecificLogicProxy.EppCommandOperations;
import google.registry.model.billing.BillingEvent;
@ -95,7 +97,7 @@ import org.joda.time.DateTime;
* @error {@link DomainRenewFlow.ExceedsMaxRegistrationYearsException}
* @error {@link DomainRenewFlow.IncorrectCurrentExpirationDateException}
*/
public final class DomainRenewFlow extends LoggedInFlow implements TransactionalFlow {
public final class DomainRenewFlow extends Flow implements TransactionalFlow {
private static final ImmutableSet<StatusValue> RENEW_DISALLOWED_STATUSES = ImmutableSet.of(
StatusValue.CLIENT_RENEW_PROHIBITED,
@ -103,20 +105,19 @@ public final class DomainRenewFlow extends LoggedInFlow implements Transactional
StatusValue.SERVER_RENEW_PROHIBITED);
@Inject ResourceCommand resourceCommand;
@Inject ExtensionManager extensionManager;
@Inject Optional<AuthInfo> authInfo;
@Inject @ClientId String clientId;
@Inject @TargetId String targetId;
@Inject HistoryEntry.Builder historyBuilder;
@Inject DomainRenewFlow() {}
@Override
protected final void initLoggedInFlow() throws EppException {
registerExtensions(MetadataExtension.class);
registerExtensions(FEE_RENEW_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
}
@Override
public final EppOutput run() throws EppException {
extensionManager.register(MetadataExtension.class);
extensionManager.registerAsGroup(FEE_RENEW_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
Renew command = (Renew) resourceCommand;
// Loads the target resource if it exists
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
@ -185,7 +186,7 @@ public final class DomainRenewFlow extends LoggedInFlow implements Transactional
if (!isSuperuser) {
verifyResourceOwnership(clientId, existingDomain);
}
checkAllowedAccessToTld(getAllowedTlds(), existingDomain.getTld());
checkAllowedAccessToTld(clientId, existingDomain.getTld());
// Verify that the resource does not have a pending transfer on it.
if (existingDomain.getTransferData().getTransferStatus() == TransferStatus.PENDING) {
throw new DomainHasPendingTransferException(targetId);

View file

@ -14,6 +14,7 @@
package google.registry.flows.domain;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
import static google.registry.flows.ResourceFlowUtils.updateForeignKeyIndexDeletionTime;
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
@ -38,9 +39,10 @@ import google.registry.dns.DnsQueue;
import google.registry.flows.EppException;
import google.registry.flows.EppException.CommandUseErrorException;
import google.registry.flows.EppException.StatusProhibitsOperationException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow;
import google.registry.flows.domain.TldSpecificLogicProxy.EppCommandOperations;
import google.registry.model.ImmutableObject;
@ -101,9 +103,10 @@ import org.joda.time.DateTime;
* @error {@link DomainRestoreRequestFlow.DomainNotEligibleForRestoreException}
* @error {@link DomainRestoreRequestFlow.RestoreCommandIncludesChangesException}
*/
public final class DomainRestoreRequestFlow extends LoggedInFlow implements TransactionalFlow {
public final class DomainRestoreRequestFlow extends Flow implements TransactionalFlow {
@Inject ResourceCommand resourceCommand;
@Inject ExtensionManager extensionManager;
@Inject Optional<AuthInfo> authInfo;
@Inject @ClientId String clientId;
@Inject @TargetId String targetId;
@ -111,14 +114,12 @@ public final class DomainRestoreRequestFlow extends LoggedInFlow implements Tran
@Inject DnsQueue dnsQueue;
@Inject DomainRestoreRequestFlow() {}
@Override
protected final void initLoggedInFlow() throws EppException {
registerExtensions(MetadataExtension.class, RgpUpdateExtension.class);
registerExtensions(FEE_UPDATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
}
@Override
public final EppOutput run() throws EppException {
extensionManager.register(MetadataExtension.class, RgpUpdateExtension.class);
extensionManager.registerAsGroup(FEE_UPDATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
Update command = (Update) resourceCommand;
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
Money restoreCost = Registry.get(existingDomain.getTld()).getStandardRestoreCost();
@ -197,7 +198,7 @@ public final class DomainRestoreRequestFlow extends LoggedInFlow implements Tran
if (!existingDomain.getGracePeriodStatuses().contains(GracePeriodStatus.REDEMPTION)) {
throw new DomainNotEligibleForRestoreException();
}
checkAllowedAccessToTld(getAllowedTlds(), existingDomain.getTld());
checkAllowedAccessToTld(clientId, existingDomain.getTld());
validateFeeChallenge(targetId, existingDomain.getTld(), now, feeUpdate, restoreCost, renewCost);
}

View file

@ -16,6 +16,7 @@ package google.registry.flows.domain;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.getOnlyElement;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.approvePendingTransfer;
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
import static google.registry.flows.ResourceFlowUtils.verifyHasPendingTransfer;
@ -36,9 +37,10 @@ import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
import google.registry.flows.EppException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow;
import google.registry.model.ImmutableObject;
import google.registry.model.billing.BillingEvent;
@ -76,31 +78,30 @@ import org.joda.time.DateTime;
* @error {@link google.registry.flows.exceptions.NotPendingTransferException}
* @error {@link DomainFlowUtils.NotAuthorizedForTldException}
*/
public final class DomainTransferApproveFlow extends LoggedInFlow implements TransactionalFlow {
public final class DomainTransferApproveFlow extends Flow implements TransactionalFlow {
@Inject ExtensionManager extensionManager;
@Inject Optional<AuthInfo> authInfo;
@Inject @ClientId String clientId;
@Inject @TargetId String targetId;
@Inject HistoryEntry.Builder historyBuilder;
@Inject DomainTransferApproveFlow() {}
@Override
protected final void initLoggedInFlow() throws EppException {
registerExtensions(MetadataExtension.class);
}
/**
* <p>The logic in this flow, which handles client approvals, very closely parallels the logic in
* {@link DomainResource#cloneProjectedAtTime} which handles implicit server approvals.
*/
@Override
public final EppOutput run() throws EppException {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
verifyOptionalAuthInfoForResource(authInfo, existingDomain);
verifyHasPendingTransfer(existingDomain);
verifyResourceOwnership(clientId, existingDomain);
String tld = existingDomain.getTld();
checkAllowedAccessToTld(getAllowedTlds(), tld);
checkAllowedAccessToTld(clientId, tld);
HistoryEntry historyEntry = historyBuilder
.setType(HistoryEntry.Type.DOMAIN_TRANSFER_APPROVE)
.setModificationTime(now)

View file

@ -14,6 +14,7 @@
package google.registry.flows.domain;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.denyPendingTransfer;
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
import static google.registry.flows.ResourceFlowUtils.verifyHasPendingTransfer;
@ -30,9 +31,10 @@ import static google.registry.util.DateTimeUtils.END_OF_TIME;
import com.google.common.base.Optional;
import com.googlecode.objectify.Key;
import google.registry.flows.EppException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow;
import google.registry.model.ImmutableObject;
import google.registry.model.domain.DomainResource;
@ -61,26 +63,25 @@ import javax.inject.Inject;
* @error {@link google.registry.flows.exceptions.NotTransferInitiatorException}
* @error {@link DomainFlowUtils.NotAuthorizedForTldException}
*/
public final class DomainTransferCancelFlow extends LoggedInFlow implements TransactionalFlow {
public final class DomainTransferCancelFlow extends Flow implements TransactionalFlow {
@Inject ExtensionManager extensionManager;
@Inject Optional<AuthInfo> authInfo;
@Inject @ClientId String clientId;
@Inject @TargetId String targetId;
@Inject HistoryEntry.Builder historyBuilder;
@Inject DomainTransferCancelFlow() {}
@Override
protected final void initLoggedInFlow() throws EppException {
registerExtensions(MetadataExtension.class);
}
@Override
public final EppOutput run() throws EppException {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
verifyOptionalAuthInfoForResource(authInfo, existingDomain);
verifyHasPendingTransfer(existingDomain);
verifyIsGainingRegistrar(existingDomain, clientId);
checkAllowedAccessToTld(getAllowedTlds(), existingDomain.getTld());
checkAllowedAccessToTld(clientId, existingDomain.getTld());
HistoryEntry historyEntry = historyBuilder
.setType(HistoryEntry.Type.DOMAIN_TRANSFER_CANCEL)
.setModificationTime(now)

View file

@ -14,6 +14,7 @@
package google.registry.flows.domain;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
import static google.registry.flows.domain.DomainFlowUtils.createTransferResponse;
@ -22,9 +23,10 @@ import static google.registry.model.eppoutput.Result.Code.SUCCESS;
import com.google.common.base.Optional;
import google.registry.flows.EppException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.exceptions.NoTransferHistoryToQueryException;
import google.registry.flows.exceptions.NotAuthorizedToViewTransferException;
import google.registry.model.domain.DomainResource;
@ -50,8 +52,9 @@ import org.joda.time.DateTime;
* @error {@link google.registry.flows.exceptions.NoTransferHistoryToQueryException}
* @error {@link google.registry.flows.exceptions.NotAuthorizedToViewTransferException}
*/
public final class DomainTransferQueryFlow extends LoggedInFlow {
public final class DomainTransferQueryFlow extends Flow {
@Inject ExtensionManager extensionManager;
@Inject Optional<AuthInfo> authInfo;
@Inject @ClientId String clientId;
@Inject @TargetId String targetId;
@ -59,6 +62,8 @@ public final class DomainTransferQueryFlow extends LoggedInFlow {
@Override
public final EppOutput run() throws EppException {
extensionManager.validate(); // There are no legal extensions for this flow.
validateClientIsLoggedIn(clientId);
DomainResource domain = loadAndVerifyExistence(DomainResource.class, targetId, now);
verifyOptionalAuthInfoForResource(authInfo, domain);
// Most of the fields on the transfer response are required, so there's no way to return valid

View file

@ -14,6 +14,7 @@
package google.registry.flows.domain;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.denyPendingTransfer;
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
import static google.registry.flows.ResourceFlowUtils.verifyHasPendingTransfer;
@ -30,9 +31,10 @@ import static google.registry.util.DateTimeUtils.END_OF_TIME;
import com.google.common.base.Optional;
import com.googlecode.objectify.Key;
import google.registry.flows.EppException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow;
import google.registry.model.ImmutableObject;
import google.registry.model.domain.DomainResource;
@ -61,21 +63,20 @@ import javax.inject.Inject;
* @error {@link google.registry.flows.exceptions.NotPendingTransferException}
* @error {@link DomainFlowUtils.NotAuthorizedForTldException}
*/
public final class DomainTransferRejectFlow extends LoggedInFlow implements TransactionalFlow {
public final class DomainTransferRejectFlow extends Flow implements TransactionalFlow {
@Inject ExtensionManager extensionManager;
@Inject Optional<AuthInfo> authInfo;
@Inject @ClientId String clientId;
@Inject @TargetId String targetId;
@Inject HistoryEntry.Builder historyBuilder;
@Inject DomainTransferRejectFlow() {}
@Override
protected final void initLoggedInFlow() throws EppException {
registerExtensions(MetadataExtension.class);
}
@Override
public final EppOutput run() throws EppException {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
HistoryEntry historyEntry = historyBuilder
.setType(HistoryEntry.Type.DOMAIN_TRANSFER_REJECT)
@ -85,7 +86,7 @@ public final class DomainTransferRejectFlow extends LoggedInFlow implements Tran
verifyOptionalAuthInfoForResource(authInfo, existingDomain);
verifyHasPendingTransfer(existingDomain);
verifyResourceOwnership(clientId, existingDomain);
checkAllowedAccessToTld(getAllowedTlds(), existingDomain.getTld());
checkAllowedAccessToTld(clientId, existingDomain.getTld());
DomainResource newDomain =
denyPendingTransfer(existingDomain, TransferStatus.CLIENT_REJECTED, now);
ofy().save().<ImmutableObject>entities(

View file

@ -16,6 +16,7 @@ package google.registry.flows.domain;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.getOnlyElement;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
import static google.registry.flows.ResourceFlowUtils.verifyRequiredAuthInfoForResourceTransfer;
@ -39,9 +40,10 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
import google.registry.flows.EppException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow;
import google.registry.flows.exceptions.AlreadyPendingTransferException;
import google.registry.flows.exceptions.ObjectAlreadySponsoredException;
@ -104,7 +106,7 @@ import org.joda.time.Duration;
* @error {@link DomainFlowUtils.PremiumNameBlockedException}
* @error {@link DomainFlowUtils.UnsupportedFeeAttributeException}
*/
public final class DomainTransferRequestFlow extends LoggedInFlow implements TransactionalFlow {
public final class DomainTransferRequestFlow extends Flow implements TransactionalFlow {
private static final ImmutableSet<StatusValue> DISALLOWED_STATUSES = ImmutableSet.of(
StatusValue.CLIENT_TRANSFER_PROHIBITED,
@ -112,20 +114,19 @@ public final class DomainTransferRequestFlow extends LoggedInFlow implements Tra
StatusValue.SERVER_TRANSFER_PROHIBITED);
@Inject ResourceCommand resourceCommand;
@Inject ExtensionManager extensionManager;
@Inject Optional<AuthInfo> authInfo;
@Inject @ClientId String gainingClientId;
@Inject @TargetId String targetId;
@Inject HistoryEntry.Builder historyBuilder;
@Inject DomainTransferRequestFlow() {}
@Override
protected final void initLoggedInFlow() throws EppException {
registerExtensions(MetadataExtension.class, FlagsTransferCommandExtension.class);
registerExtensions(FEE_TRANSFER_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
}
@Override
public final EppOutput run() throws EppException {
extensionManager.register(FlagsTransferCommandExtension.class, MetadataExtension.class);
extensionManager.registerAsGroup(FEE_TRANSFER_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
extensionManager.validate();
validateClientIsLoggedIn(gainingClientId);
Period period = ((Transfer) resourceCommand).getPeriod();
int years = period.getValue();
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
@ -194,7 +195,7 @@ public final class DomainTransferRequestFlow extends LoggedInFlow implements Tra
if (gainingClientId.equals(existingDomain.getCurrentSponsorClientId())) {
throw new ObjectAlreadySponsoredException();
}
checkAllowedAccessToTld(getAllowedTlds(), existingDomain.getTld());
checkAllowedAccessToTld(gainingClientId, existingDomain.getTld());
verifyUnitIsYears(period);
if (!isSuperuser) {
verifyPremiumNameIsNotBlocked(targetId, now, gainingClientId);

View file

@ -15,6 +15,7 @@
package google.registry.flows.domain;
import static com.google.common.collect.Sets.symmetricDifference;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
@ -44,9 +45,10 @@ import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
import google.registry.dns.DnsQueue;
import google.registry.flows.EppException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow;
import google.registry.flows.domain.DomainFlowUtils.FeesRequiredForNonFreeUpdateException;
import google.registry.flows.domain.TldSpecificLogicProxy.EppCommandOperations;
@ -116,7 +118,7 @@ import org.joda.time.DateTime;
* @error {@link DomainFlowUtils.TooManyNameserversException}
* @error {@link DomainFlowUtils.UrgentAttributeNotSupportedException}
*/
public final class DomainUpdateFlow extends LoggedInFlow implements TransactionalFlow {
public final class DomainUpdateFlow extends Flow implements TransactionalFlow {
/**
* Note that CLIENT_UPDATE_PROHIBITED is intentionally not in this list. This is because it
@ -128,6 +130,7 @@ public final class DomainUpdateFlow extends LoggedInFlow implements Transactiona
StatusValue.SERVER_UPDATE_PROHIBITED);
@Inject ResourceCommand resourceCommand;
@Inject ExtensionManager extensionManager;
@Inject Optional<AuthInfo> authInfo;
@Inject @ClientId String clientId;
@Inject @TargetId String targetId;
@ -135,15 +138,15 @@ public final class DomainUpdateFlow extends LoggedInFlow implements Transactiona
@Inject DnsQueue dnsQueue;
@Inject DomainUpdateFlow() {}
@Override
protected final void initLoggedInFlow() throws EppException {
registerExtensions(FEE_UPDATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
registerExtensions(
MetadataExtension.class, SecDnsUpdateExtension.class, FlagsUpdateCommandExtension.class);
}
@Override
public EppOutput run() throws EppException {
extensionManager.register(
FlagsUpdateCommandExtension.class,
MetadataExtension.class,
SecDnsUpdateExtension.class);
extensionManager.registerAsGroup(FEE_UPDATE_COMMAND_EXTENSIONS_IN_PREFERENCE_ORDER);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
Update command = cloneAndLinkReferences((Update) resourceCommand, now);
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
verifyUpdateAllowed(command, existingDomain);
@ -184,7 +187,7 @@ public final class DomainUpdateFlow extends LoggedInFlow implements Transactiona
verifyStatusChangesAreClientSettable(command);
}
String tld = existingDomain.getTld();
checkAllowedAccessToTld(getAllowedTlds(), tld);
checkAllowedAccessToTld(clientId, tld);
EppCommandOperations commandOperations = TldSpecificLogicProxy.getUpdatePrice(
Registry.get(tld), targetId, clientId, now, eppInput);

View file

@ -14,6 +14,7 @@
package google.registry.flows.host;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.verifyTargetIdCount;
import static google.registry.model.EppResourceUtils.checkResourcesExist;
import static google.registry.model.eppoutput.Result.Code.SUCCESS;
@ -21,7 +22,9 @@ import static google.registry.model.eppoutput.Result.Code.SUCCESS;
import com.google.common.collect.ImmutableList;
import google.registry.config.ConfigModule.Config;
import google.registry.flows.EppException;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.model.eppinput.ResourceCommand;
import google.registry.model.eppoutput.CheckData.HostCheck;
import google.registry.model.eppoutput.CheckData.HostCheckData;
@ -39,14 +42,18 @@ import javax.inject.Inject;
*
* @error {@link google.registry.flows.exceptions.TooManyResourceChecksException}
*/
public final class HostCheckFlow extends LoggedInFlow {
public final class HostCheckFlow extends Flow {
@Inject ResourceCommand resourceCommand;
@Inject @ClientId String clientId;
@Inject ExtensionManager extensionManager;
@Inject @Config("maxChecks") int maxChecks;
@Inject HostCheckFlow() {}
@Override
protected final EppOutput run() throws EppException {
extensionManager.validate(); // There are no legal extensions for this flow.
validateClientIsLoggedIn(clientId);
List<String> targetIds = ((Check) resourceCommand).getTargetIds();
verifyTargetIdCount(targetIds, maxChecks);
Set<String> existingIds = checkResourcesExist(HostResource.class, targetIds, now);

View file

@ -14,6 +14,7 @@
package google.registry.flows.host;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.verifyResourceDoesNotExist;
import static google.registry.flows.host.HostFlowUtils.lookupSuperordinateDomain;
import static google.registry.flows.host.HostFlowUtils.validateHostName;
@ -31,9 +32,10 @@ import google.registry.dns.DnsQueue;
import google.registry.flows.EppException;
import google.registry.flows.EppException.ParameterValueRangeErrorException;
import google.registry.flows.EppException.RequiredParameterMissingException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow;
import google.registry.model.ImmutableObject;
import google.registry.model.domain.DomainResource;
@ -68,23 +70,21 @@ import javax.inject.Inject;
* @error {@link SubordinateHostMustHaveIpException}
* @error {@link UnexpectedExternalHostIpException}
*/
public final class HostCreateFlow extends LoggedInFlow implements TransactionalFlow {
public final class HostCreateFlow extends Flow implements TransactionalFlow {
@Inject ResourceCommand resourceCommand;
@Inject ExtensionManager extensionManager;
@Inject @ClientId String clientId;
@Inject @TargetId String targetId;
@Inject HistoryEntry.Builder historyBuilder;
@Inject DnsQueue dnsQueue;
@Inject HostCreateFlow() {}
@Override
@SuppressWarnings("unchecked")
protected final void initLoggedInFlow() throws EppException {
registerExtensions(MetadataExtension.class);
}
@Override
protected final EppOutput run() throws EppException {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
Create command = (Create) resourceCommand;
verifyResourceDoesNotExist(HostResource.class, targetId, now);
// The superordinate domain of the host object if creating an in-bailiwick host, or null if

View file

@ -14,6 +14,7 @@
package google.registry.flows.host;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.failfastForAsyncDelete;
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
@ -27,9 +28,10 @@ import com.google.common.base.Optional;
import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
import google.registry.flows.EppException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow;
import google.registry.flows.async.AsyncFlowEnqueuer;
import google.registry.model.domain.DomainBase;
@ -55,7 +57,7 @@ import javax.inject.Inject;
* @error {@link google.registry.flows.exceptions.ResourceStatusProhibitsOperationException}
* @error {@link google.registry.flows.exceptions.ResourceToDeleteIsReferencedException}
*/
public final class HostDeleteFlow extends LoggedInFlow implements TransactionalFlow {
public final class HostDeleteFlow extends Flow implements TransactionalFlow {
private static final ImmutableSet<StatusValue> DISALLOWED_STATUSES = ImmutableSet.of(
StatusValue.LINKED,
@ -70,20 +72,19 @@ public final class HostDeleteFlow extends LoggedInFlow implements TransactionalF
return domain.getNameservers();
}};
@Inject AsyncFlowEnqueuer asyncFlowEnqueuer;
@Inject ExtensionManager extensionManager;
@Inject Optional<AuthInfo> authInfo;
@Inject @ClientId String clientId;
@Inject @TargetId String targetId;
@Inject HistoryEntry.Builder historyBuilder;
@Inject AsyncFlowEnqueuer asyncFlowEnqueuer;
@Inject HostDeleteFlow() {}
@Override
protected final void initLoggedInFlow() throws EppException {
registerExtensions(MetadataExtension.class);
}
@Override
public final EppOutput run() throws EppException {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
failfastForAsyncDelete(targetId, now, HostResource.class, GET_NAMESERVERS);
HostResource existingHost = loadAndVerifyExistence(HostResource.class, targetId, now);
verifyNoDisallowedStatuses(existingHost, DISALLOWED_STATUSES);

View file

@ -14,6 +14,7 @@
package google.registry.flows.host;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
import static google.registry.model.EppResourceUtils.cloneResourceWithLinkedStatus;
@ -21,8 +22,10 @@ import static google.registry.model.eppoutput.Result.Code.SUCCESS;
import com.google.common.base.Optional;
import google.registry.flows.EppException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow;
import google.registry.model.eppcommon.AuthInfo;
import google.registry.model.eppoutput.EppOutput;
import google.registry.model.host.HostResource;
@ -36,14 +39,18 @@ import javax.inject.Inject;
*
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException}
*/
public final class HostInfoFlow extends LoggedInFlow {
public final class HostInfoFlow extends Flow {
@Inject ExtensionManager extensionManager;
@Inject @ClientId String clientId;
@Inject @TargetId String targetId;
@Inject Optional<AuthInfo> authInfo;
@Inject HostInfoFlow() {}
@Override
public EppOutput run() throws EppException {
extensionManager.validate(); // There are no legal extensions for this flow.
validateClientIsLoggedIn(clientId);
HostResource host = loadAndVerifyExistence(HostResource.class, targetId, now);
verifyOptionalAuthInfoForResource(authInfo, host);
return createOutput(SUCCESS, cloneResourceWithLinkedStatus(host, now));

View file

@ -15,6 +15,7 @@
package google.registry.flows.host;
import static com.google.common.base.MoreObjects.firstNonNull;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
@ -37,9 +38,10 @@ import google.registry.flows.EppException.ObjectAlreadyExistsException;
import google.registry.flows.EppException.ParameterValueRangeErrorException;
import google.registry.flows.EppException.RequiredParameterMissingException;
import google.registry.flows.EppException.StatusProhibitsOperationException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow;
import google.registry.flows.async.AsyncFlowEnqueuer;
import google.registry.flows.exceptions.AddRemoveSameValueEppException;
@ -88,7 +90,7 @@ import javax.inject.Inject;
* @error {@link RenameHostToExternalRemoveIpException}
* @error {@link RenameHostToSubordinateRequiresIpException}
*/
public final class HostUpdateFlow extends LoggedInFlow implements TransactionalFlow {
public final class HostUpdateFlow extends Flow implements TransactionalFlow {
/**
* Note that CLIENT_UPDATE_PROHIBITED is intentionally not in this list. This is because it
@ -100,6 +102,7 @@ public final class HostUpdateFlow extends LoggedInFlow implements TransactionalF
StatusValue.SERVER_UPDATE_PROHIBITED);
@Inject ResourceCommand resourceCommand;
@Inject ExtensionManager extensionManager;
@Inject Optional<AuthInfo> authInfo;
@Inject @ClientId String clientId;
@Inject @TargetId String targetId;
@ -108,13 +111,11 @@ public final class HostUpdateFlow extends LoggedInFlow implements TransactionalF
@Inject DnsQueue dnsQueue;
@Inject HostUpdateFlow() {}
@Override
protected final void initLoggedInFlow() throws EppException {
registerExtensions(MetadataExtension.class);
}
@Override
public final EppOutput run() throws EppException {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateClientIsLoggedIn(clientId);
Update command = (Update) resourceCommand;
String suppliedNewHostName = command.getInnerChange().getFullyQualifiedHostName();
HostResource existingHost = loadAndVerifyExistence(HostResource.class, targetId, now);

View file

@ -15,6 +15,7 @@
package google.registry.flows.poll;
import static com.google.common.base.Preconditions.checkState;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
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;
@ -28,9 +29,10 @@ import google.registry.flows.EppException.AuthorizationErrorException;
import google.registry.flows.EppException.ObjectDoesNotExistException;
import google.registry.flows.EppException.ParameterValueSyntaxErrorException;
import google.registry.flows.EppException.RequiredParameterMissingException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.PollMessageId;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow;
import google.registry.model.eppoutput.EppOutput;
import google.registry.model.poll.MessageQueueInfo;
@ -53,14 +55,17 @@ import org.joda.time.DateTime;
* @error {@link PollAckFlow.MissingMessageIdException}
* @error {@link PollAckFlow.NotAuthorizedToAckMessageException}
*/
public class PollAckFlow extends LoggedInFlow implements TransactionalFlow {
public class PollAckFlow extends Flow implements TransactionalFlow {
@Inject ExtensionManager extensionManager;
@Inject @ClientId String clientId;
@Inject @PollMessageId String messageId;
@Inject PollAckFlow() {}
@Override
public final EppOutput run() throws EppException {
extensionManager.validate(); // There are no legal extensions for this flow.
validateClientIsLoggedIn(clientId);
if (messageId.isEmpty()) {
throw new MissingMessageIdException();
}

View file

@ -14,6 +14,7 @@
package google.registry.flows.poll;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.poll.PollFlowUtils.getPollMessagesQuery;
import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACK_MESSAGE;
import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_NO_MESSAGES;
@ -22,9 +23,10 @@ import static google.registry.util.CollectionUtils.forceEmptyToNull;
import com.googlecode.objectify.Key;
import google.registry.flows.EppException;
import google.registry.flows.EppException.ParameterValueSyntaxErrorException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.PollMessageId;
import google.registry.flows.LoggedInFlow;
import google.registry.model.eppoutput.EppOutput;
import google.registry.model.poll.MessageQueueInfo;
import google.registry.model.poll.PollMessage;
@ -42,14 +44,17 @@ import javax.inject.Inject;
*
* @error {@link PollRequestFlow.UnexpectedMessageIdException}
*/
public class PollRequestFlow extends LoggedInFlow {
public class PollRequestFlow extends Flow {
@Inject ExtensionManager extensionManager;
@Inject @ClientId String clientId;
@Inject @PollMessageId String messageId;
@Inject PollRequestFlow() {}
@Override
public final EppOutput run() throws EppException {
extensionManager.validate(); // There are no legal extensions for this flow.
validateClientIsLoggedIn(clientId);
if (!messageId.isEmpty()) {
throw new UnexpectedMessageIdException();
}

View file

@ -14,6 +14,8 @@
package google.registry.flows.session;
import google.registry.flows.EppException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.model.eppoutput.EppOutput;
import google.registry.model.eppoutput.Greeting;
@ -22,10 +24,12 @@ import javax.inject.Inject;
/** A flow for an Epp "hello". */
public class HelloFlow extends Flow {
@Inject ExtensionManager extensionManager;
@Inject HelloFlow() {}
@Override
public EppOutput run() {
public EppOutput run() throws EppException {
extensionManager.validate(); // There are no legal extensions for this flow.
return EppOutput.create(Greeting.create(now));
}
}

View file

@ -27,6 +27,7 @@ import google.registry.flows.EppException.ParameterValuePolicyErrorException;
import google.registry.flows.EppException.UnimplementedExtensionException;
import google.registry.flows.EppException.UnimplementedObjectServiceException;
import google.registry.flows.EppException.UnimplementedOptionException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.model.eppcommon.ProtocolDefinition;
@ -68,6 +69,7 @@ public class LoginFlow extends Flow {
/** Maximum number of failed login attempts allowed per connection. */
private static final int MAX_FAILED_LOGIN_ATTEMPTS_PER_CONNECTION = 3;
@Inject ExtensionManager extensionManager;
@Inject @ClientId String clientId;
@Inject LoginFlow() {}
@ -84,6 +86,7 @@ public class LoginFlow extends Flow {
/** Run the flow without bothering to log errors. The {@link #run} method will do that for us. */
public final EppOutput runWithoutLogging() throws EppException {
extensionManager.validate(); // There are no legal extensions for this flow.
Login login = (Login) eppInput.getCommandWrapper().getCommand();
if (!clientId.isEmpty()) {
throw new AlreadyLoggedInException();

View file

@ -14,24 +14,31 @@
package google.registry.flows.session;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.model.eppoutput.Result.Code.SUCCESS_AND_CLOSE;
import google.registry.flows.EppException;
import google.registry.flows.LoggedInFlow;
import google.registry.flows.ExtensionManager;
import google.registry.flows.Flow;
import google.registry.flows.FlowModule.ClientId;
import google.registry.model.eppoutput.EppOutput;
import javax.inject.Inject;
/**
* An EPP flow for logout.
*
* @error {@link google.registry.flows.LoggedInFlow.NotLoggedInException}
* @error {@link google.registry.flows.FlowUtils.NotLoggedInException}
*/
public class LogoutFlow extends LoggedInFlow {
public class LogoutFlow extends Flow {
@Inject ExtensionManager extensionManager;
@Inject @ClientId String clientId;
@Inject LogoutFlow() {}
@Override
public final EppOutput run() throws EppException {
extensionManager.validate(); // There are no legal extensions for this flow.
validateClientIsLoggedIn(clientId);
sessionMetadata.invalidate();
return createOutput(SUCCESS_AND_CLOSE);
}

View file

@ -0,0 +1,218 @@
// Copyright 2016 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.flows;
import static com.google.common.truth.Truth.assertThat;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.testing.TestLogHandler;
import google.registry.flows.EppException.UnimplementedExtensionException;
import google.registry.flows.ExtensionManager.UndeclaredServiceExtensionException;
import google.registry.flows.ExtensionManager.UnsupportedRepeatedExtensionException;
import google.registry.flows.exceptions.OnlyToolCanPassMetadataException;
import google.registry.flows.session.HelloFlow;
import google.registry.model.domain.allocate.AllocateCreateExtension;
import google.registry.model.domain.fee06.FeeInfoCommandExtensionV06;
import google.registry.model.domain.launch.LaunchCreateExtension;
import google.registry.model.domain.metadata.MetadataExtension;
import google.registry.model.eppcommon.ProtocolDefinition.ServiceExtension;
import google.registry.model.eppinput.EppInput;
import google.registry.model.eppinput.EppInput.CommandExtension;
import google.registry.testing.AppEngineRule;
import google.registry.testing.ExceptionRule;
import google.registry.util.TypeUtils;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Unit tests for {@link ExtensionManager}. */
@RunWith(JUnit4.class)
public class ExtensionManagerTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
@Rule
public final ExceptionRule thrown = new ExceptionRule();
@Test
public void testDuplicateExtensionsForbidden() throws Exception {
ExtensionManager manager = new TestInstanceBuilder()
.setEppRequestSource(EppRequestSource.TOOL)
.setDeclaredUris()
.setSuppliedExtensions(
MetadataExtension.class,
LaunchCreateExtension.class,
MetadataExtension.class)
.build();
manager.register(MetadataExtension.class, LaunchCreateExtension.class);
thrown.expect(UnsupportedRepeatedExtensionException.class);
manager.validate();
}
@Test
public void testMultipleExtensionsFromSameGroupForbidden() throws Exception {
ExtensionManager manager = new TestInstanceBuilder()
.setEppRequestSource(EppRequestSource.TOOL)
.setDeclaredUris(ServiceExtension.FEE_0_6.getUri())
.setSuppliedExtensions(
MetadataExtension.class,
LaunchCreateExtension.class,
AllocateCreateExtension.class)
.build();
manager.register(MetadataExtension.class);
manager.registerAsGroup(
ImmutableList.of(LaunchCreateExtension.class, AllocateCreateExtension.class));
thrown.expect(UnsupportedRepeatedExtensionException.class);
manager.validate();
}
@Test
public void testUndeclaredExtensionsLogged() throws Exception {
TestLogHandler handler = new TestLogHandler();
Logger.getLogger(ExtensionManager.class.getCanonicalName()).addHandler(handler);
ExtensionManager manager = new TestInstanceBuilder()
.setEppRequestSource(EppRequestSource.TOOL)
.setDeclaredUris()
.setSuppliedExtensions(MetadataExtension.class)
.build();
manager.register(MetadataExtension.class);
manager.validate();
ImmutableList.Builder<String> logMessages = new ImmutableList.Builder<>();
for (LogRecord record : handler.getStoredLogRecords()) {
logMessages.add(record.getMessage());
}
assertThat(logMessages.build()).contains(
"Client clientId is attempting to run HelloFlow without declaring "
+ "URIs [urn:google:params:xml:ns:metadata-1.0] on login");
}
@Test
public void testBlacklistedExtensions_forbiddenWhenUndeclared() throws Exception {
ExtensionManager manager = new TestInstanceBuilder()
.setEppRequestSource(EppRequestSource.TOOL)
.setDeclaredUris()
.setSuppliedExtensions(FeeInfoCommandExtensionV06.class)
.build();
manager.register(FeeInfoCommandExtensionV06.class);
thrown.expect(UndeclaredServiceExtensionException.class);
manager.validate();
}
@Test
public void testBlacklistedExtensions_allowedWhenDeclared() throws Exception {
ExtensionManager manager = new TestInstanceBuilder()
.setEppRequestSource(EppRequestSource.TOOL)
.setDeclaredUris(ServiceExtension.FEE_0_6.getUri())
.setSuppliedExtensions(FeeInfoCommandExtensionV06.class)
.build();
manager.register(FeeInfoCommandExtensionV06.class);
manager.validate();
}
@Test
public void testMetadataExtension_allowedForToolSource() throws Exception {
ExtensionManager manager = new TestInstanceBuilder()
.setEppRequestSource(EppRequestSource.TOOL)
.setDeclaredUris()
.setSuppliedExtensions(MetadataExtension.class)
.build();
manager.register(MetadataExtension.class);
manager.validate();
}
@Test
public void testMetadataExtension_forbiddenWhenNotToolSource() throws Exception {
ExtensionManager manager = new TestInstanceBuilder()
.setEppRequestSource(EppRequestSource.CONSOLE)
.setDeclaredUris()
.setSuppliedExtensions(MetadataExtension.class)
.build();
manager.register(MetadataExtension.class);
thrown.expect(OnlyToolCanPassMetadataException.class);
manager.validate();
}
@Test
public void testUnimplementedExtensionsForbidden() throws Exception {
ExtensionManager manager = new TestInstanceBuilder()
.setEppRequestSource(EppRequestSource.TOOL)
.setDeclaredUris()
.setSuppliedExtensions(LaunchCreateExtension.class)
.build();
thrown.expect(UnimplementedExtensionException.class);
manager.validate();
}
/** A builder for a test-ready {@link ExtensionManager} instance. */
private static class TestInstanceBuilder {
ExtensionManager manager = new ExtensionManager();
TestInstanceBuilder setEppRequestSource(EppRequestSource eppRequestSource) {
manager.eppRequestSource = eppRequestSource;
return this;
}
TestInstanceBuilder setDeclaredUris(String... declaredUris) {
manager.sessionMetadata =
new StatelessRequestSessionMetadata("clientId", ImmutableSet.copyOf(declaredUris));
return this;
}
@SafeVarargs
final TestInstanceBuilder setSuppliedExtensions(
Class<? extends CommandExtension>... suppliedExtensionClasses) {
manager.eppInput = new FakeEppInput(suppliedExtensionClasses);
return this;
}
ExtensionManager build() {
manager.flowClass = HelloFlow.class;
manager.clientId = manager.sessionMetadata.getClientId();
return manager;
}
}
/** A minimal fake {@link EppInput} that presents the given extensions. */
private static class FakeEppInput extends EppInput {
private final ImmutableList<CommandExtension> suppliedExtensions;
@SafeVarargs
FakeEppInput(Class<? extends CommandExtension>... suppliedExtensionClasses) {
ImmutableList.Builder<CommandExtension> instancesBuilder = new ImmutableList.Builder<>();
for (Class<? extends CommandExtension> clazz : suppliedExtensionClasses) {
instancesBuilder.add(TypeUtils.<CommandExtension>instantiate(clazz));
}
suppliedExtensions = instancesBuilder.build();
}
@Override
public CommandWrapper getCommandWrapper() {
return new CommandWrapper() {
@Override
public ImmutableList<CommandExtension> getExtensions() {
return suppliedExtensions;
}};
}
}
}

View file

@ -25,7 +25,7 @@ import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.googlecode.objectify.Key;
import google.registry.flows.EppException.CommandUseErrorException;
import google.registry.flows.FlowUtils.NotLoggedInException;
import google.registry.model.EppResource;
import google.registry.model.EppResourceUtils;
import google.registry.model.domain.DomainApplication;
@ -114,7 +114,7 @@ public abstract class ResourceFlowTestCase<F extends Flow, R extends EppResource
@Test
public void testRequiresLogin() throws Exception {
sessionMetadata.setClientId(null);
thrown.expect(CommandUseErrorException.class);
thrown.expect(NotLoggedInException.class);
runFlow();
}

View file

@ -54,7 +54,7 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import google.registry.flows.EppException.UnimplementedExtensionException;
import google.registry.flows.EppRequestSource;
import google.registry.flows.LoggedInFlow.UndeclaredServiceExtensionException;
import google.registry.flows.ExtensionManager.UndeclaredServiceExtensionException;
import google.registry.flows.ResourceFlowTestCase;
import google.registry.flows.domain.DomainCreateFlow.DomainHasOpenApplicationsException;
import google.registry.flows.domain.DomainCreateFlow.NoGeneralRegistrationsInCurrentPhaseException;

View file

@ -17,7 +17,7 @@ package google.registry.flows.session;
import static google.registry.testing.DatastoreHelper.createTld;
import google.registry.flows.FlowTestCase;
import google.registry.flows.LoggedInFlow.NotLoggedInException;
import google.registry.flows.FlowUtils.NotLoggedInException;
import org.junit.Before;
import org.junit.Test;