diff --git a/java/google/registry/flows/custom/DomainCreateFlowCustomLogic.java b/java/google/registry/flows/custom/DomainCreateFlowCustomLogic.java index a4e456db5..e0a841379 100644 --- a/java/google/registry/flows/custom/DomainCreateFlowCustomLogic.java +++ b/java/google/registry/flows/custom/DomainCreateFlowCustomLogic.java @@ -15,6 +15,7 @@ package google.registry.flows.custom; import com.google.auto.value.AutoValue; +import com.google.common.collect.ImmutableList; import com.google.common.net.InternetDomainName; import google.registry.flows.EppException; import google.registry.flows.SessionMetadata; @@ -22,6 +23,8 @@ import google.registry.flows.domain.DomainCreateFlow; import google.registry.model.ImmutableObject; import google.registry.model.domain.DomainResource; import google.registry.model.eppinput.EppInput; +import google.registry.model.eppoutput.EppResponse.ResponseData; +import google.registry.model.eppoutput.EppResponse.ResponseExtension; import google.registry.model.reporting.HistoryEntry; /** @@ -60,6 +63,21 @@ public class DomainCreateFlowCustomLogic extends BaseFlowCustomLogic { return parameters.entityChanges(); } + /** + * A hook that runs before the response is returned. + * + *

This takes the {@link ResponseData} and {@link ResponseExtension}s as input and returns + * them, potentially with modifications. + */ + @SuppressWarnings("unused") + public BeforeResponseReturnData beforeResponse(BeforeResponseParameters parameters) + throws EppException { + return BeforeResponseReturnData.newBuilder() + .setResData(parameters.resData()) + .setResponseExtensions(parameters.responseExtensions()) + .build(); + } + /** A class to encapsulate parameters for a call to {@link #afterValidation}. */ @AutoValue public abstract static class AfterValidationParameters extends ImmutableObject { @@ -143,4 +161,56 @@ public class DomainCreateFlowCustomLogic extends BaseFlowCustomLogic { public abstract BeforeSaveParameters build(); } } + + /** A class to encapsulate parameters for a call to {@link #beforeResponse}. */ + @AutoValue + public abstract static class BeforeResponseParameters extends ImmutableObject { + + public abstract ResponseData resData(); + + public abstract ImmutableList responseExtensions(); + + public static BeforeResponseParameters.Builder newBuilder() { + return new AutoValue_DomainCreateFlowCustomLogic_BeforeResponseParameters.Builder(); + } + + /** Builder for {@link DomainCreateFlowCustomLogic.BeforeResponseParameters}. */ + @AutoValue.Builder + public abstract static class Builder { + + public abstract BeforeResponseParameters.Builder setResData(ResponseData resData); + + public abstract BeforeResponseParameters.Builder setResponseExtensions( + ImmutableList responseExtensions); + + public abstract BeforeResponseParameters build(); + } + } + + /** + * A class to encapsulate parameters for the return values from a call to {@link #beforeResponse}. + */ + @AutoValue + public abstract static class BeforeResponseReturnData extends ImmutableObject { + + public abstract ResponseData resData(); + + public abstract ImmutableList responseExtensions(); + + public static BeforeResponseReturnData.Builder newBuilder() { + return new AutoValue_DomainCreateFlowCustomLogic_BeforeResponseReturnData.Builder(); + } + + /** Builder for {@link DomainCreateFlowCustomLogic.BeforeResponseReturnData}. */ + @AutoValue.Builder + public abstract static class Builder { + + public abstract BeforeResponseReturnData.Builder setResData(ResponseData resData); + + public abstract BeforeResponseReturnData.Builder setResponseExtensions( + ImmutableList responseExtensions); + + public abstract BeforeResponseReturnData build(); + } + } } diff --git a/java/google/registry/flows/domain/DomainAllocateFlow.java b/java/google/registry/flows/domain/DomainAllocateFlow.java index d11ffa386..7b78c677e 100644 --- a/java/google/registry/flows/domain/DomainAllocateFlow.java +++ b/java/google/registry/flows/domain/DomainAllocateFlow.java @@ -52,7 +52,7 @@ import google.registry.flows.FlowModule.ClientId; import google.registry.flows.FlowModule.Superuser; import google.registry.flows.FlowModule.TargetId; import google.registry.flows.TransactionalFlow; -import google.registry.flows.domain.TldSpecificLogicProxy.EppCommandOperations; +import google.registry.flows.domain.DomainPricingLogic.EppCommandOperations; import google.registry.model.ImmutableObject; import google.registry.model.billing.BillingEvent; import google.registry.model.billing.BillingEvent.Flag; @@ -113,6 +113,7 @@ public class DomainAllocateFlow implements TransactionalFlow { @Inject HistoryEntry.Builder historyBuilder; @Inject EppInput eppInput; @Inject EppResponse.Builder responseBuilder; + @Inject DomainPricingLogic pricingLogic; @Inject DomainAllocateFlow() {} @Override @@ -389,8 +390,8 @@ public class DomainAllocateFlow implements TransactionalFlow { private ImmutableList createResponseExtensions( DateTime now, Registry registry, int years) throws EppException { - EppCommandOperations commandOperations = TldSpecificLogicProxy.getCreatePrice( - registry, targetId, clientId, now, years, eppInput); + EppCommandOperations commandOperations = + pricingLogic.getCreatePrice(registry, targetId, now, years); FeeCreateCommandExtension feeCreate = eppInput.getSingleExtension(FeeCreateCommandExtension.class); return (feeCreate == null) diff --git a/java/google/registry/flows/domain/DomainApplicationCreateFlow.java b/java/google/registry/flows/domain/DomainApplicationCreateFlow.java index 69064317f..ee315b2ff 100644 --- a/java/google/registry/flows/domain/DomainApplicationCreateFlow.java +++ b/java/google/registry/flows/domain/DomainApplicationCreateFlow.java @@ -64,7 +64,7 @@ import google.registry.flows.custom.DomainApplicationCreateFlowCustomLogic.After import google.registry.flows.custom.DomainApplicationCreateFlowCustomLogic.BeforeResponseParameters; import google.registry.flows.custom.DomainApplicationCreateFlowCustomLogic.BeforeResponseReturnData; import google.registry.flows.custom.EntityChanges; -import google.registry.flows.domain.TldSpecificLogicProxy.EppCommandOperations; +import google.registry.flows.domain.DomainPricingLogic.EppCommandOperations; import google.registry.model.ImmutableObject; import google.registry.model.domain.DomainApplication; import google.registry.model.domain.DomainCommand.Create; @@ -174,6 +174,7 @@ public final class DomainApplicationCreateFlow implements TransactionalFlow { @Inject Trid trid; @Inject EppResponse.Builder responseBuilder; @Inject DomainApplicationCreateFlowCustomLogic customLogic; + @Inject DomainPricingLogic pricingLogic; @Inject DomainApplicationCreateFlow() {} @Override @@ -200,8 +201,8 @@ public final class DomainApplicationCreateFlow implements TransactionalFlow { String tld = domainName.parent().toString(); checkAllowedAccessToTld(clientId, tld); Registry registry = Registry.get(tld); - EppCommandOperations commandOperations = TldSpecificLogicProxy.getCreatePrice( - registry, targetId, clientId, now, command.getPeriod().getValue(), eppInput); + EppCommandOperations commandOperations = + pricingLogic.getCreatePrice(registry, targetId, now, command.getPeriod().getValue()); // Superusers can create reserved domains, force creations on domains that require a claims // notice without specifying a claims key, and override blocks on registering premium domains. verifyUnitIsYears(command.getPeriod()); diff --git a/java/google/registry/flows/domain/DomainCheckFlow.java b/java/google/registry/flows/domain/DomainCheckFlow.java index bec65dc2a..9d17ef325 100644 --- a/java/google/registry/flows/domain/DomainCheckFlow.java +++ b/java/google/registry/flows/domain/DomainCheckFlow.java @@ -110,6 +110,7 @@ public final class DomainCheckFlow implements Flow { @Inject Clock clock; @Inject EppResponse.Builder responseBuilder; @Inject DomainCheckFlowCustomLogic customLogic; + @Inject DomainPricingLogic pricingLogic; @Inject DomainCheckFlow() {} @Override @@ -208,7 +209,8 @@ public final class DomainCheckFlow implements Flow { clientId, feeCheck.getCurrency(), now, - eppInput); + eppInput, + pricingLogic); responseItems.add(builder.setDomainNameIfSupported(domainName).build()); } } diff --git a/java/google/registry/flows/domain/DomainCreateFlow.java b/java/google/registry/flows/domain/DomainCreateFlow.java index 7669f88a0..ca7bf9546 100644 --- a/java/google/registry/flows/domain/DomainCreateFlow.java +++ b/java/google/registry/flows/domain/DomainCreateFlow.java @@ -43,7 +43,6 @@ import static google.registry.model.registry.label.ReservedList.matchesAnchorTen import static google.registry.util.DateTimeUtils.END_OF_TIME; import static google.registry.util.DateTimeUtils.leapSafeAddYears; -import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; @@ -59,8 +58,10 @@ import google.registry.flows.FlowModule.Superuser; import google.registry.flows.FlowModule.TargetId; import google.registry.flows.TransactionalFlow; import google.registry.flows.custom.DomainCreateFlowCustomLogic; +import google.registry.flows.custom.DomainCreateFlowCustomLogic.BeforeResponseParameters; +import google.registry.flows.custom.DomainCreateFlowCustomLogic.BeforeResponseReturnData; import google.registry.flows.custom.EntityChanges; -import google.registry.flows.domain.TldSpecificLogicProxy.EppCommandOperations; +import google.registry.flows.domain.DomainPricingLogic.EppCommandOperations; import google.registry.model.ImmutableObject; import google.registry.model.billing.BillingEvent; import google.registry.model.billing.BillingEvent.Flag; @@ -166,6 +167,7 @@ public class DomainCreateFlow implements TransactionalFlow { @Inject HistoryEntry.Builder historyBuilder; @Inject EppResponse.Builder responseBuilder; @Inject DomainCreateFlowCustomLogic customLogic; + @Inject DomainPricingLogic pricingLogic; @Inject DomainCreateFlow() {} @Override @@ -211,8 +213,8 @@ public class DomainCreateFlow implements TransactionalFlow { FeeCreateCommandExtension feeCreate = eppInput.getSingleExtension(FeeCreateCommandExtension.class); - EppCommandOperations commandOperations = TldSpecificLogicProxy.getCreatePrice( - registry, targetId, clientId, now, years, eppInput); + EppCommandOperations commandOperations = + pricingLogic.getCreatePrice(registry, targetId, now, years); validateFeeChallenge( targetId, registry.getTldStr(), now, feeCreate, commandOperations.getTotalCost()); // Superusers can create reserved domains, force creations on domains that require a claims @@ -293,18 +295,6 @@ public class DomainCreateFlow implements TransactionalFlow { } enqueueTasks(hasSignedMarks, hasClaimsNotice, newDomain); - // TODO: Remove this section and only use the customLogic. - Optional extraFlowLogic = - RegistryExtraFlowLogicProxy.newInstanceForTld(registry.getTldStr()); - if (extraFlowLogic.isPresent()) { - extraFlowLogic.get().performAdditionalDomainCreateLogic( - newDomain, - clientId, - years, - eppInput, - historyEntry); - } - EntityChanges entityChanges = customLogic.beforeSave( DomainCreateFlowCustomLogic.BeforeSaveParameters.newBuilder() @@ -316,9 +306,15 @@ public class DomainCreateFlow implements TransactionalFlow { .build()); persistEntityChanges(entityChanges); + BeforeResponseReturnData responseData = + customLogic.beforeResponse( + BeforeResponseParameters.newBuilder() + .setResData(DomainCreateData.create(targetId, now, registrationExpirationTime)) + .setResponseExtensions(createResponseExtensions(feeCreate, commandOperations)) + .build()); return responseBuilder - .setResData(DomainCreateData.create(targetId, now, registrationExpirationTime)) - .setExtensions(createResponseExtensions(feeCreate, commandOperations)) + .setResData(responseData.resData()) + .setExtensions(responseData.responseExtensions()) .build(); } diff --git a/java/google/registry/flows/domain/DomainFlowUtils.java b/java/google/registry/flows/domain/DomainFlowUtils.java index 4974e4a1d..14987d293 100644 --- a/java/google/registry/flows/domain/DomainFlowUtils.java +++ b/java/google/registry/flows/domain/DomainFlowUtils.java @@ -56,7 +56,7 @@ import google.registry.flows.EppException.ParameterValueSyntaxErrorException; import google.registry.flows.EppException.RequiredParameterMissingException; import google.registry.flows.EppException.StatusProhibitsOperationException; import google.registry.flows.EppException.UnimplementedOptionException; -import google.registry.flows.domain.TldSpecificLogicProxy.EppCommandOperations; +import google.registry.flows.domain.DomainPricingLogic.EppCommandOperations; import google.registry.flows.exceptions.ResourceAlreadyExistsException; import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException; import google.registry.model.EppResource; @@ -589,7 +589,9 @@ public class DomainFlowUtils { String clientId, @Nullable CurrencyUnit topLevelCurrency, DateTime currentDate, - EppInput eppInput) throws EppException { + EppInput eppInput, + DomainPricingLogic pricingLogic) + throws EppException { DateTime now = currentDate; // Use the custom effective date specified in the fee check request, if there is one. if (feeRequest.getEffectiveDate().isPresent()) { @@ -620,14 +622,13 @@ public class DomainFlowUtils { ImmutableList fees = ImmutableList.of(); switch (feeRequest.getCommandName()) { case CREATE: - if (isReserved(domain, isSunrise)) { // Don't return a create price for reserved names. - builder.setClass("reserved"); // Override whatever class we've set above. + if (isReserved(domain, isSunrise)) { // Don't return a create price for reserved names. + builder.setClass("reserved"); // Override whatever class we've set above. builder.setAvailIfSupported(false); builder.setReasonIfSupported("reserved"); } else { builder.setAvailIfSupported(true); - fees = TldSpecificLogicProxy.getCreatePrice( - registry, domainNameString, clientId, now, years, eppInput).getFees(); + fees = pricingLogic.getCreatePrice(registry, domainNameString, now, years).getFees(); } break; case RENEW: diff --git a/java/google/registry/flows/domain/DomainInfoFlow.java b/java/google/registry/flows/domain/DomainInfoFlow.java index 81507a1b5..888994241 100644 --- a/java/google/registry/flows/domain/DomainInfoFlow.java +++ b/java/google/registry/flows/domain/DomainInfoFlow.java @@ -77,6 +77,7 @@ public final class DomainInfoFlow implements Flow { @Inject Clock clock; @Inject EppResponse.Builder responseBuilder; @Inject DomainInfoFlowCustomLogic customLogic; + @Inject DomainPricingLogic pricingLogic; @Inject DomainInfoFlow() {} @@ -145,7 +146,14 @@ public final class DomainInfoFlow implements Flow { if (feeInfo != null) { // Fee check was requested. FeeInfoResponseExtensionV06.Builder builder = new FeeInfoResponseExtensionV06.Builder(); handleFeeRequest( - feeInfo, builder, InternetDomainName.from(targetId), clientId, null, now, eppInput); + feeInfo, + builder, + InternetDomainName.from(targetId), + clientId, + null, + now, + eppInput, + pricingLogic); extensions.add(builder.build()); } // If the TLD uses the flags extension, add it to the info response. diff --git a/java/google/registry/model/eppoutput/CreateData.java b/java/google/registry/model/eppoutput/CreateData.java index 96529cc23..7893a2478 100644 --- a/java/google/registry/model/eppoutput/CreateData.java +++ b/java/google/registry/model/eppoutput/CreateData.java @@ -63,6 +63,18 @@ public abstract class CreateData implements ResponseData { instance.expirationDate = expirationDate; return instance; } + + public String name() { + return name; + } + + public DateTime creationDate() { + return creationDate; + } + + public DateTime expirationDate() { + return expirationDate; + } } /** An acknowledgment message indicating that a host was created. */ diff --git a/javatests/google/registry/flows/EppTestComponent.java b/javatests/google/registry/flows/EppTestComponent.java index 7bed382c9..f56ea4979 100644 --- a/javatests/google/registry/flows/EppTestComponent.java +++ b/javatests/google/registry/flows/EppTestComponent.java @@ -23,7 +23,8 @@ import dagger.Provides; import dagger.Subcomponent; import google.registry.config.ConfigModule; import google.registry.dns.DnsQueue; -import google.registry.flows.custom.CustomLogicFactoryModule; +import google.registry.flows.custom.CustomLogicFactory; +import google.registry.flows.custom.TestCustomLogicFactory; import google.registry.monitoring.whitebox.BigQueryMetricsEnqueuer; import google.registry.monitoring.whitebox.EppMetric; import google.registry.request.RequestScope; @@ -38,7 +39,6 @@ import javax.inject.Singleton; @Component( modules = { ConfigModule.class, - CustomLogicFactoryModule.class, EppTestComponent.FakesAndMocksModule.class }) interface EppTestComponent { @@ -94,6 +94,11 @@ interface EppTestComponent { BigQueryMetricsEnqueuer provideBigQueryMetricsEnqueuer() { return metricsEnqueuer; } + + @Provides + CustomLogicFactory provideCustomLogicFactory() { + return new TestCustomLogicFactory(); + } } /** Subcomponent for request scoped injections. */ diff --git a/javatests/google/registry/flows/custom/TestCustomLogicFactory.java b/javatests/google/registry/flows/custom/TestCustomLogicFactory.java new file mode 100644 index 000000000..665ddde35 --- /dev/null +++ b/javatests/google/registry/flows/custom/TestCustomLogicFactory.java @@ -0,0 +1,40 @@ +// 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.custom; + +import google.registry.flows.SessionMetadata; +import google.registry.model.eppinput.EppInput; + +/** A custom logic factory for testing. */ +public class TestCustomLogicFactory extends CustomLogicFactory { + + @Override + public DomainPricingCustomLogic forDomainPricing( + EppInput eppInput, SessionMetadata sessionMetadata) { + return new TestDomainPricingCustomLogic(eppInput, sessionMetadata); + } + + @Override + public DomainCreateFlowCustomLogic forDomainCreateFlow( + EppInput eppInput, SessionMetadata sessionMetadata) { + return new TestDomainCreateFlowCustomLogic(eppInput, sessionMetadata); + } + + @Override + public DomainApplicationCreateFlowCustomLogic forDomainApplicationCreateFlow( + EppInput eppInput, SessionMetadata sessionMetadata) { + return new TestDomainApplicationCreateFlowCustomLogic(eppInput, sessionMetadata); + } +} diff --git a/javatests/google/registry/flows/custom/TestDomainApplicationCreateFlowCustomLogic.java b/javatests/google/registry/flows/custom/TestDomainApplicationCreateFlowCustomLogic.java new file mode 100644 index 000000000..6b26d2551 --- /dev/null +++ b/javatests/google/registry/flows/custom/TestDomainApplicationCreateFlowCustomLogic.java @@ -0,0 +1,63 @@ +// 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.custom; + +import com.google.common.base.Joiner; +import com.google.common.net.InternetDomainName; +import google.registry.flows.SessionMetadata; +import google.registry.flows.domain.DomainApplicationCreateFlow; +import google.registry.model.domain.flags.FlagsCreateCommandExtension; +import google.registry.model.eppinput.EppInput; +import google.registry.model.eppoutput.CreateData.DomainCreateData; + +/** A class to customize {@link DomainApplicationCreateFlow} for testing. */ +public class TestDomainApplicationCreateFlowCustomLogic + extends DomainApplicationCreateFlowCustomLogic { + + protected TestDomainApplicationCreateFlowCustomLogic( + EppInput eppInput, SessionMetadata sessionMetadata) { + super(eppInput, sessionMetadata); + } + + private String getTld() { + return InternetDomainName.from(getEppInput().getTargetIds().get(0)).parent().toString(); + } + + @Override + public BeforeResponseReturnData beforeResponse(BeforeResponseParameters parameters) { + if (getTld().equals("flags")) { + String flagsPrefix = + Joiner.on('-') + .join(getEppInput().getSingleExtension(FlagsCreateCommandExtension.class).getFlags()); + + DomainCreateData resData = (DomainCreateData) parameters.resData(); + resData = + DomainCreateData.create( + Joiner.on('-').join(flagsPrefix, resData.name()), + resData.creationDate(), + resData.expirationDate()); + + return BeforeResponseReturnData.newBuilder() + .setResData(resData) + .setResponseExtensions(parameters.responseExtensions()) + .build(); + } else { + return BeforeResponseReturnData.newBuilder() + .setResData(parameters.resData()) + .setResponseExtensions(parameters.responseExtensions()) + .build(); + } + } +} diff --git a/javatests/google/registry/flows/custom/TestDomainCreateFlowCustomLogic.java b/javatests/google/registry/flows/custom/TestDomainCreateFlowCustomLogic.java new file mode 100644 index 000000000..f3ccba6e7 --- /dev/null +++ b/javatests/google/registry/flows/custom/TestDomainCreateFlowCustomLogic.java @@ -0,0 +1,61 @@ +// 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.custom; + +import com.google.common.base.Joiner; +import com.google.common.net.InternetDomainName; +import google.registry.flows.SessionMetadata; +import google.registry.flows.domain.DomainCreateFlow; +import google.registry.model.domain.flags.FlagsCreateCommandExtension; +import google.registry.model.eppinput.EppInput; +import google.registry.model.eppoutput.CreateData.DomainCreateData; + +/** A class to customize {@link DomainCreateFlow} for testing. */ +public class TestDomainCreateFlowCustomLogic extends DomainCreateFlowCustomLogic { + + protected TestDomainCreateFlowCustomLogic(EppInput eppInput, SessionMetadata sessionMetadata) { + super(eppInput, sessionMetadata); + } + + private String getTld() { + return InternetDomainName.from(getEppInput().getTargetIds().get(0)).parent().toString(); + } + + @Override + public BeforeResponseReturnData beforeResponse(BeforeResponseParameters parameters) { + if (getTld().equals("flags")) { + String flagsPrefix = + Joiner.on('-') + .join(getEppInput().getSingleExtension(FlagsCreateCommandExtension.class).getFlags()); + + DomainCreateData resData = (DomainCreateData) parameters.resData(); + resData = + DomainCreateData.create( + Joiner.on('-').join(flagsPrefix, resData.name()), + resData.creationDate(), + resData.expirationDate()); + + return BeforeResponseReturnData.newBuilder() + .setResData(resData) + .setResponseExtensions(parameters.responseExtensions()) + .build(); + } else { + return BeforeResponseReturnData.newBuilder() + .setResData(parameters.resData()) + .setResponseExtensions(parameters.responseExtensions()) + .build(); + } + } +} diff --git a/javatests/google/registry/flows/custom/TestDomainPricingCustomLogic.java b/javatests/google/registry/flows/custom/TestDomainPricingCustomLogic.java new file mode 100644 index 000000000..e6bd1357b --- /dev/null +++ b/javatests/google/registry/flows/custom/TestDomainPricingCustomLogic.java @@ -0,0 +1,73 @@ +// 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.custom; + +import static com.google.common.base.Preconditions.checkArgument; + +import com.google.common.base.Ascii; +import com.google.common.base.Splitter; +import com.google.common.collect.Iterables; +import com.google.common.net.InternetDomainName; +import google.registry.flows.EppException; +import google.registry.flows.SessionMetadata; +import google.registry.flows.domain.DomainPricingLogic; +import google.registry.model.domain.fee.BaseFee; +import google.registry.model.domain.fee.BaseFee.FeeType; +import google.registry.model.domain.fee.Credit; +import google.registry.model.domain.fee.Fee; +import google.registry.model.eppinput.EppInput; +import java.math.BigDecimal; +import java.util.List; + +/** A class to customize {@link DomainPricingLogic} for testing. */ +public class TestDomainPricingCustomLogic extends DomainPricingCustomLogic { + + protected TestDomainPricingCustomLogic(EppInput eppInput, SessionMetadata sessionMetadata) { + super(eppInput, sessionMetadata); + } + + private static BaseFee domainNameToFeeOrCredit(InternetDomainName domainName) { + // The second-level domain should be of the form "description-price", where description is the + // description string of the fee or credit, and price is the price (credit if negative, fee + // otherwise). To make sure this is a valid domain name, don't use any spaces, and limit prices + // to integers. Don't use a two-character description for credits, since it is illegal to have + // both the third and fourth characters of a domain name label be hyphens. + List components = + Splitter.on('-') + .limit(2) + .splitToList(Iterables.getFirst(Splitter.on('.').split(domainName.toString()), "")); + checkArgument(components.size() == 2, "Domain name must be of the form description-price.tld"); + int price = Integer.parseInt(components.get(1)); + if (price < 0) { + return Credit.create( + new BigDecimal(price), FeeType.valueOf(Ascii.toUpperCase(components.get(0)))); + } else { + return Fee.create( + new BigDecimal(price), FeeType.valueOf(Ascii.toUpperCase(components.get(0)))); + } + } + + /** A hook that customizes create price. */ + @Override + public BaseFee customizeCreatePrice(CreatePriceParameters createPriceParameters) + throws EppException { + InternetDomainName domainName = createPriceParameters.domainName(); + if (domainName.parent().toString().equals("flags")) { + return domainNameToFeeOrCredit(domainName); + } else { + return createPriceParameters.createFee(); + } + } +} diff --git a/javatests/google/registry/flows/domain/DomainApplicationCreateFlowTest.java b/javatests/google/registry/flows/domain/DomainApplicationCreateFlowTest.java index 2db1dcd53..7f85a89d1 100644 --- a/javatests/google/registry/flows/domain/DomainApplicationCreateFlowTest.java +++ b/javatests/google/registry/flows/domain/DomainApplicationCreateFlowTest.java @@ -105,13 +105,13 @@ import google.registry.flows.exceptions.ResourceAlreadyExistsException; import google.registry.model.domain.DomainApplication; import google.registry.model.domain.GracePeriod; import google.registry.model.domain.LrpTokenEntity; -import google.registry.model.domain.TestExtraLogicManager; -import google.registry.model.domain.TestExtraLogicManager.TestExtraLogicManagerSuccessException; import google.registry.model.domain.launch.ApplicationStatus; import google.registry.model.domain.launch.LaunchNotice; import google.registry.model.domain.launch.LaunchPhase; import google.registry.model.domain.rgp.GracePeriodStatus; import google.registry.model.domain.secdns.DelegationSignerData; +import google.registry.model.eppoutput.CreateData.DomainCreateData; +import google.registry.model.eppoutput.EppOutput; import google.registry.model.registrar.Registrar; import google.registry.model.registry.Registry; import google.registry.model.registry.Registry.TldState; @@ -158,7 +158,6 @@ public class DomainApplicationCreateFlowTest createTld("tld", TldState.SUNRISE); persistResource(Registry.get("tld").asBuilder().setReservedLists(createReservedList()).build()); createTld("flags", TldState.LANDRUSH); - RegistryExtraFlowLogicProxy.setOverride("flags", TestExtraLogicManager.class); persistResource( Registry.get("flags").asBuilder().setReservedLists(createReservedList()).build()); inject.setStaticField(TmchCertificateAuthority.class, "clock", clock); @@ -1705,7 +1704,9 @@ public class DomainApplicationCreateFlowTest public void testSuccess_flags() throws Exception { persistContactsAndHosts(); setEppInput("domain_create_landrush_flags.xml", ImmutableMap.of("FEE", "42")); - thrown.expect(TestExtraLogicManagerSuccessException.class, "flag1,flag2"); - runFlow(); + EppOutput eppOutput = runFlow(); + String domainNameWithFlagsPrefix = + ((DomainCreateData) eppOutput.getResponse().getResponseData().get(0)).name(); + assertThat(domainNameWithFlagsPrefix).isEqualTo("flag1-flag2-create-42.flags"); } } diff --git a/javatests/google/registry/flows/domain/DomainCreateFlowTest.java b/javatests/google/registry/flows/domain/DomainCreateFlowTest.java index 12923652a..84ab38458 100644 --- a/javatests/google/registry/flows/domain/DomainCreateFlowTest.java +++ b/javatests/google/registry/flows/domain/DomainCreateFlowTest.java @@ -109,13 +109,13 @@ import google.registry.model.billing.BillingEvent.Reason; import google.registry.model.domain.DomainResource; import google.registry.model.domain.GracePeriod; import google.registry.model.domain.LrpTokenEntity; -import google.registry.model.domain.TestExtraLogicManager; -import google.registry.model.domain.TestExtraLogicManager.TestExtraLogicManagerSuccessException; import google.registry.model.domain.launch.ApplicationStatus; import google.registry.model.domain.launch.LaunchNotice; import google.registry.model.domain.rgp.GracePeriodStatus; import google.registry.model.domain.secdns.DelegationSignerData; import google.registry.model.eppcommon.StatusValue; +import google.registry.model.eppoutput.CreateData.DomainCreateData; +import google.registry.model.eppoutput.EppOutput; import google.registry.model.registrar.Registrar; import google.registry.model.registry.Registry; import google.registry.model.registry.Registry.TldState; @@ -151,7 +151,6 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase