From b783acfcc677c53d58d4b01421ab52a1c6a18edd Mon Sep 17 00:00:00 2001 From: jianglai Date: Thu, 22 Sep 2016 13:07:21 -0700 Subject: [PATCH] Support date and notAfter in fee extension response v12 When custom effective date is passed in the check command, the response should contain that date as an acknowledgemant that the check is performed at a time different from now. Also when the fee(s) returned contains a validDateRange (i. e. EAP fees that are only valid during a certain period), the response will contain a notAfter field which is the date after which the quoted fee(s) are no longer valid. (i. e. the earliest of the end dates of all fees that would expire. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=133989775 --- .../flows/domain/DomainCheckFlow.java | 4 +- .../flows/domain/DomainFlowUtils.java | 53 +++++++++++++------ .../registry/flows/domain/DomainInfoFlow.java | 2 +- .../registry/model/domain/fee/BaseFee.java | 5 ++ .../fee/FeeQueryResponseExtensionItem.java | 9 +++- .../FeeCheckResponseExtensionItemV06.java | 12 +++++ .../fee06/FeeInfoResponseExtensionV06.java | 11 ++++ .../FeeCheckResponseExtensionItemV11.java | 11 ++++ ...eCheckResponseExtensionItemCommandV12.java | 26 +++++++-- .../FeeCheckResponseExtensionItemV12.java | 13 +++++ .../flows/domain/DomainCheckFlowTest.java | 9 +++- ...domain_check_eap_fee_response_date_v12.xml | 6 +++ .../domain_check_eap_fee_response_v12.xml | 3 ++ 13 files changed, 139 insertions(+), 25 deletions(-) diff --git a/java/google/registry/flows/domain/DomainCheckFlow.java b/java/google/registry/flows/domain/DomainCheckFlow.java index 4cf163b75..e7c6544da 100644 --- a/java/google/registry/flows/domain/DomainCheckFlow.java +++ b/java/google/registry/flows/domain/DomainCheckFlow.java @@ -187,9 +187,7 @@ public final class DomainCheckFlow extends LoggedInFlow { domainNames.get(domainName), clientId, feeCheck.getCurrency(), - feeCheckItem.getEffectiveDate().isPresent() - ? feeCheckItem.getEffectiveDate().get() - : now, + now, eppInput); responseItems.add(builder.setDomainNameIfSupported(domainName).build()); } diff --git a/java/google/registry/flows/domain/DomainFlowUtils.java b/java/google/registry/flows/domain/DomainFlowUtils.java index 393a1775e..74de4f651 100644 --- a/java/google/registry/flows/domain/DomainFlowUtils.java +++ b/java/google/registry/flows/domain/DomainFlowUtils.java @@ -27,6 +27,7 @@ import static google.registry.model.registry.label.ReservedList.getReservation; import static google.registry.pricing.PricingEngineProxy.getPricesForDomainName; import static google.registry.tldconfig.idn.IdnLabelValidator.findValidIdnTableForTld; import static google.registry.util.CollectionUtils.nullToEmpty; +import static google.registry.util.DateTimeUtils.END_OF_TIME; import static google.registry.util.DateTimeUtils.isAtOrAfter; import static google.registry.util.DomainNameUtils.ACE_PREFIX; @@ -64,8 +65,6 @@ import google.registry.model.domain.DomainResource; import google.registry.model.domain.Period; import google.registry.model.domain.fee.Credit; import google.registry.model.domain.fee.Fee; -import google.registry.model.domain.fee.FeeCheckCommandExtensionItem; -import google.registry.model.domain.fee.FeeCheckResponseExtensionItem; import google.registry.model.domain.fee.FeeQueryCommandExtensionItem; import google.registry.model.domain.fee.FeeQueryResponseExtensionItem; import google.registry.model.domain.fee.FeeTransformCommandExtension; @@ -570,8 +569,8 @@ public class DomainFlowUtils { } /** - * Validates a {@link FeeCheckCommandExtensionItem} and sets the appropriate fields on a - * {@link FeeCheckResponseExtensionItem} builder. + * Validates a {@link FeeQueryCommandExtensionItem} and sets the appropriate fields on a {@link + * FeeQueryResponseExtensionItem} builder. */ static void handleFeeRequest( FeeQueryCommandExtensionItem feeRequest, @@ -579,8 +578,14 @@ public class DomainFlowUtils { InternetDomainName domain, String clientId, @Nullable CurrencyUnit topLevelCurrency, - DateTime now, + DateTime currentDate, EppInput eppInput) throws EppException { + DateTime now = currentDate; + // Use the custom effective date specified in the fee check request, if there is one. + if (feeRequest.getEffectiveDate().isPresent()) { + now = feeRequest.getEffectiveDate().get(); + builder.setEffectiveDateIfSupported(now); + } String domainNameString = domain.toString(); Registry registry = Registry.get(domain.parent().toString()); int years = verifyUnitIsYears(feeRequest.getPeriod()).getValue(); @@ -602,6 +607,7 @@ public class DomainFlowUtils { .setPeriod(feeRequest.getPeriod()) .setClass(TldSpecificLogicProxy.getFeeClass(domainNameString, now).orNull()); + List fees = ImmutableList.of(); switch (feeRequest.getCommandName()) { case CREATE: if (isReserved(domain, isSunrise)) { // Don't return a create price for reserved names. @@ -610,36 +616,53 @@ public class DomainFlowUtils { builder.setReasonIfSupported("reserved"); } else { builder.setAvailIfSupported(true); - builder.setFees(TldSpecificLogicProxy.getCreatePrice( - registry, domainNameString, clientId, now, years, eppInput).getFees()); + fees = TldSpecificLogicProxy.getCreatePrice( + registry, domainNameString, clientId, now, years, eppInput).getFees(); } break; case RENEW: builder.setAvailIfSupported(true); - builder.setFees(TldSpecificLogicProxy.getRenewPrice( - registry, domainNameString, clientId, now, years, eppInput).getFees()); + fees = TldSpecificLogicProxy.getRenewPrice( + registry, domainNameString, clientId, now, years, eppInput).getFees(); break; case RESTORE: if (years != 1) { throw new RestoresAreAlwaysForOneYearException(); } builder.setAvailIfSupported(true); - builder.setFees(TldSpecificLogicProxy.getRestorePrice( - registry, domainNameString, clientId, now, eppInput).getFees()); + fees = TldSpecificLogicProxy.getRestorePrice( + registry, domainNameString, clientId, now, eppInput).getFees(); break; case TRANSFER: builder.setAvailIfSupported(true); - builder.setFees(TldSpecificLogicProxy.getTransferPrice( - registry, domainNameString, clientId, now, years, eppInput).getFees()); + fees = TldSpecificLogicProxy.getTransferPrice( + registry, domainNameString, clientId, now, years, eppInput).getFees(); break; case UPDATE: builder.setAvailIfSupported(true); - builder.setFees(TldSpecificLogicProxy.getUpdatePrice( - registry, domainNameString, clientId, now, eppInput).getFees()); + fees = TldSpecificLogicProxy.getUpdatePrice( + registry, domainNameString, clientId, now, eppInput).getFees(); break; default: throw new UnknownFeeCommandException(feeRequest.getUnparsedCommandName()); } + + // Set the fees, and based on the validDateRange of the fees, set the notAfterDate. + if (!fees.isEmpty()) { + builder.setFees(fees); + DateTime notAfterDate = null; + for (Fee fee : fees) { + if (fee.hasValidDateRange()) { + DateTime endDate = fee.getValidDateRange().upperEndpoint(); + if (notAfterDate == null || notAfterDate.isAfter(endDate)) { + notAfterDate = endDate; + } + } + } + if (notAfterDate != null && !notAfterDate.equals(END_OF_TIME)) { + builder.setNotAfterDateIfSupported(notAfterDate); + } + } } public static void validateFeeChallenge( diff --git a/java/google/registry/flows/domain/DomainInfoFlow.java b/java/google/registry/flows/domain/DomainInfoFlow.java index cd7e8264a..af860ae19 100644 --- a/java/google/registry/flows/domain/DomainInfoFlow.java +++ b/java/google/registry/flows/domain/DomainInfoFlow.java @@ -128,7 +128,7 @@ public final class DomainInfoFlow extends LoggedInFlow { InternetDomainName.from(targetId), clientId, null, - feeInfo.getEffectiveDate().isPresent() ? feeInfo.getEffectiveDate().get() : now, + now, eppInput); extensions.add(builder.build()); } diff --git a/java/google/registry/model/domain/fee/BaseFee.java b/java/google/registry/model/domain/fee/BaseFee.java index 2967209ea..f8aa6d610 100644 --- a/java/google/registry/model/domain/fee/BaseFee.java +++ b/java/google/registry/model/domain/fee/BaseFee.java @@ -118,6 +118,11 @@ public abstract class BaseFee extends ImmutableObject { public boolean hasValidDateRange() { return validDateRange != null; } + + public Range getValidDateRange() { + checkState(hasValidDateRange()); + return validDateRange; + } protected void generateDescription(Object... args) { checkState(type != null); diff --git a/java/google/registry/model/domain/fee/FeeQueryResponseExtensionItem.java b/java/google/registry/model/domain/fee/FeeQueryResponseExtensionItem.java index 0f46b8fac..0a252ef8f 100644 --- a/java/google/registry/model/domain/fee/FeeQueryResponseExtensionItem.java +++ b/java/google/registry/model/domain/fee/FeeQueryResponseExtensionItem.java @@ -18,6 +18,7 @@ import google.registry.model.domain.Period; import google.registry.model.domain.fee.FeeQueryCommandExtensionItem.CommandName; import java.util.List; import org.joda.money.CurrencyUnit; +import org.joda.time.DateTime; /** * Interface for individual query items in Check and Info response. Each item indicates the fees and @@ -50,10 +51,16 @@ public interface FeeQueryResponseExtensionItem { /** The reason that the check item cannot be calculated. */ public Builder setReasonIfSupported(String reason); + /** The effective date that the check is run on. */ + public Builder setEffectiveDateIfSupported(DateTime effectiveDate); + + /** The date after which the quoted fees are no longer valid. */ + public Builder setNotAfterDateIfSupported(DateTime notAfterDate); + public Builder setCommand(CommandName commandName, String phase, String subphase); public Builder setPeriod(Period period); - + public Builder setFees(List fees); public Builder setClass(String feeClass); diff --git a/java/google/registry/model/domain/fee06/FeeCheckResponseExtensionItemV06.java b/java/google/registry/model/domain/fee06/FeeCheckResponseExtensionItemV06.java index 17de4550f..1377aa468 100644 --- a/java/google/registry/model/domain/fee06/FeeCheckResponseExtensionItemV06.java +++ b/java/google/registry/model/domain/fee06/FeeCheckResponseExtensionItemV06.java @@ -18,6 +18,7 @@ import google.registry.model.domain.fee.FeeCheckResponseExtensionItem; import google.registry.model.domain.fee.FeeQueryResponseExtensionItemImpl; import javax.xml.bind.annotation.XmlType; import org.joda.money.CurrencyUnit; +import org.joda.time.DateTime; /** The version 0.6 response for a domain check on a single resource. */ @XmlType(propOrder = {"name", "currency", "command", "period", "fee", "feeClass"}) @@ -54,5 +55,16 @@ public class FeeCheckResponseExtensionItemV06 public Builder setReasonIfSupported(String reason) { return this; } + + @Override + public Builder setEffectiveDateIfSupported(DateTime effectiveDate) { + return this; + } + + @Override + public Builder setNotAfterDateIfSupported(DateTime notAfterDate) { + return this; + } + } } diff --git a/java/google/registry/model/domain/fee06/FeeInfoResponseExtensionV06.java b/java/google/registry/model/domain/fee06/FeeInfoResponseExtensionV06.java index bf11f1c8f..c51fe8e4c 100644 --- a/java/google/registry/model/domain/fee06/FeeInfoResponseExtensionV06.java +++ b/java/google/registry/model/domain/fee06/FeeInfoResponseExtensionV06.java @@ -20,6 +20,7 @@ import google.registry.model.eppoutput.EppResponse.ResponseExtension; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; import org.joda.money.CurrencyUnit; +import org.joda.time.DateTime; /** * An XML data object that represents a fee extension that may be present on the response to EPP @@ -52,5 +53,15 @@ public class FeeInfoResponseExtensionV06 getInstance().currency = currency; return this; } + + @Override + public Builder setEffectiveDateIfSupported(DateTime effectiveDate) { + return this; + } + + @Override + public Builder setNotAfterDateIfSupported(DateTime notAfterDate) { + return this; + } } } diff --git a/java/google/registry/model/domain/fee11/FeeCheckResponseExtensionItemV11.java b/java/google/registry/model/domain/fee11/FeeCheckResponseExtensionItemV11.java index 03a45da12..edd3759b3 100644 --- a/java/google/registry/model/domain/fee11/FeeCheckResponseExtensionItemV11.java +++ b/java/google/registry/model/domain/fee11/FeeCheckResponseExtensionItemV11.java @@ -20,6 +20,7 @@ import google.registry.model.domain.fee.FeeQueryResponseExtensionItemImpl; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlType; import org.joda.money.CurrencyUnit; +import org.joda.time.DateTime; /** The version 0.11 response for a domain check on a single resource. */ @XmlType(propOrder = {"object", "command", "currency", "period", "fee", "feeClass", "reason"}) @@ -66,5 +67,15 @@ public class FeeCheckResponseExtensionItemV11 getInstance().reason = reason; return this; } + + @Override + public Builder setEffectiveDateIfSupported(DateTime effectiveDate) { + return this; + } + + @Override + public Builder setNotAfterDateIfSupported(DateTime notAfterDate) { + return this; + } } } diff --git a/java/google/registry/model/domain/fee12/FeeCheckResponseExtensionItemCommandV12.java b/java/google/registry/model/domain/fee12/FeeCheckResponseExtensionItemCommandV12.java index 66d45cf1a..593363eab 100644 --- a/java/google/registry/model/domain/fee12/FeeCheckResponseExtensionItemCommandV12.java +++ b/java/google/registry/model/domain/fee12/FeeCheckResponseExtensionItemCommandV12.java @@ -27,11 +27,10 @@ import java.util.List; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; +import org.joda.time.DateTime; -/** - * The version 0.12 response command entity for a domain check on a single resource. - */ -@XmlType(propOrder = {"period", "fee", "feeClass"}) +/** The version 0.12 response command entity for a domain check on a single resource. */ +@XmlType(propOrder = {"period", "fee", "feeClass", "effectiveDate", "notAfterDate"}) public class FeeCheckResponseExtensionItemCommandV12 extends ImmutableObject { /** The command that was checked. */ @@ -63,6 +62,15 @@ public class FeeCheckResponseExtensionItemCommandV12 extends ImmutableObject { */ @XmlElement(name = "class") String feeClass; + + /** The effective date that the check is to be performed on (if specified in the query). */ + @XmlElement(name = "date") + DateTime effectiveDate; + + /** The date after which the quoted fee is no longer valid (if applicable). */ + @XmlElement(name = "notAfter") + DateTime notAfterDate; + public String getFeeClass() { return feeClass; @@ -92,6 +100,16 @@ public class FeeCheckResponseExtensionItemCommandV12 extends ImmutableObject { return this; } + public Builder setEffectiveDate(DateTime effectiveDate) { + getInstance().effectiveDate = effectiveDate; + return this; + } + + public Builder setNotAfterDate(DateTime notAfterDate) { + getInstance().notAfterDate = notAfterDate; + return this; + } + public Builder setFee(List fees) { getInstance().fee = forceEmptyToNull(ImmutableList.copyOf(fees)); return this; diff --git a/java/google/registry/model/domain/fee12/FeeCheckResponseExtensionItemV12.java b/java/google/registry/model/domain/fee12/FeeCheckResponseExtensionItemV12.java index fc957009b..2a5599e3e 100644 --- a/java/google/registry/model/domain/fee12/FeeCheckResponseExtensionItemV12.java +++ b/java/google/registry/model/domain/fee12/FeeCheckResponseExtensionItemV12.java @@ -27,6 +27,7 @@ import google.registry.model.domain.fee.FeeQueryCommandExtensionItem.CommandName import java.util.List; import javax.xml.bind.annotation.XmlType; import org.joda.money.CurrencyUnit; +import org.joda.time.DateTime; /** * The version 0.12 response for a domain check on a single resource. @@ -111,5 +112,17 @@ public class FeeCheckResponseExtensionItemV12 getInstance().command = commandBuilder.build(); return super.build(); } + + @Override + public Builder setEffectiveDateIfSupported(DateTime effectiveDate) { + commandBuilder.setEffectiveDate(effectiveDate); + return this; + } + + @Override + public Builder setNotAfterDateIfSupported(DateTime notAfterDate) { + commandBuilder.setNotAfterDate(notAfterDate); + return this; + } } } diff --git a/javatests/google/registry/flows/domain/DomainCheckFlowTest.java b/javatests/google/registry/flows/domain/DomainCheckFlowTest.java index 169943bbf..7c657236f 100644 --- a/javatests/google/registry/flows/domain/DomainCheckFlowTest.java +++ b/javatests/google/registry/flows/domain/DomainCheckFlowTest.java @@ -60,6 +60,7 @@ import org.joda.money.CurrencyUnit; import org.joda.money.Money; import org.joda.time.DateTime; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; /** Unit tests for {@link DomainCheckFlow}. */ @@ -803,5 +804,11 @@ public class DomainCheckFlowTest runEapFeeCheckTest("domain_check_fee_date_v12.xml", "domain_check_eap_fee_response_date_v12.xml"); } - + + @Ignore + @Test + public void testSuccess_feeCheck_multipleRanges() throws Exception { + // TODO: If at some point we have more than one type of fees that are time dependent, populate + // this test to test if the notAfter date is the earliest of the end points of the ranges. + } } diff --git a/javatests/google/registry/flows/domain/testdata/domain_check_eap_fee_response_date_v12.xml b/javatests/google/registry/flows/domain/testdata/domain_check_eap_fee_response_date_v12.xml index f41e225c4..316179cdb 100644 --- a/javatests/google/registry/flows/domain/testdata/domain_check_eap_fee_response_date_v12.xml +++ b/javatests/google/registry/flows/domain/testdata/domain_check_eap_fee_response_date_v12.xml @@ -29,6 +29,8 @@ 1 13.00 50.00 + 2010-01-02T13:22:21Z + 2010-01-03T10:00:00.000Z @@ -39,6 +41,8 @@ 1 13.00 50.00 + 2010-01-02T13:22:21Z + 2010-01-03T10:00:00.000Z @@ -49,6 +53,8 @@ 1 13.00 50.00 + 2010-01-02T13:22:21Z + 2010-01-03T10:00:00.000Z diff --git a/javatests/google/registry/flows/domain/testdata/domain_check_eap_fee_response_v12.xml b/javatests/google/registry/flows/domain/testdata/domain_check_eap_fee_response_v12.xml index c6664c581..b1a6a3e54 100644 --- a/javatests/google/registry/flows/domain/testdata/domain_check_eap_fee_response_v12.xml +++ b/javatests/google/registry/flows/domain/testdata/domain_check_eap_fee_response_v12.xml @@ -29,6 +29,7 @@ 1 13.00 100.00 + 2010-01-02T10:00:00.000Z @@ -39,6 +40,7 @@ 1 13.00 100.00 + 2010-01-02T10:00:00.000Z @@ -49,6 +51,7 @@ 1 13.00 100.00 + 2010-01-02T10:00:00.000Z