From 1a63d50b8283b35f380a1c058870b90392f152f1 Mon Sep 17 00:00:00 2001 From: gbrodman Date: Fri, 18 Sep 2020 13:22:29 -0400 Subject: [PATCH] Create a separate per-tld registry lock/unlock cost (#800) * Create a separate per-tld registry lock/unlock cost Currently we use the standard server status change cost for this, but this might not be ideal at some point in the future if we wish to allow manual forced updates outside of the standard registry lock system (we would charge for these manual forced updates, even if we don't charge for registry locks). * Remove period --- .../registry/model/registry/Registry.java | 18 ++++++++++++++++++ .../tools/CreateOrUpdateTldCommand.java | 8 ++++++++ .../google/registry/tools/DomainLockUtils.java | 2 +- .../flows/domain/DomainRenewFlowTest.java | 3 +++ .../domain/DomainRestoreRequestFlowTest.java | 1 + .../registry/tools/CreateTldCommandTest.java | 14 ++++++++++++++ .../registry/tools/DomainLockUtilsTest.java | 2 +- .../registry/tools/UpdateTldCommandTest.java | 14 ++++++++------ .../RegistryLockVerifyActionTest.java | 2 +- .../resources/google/registry/model/schema.txt | 1 + 10 files changed, 56 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/google/registry/model/registry/Registry.java b/core/src/main/java/google/registry/model/registry/Registry.java index 64819879a..dab5f7499 100644 --- a/core/src/main/java/google/registry/model/registry/Registry.java +++ b/core/src/main/java/google/registry/model/registry/Registry.java @@ -133,6 +133,7 @@ public class Registry extends ImmutableObject implements Buildable { public static final Money DEFAULT_RENEW_BILLING_COST = Money.of(USD, 8); public static final Money DEFAULT_RESTORE_BILLING_COST = Money.of(USD, 100); public static final Money DEFAULT_SERVER_STATUS_CHANGE_BILLING_COST = Money.of(USD, 20); + public static final Money DEFAULT_REGISTRY_LOCK_OR_UNLOCK_BILLING_COST = Money.of(USD, 0); /** The type of TLD, which determines things like backups and escrow policy. */ public enum TldType { @@ -478,6 +479,9 @@ public class Registry extends ImmutableObject implements Buildable { }) Money serverStatusChangeBillingCost = DEFAULT_SERVER_STATUS_CHANGE_BILLING_COST; + /** The one-time billing cost for a registry lock/unlock action initiated by a registrar. */ + Money registryLockOrUnlockBillingCost = DEFAULT_REGISTRY_LOCK_OR_UNLOCK_BILLING_COST; + /** * A property that transitions to different renew billing costs at different times. Stored as a * list of BillingCostTransition embedded objects using the @Mapify annotation. @@ -631,6 +635,11 @@ public class Registry extends ImmutableObject implements Buildable { return serverStatusChangeBillingCost; } + /** Returns the cost of a registry lock/unlock. */ + public Money getRegistryLockOrUnlockBillingCost() { + return registryLockOrUnlockBillingCost; + } + public ImmutableSortedMap getTldStateTransitions() { return tldStateTransitions.toValueMap(); } @@ -932,6 +941,12 @@ public class Registry extends ImmutableObject implements Buildable { return this; } + public Builder setRegistryLockOrUnlockBillingCost(Money amount) { + checkArgument(amount.isPositiveOrZero(), "Registry lock/unlock cost cannot be negative"); + getInstance().registryLockOrUnlockBillingCost = amount; + return this; + } + public Builder setLordnUsername(String username) { getInstance().lordnUsername = username; return this; @@ -983,6 +998,9 @@ public class Registry extends ImmutableObject implements Buildable { checkArgument( instance.getServerStatusChangeCost().getCurrencyUnit().equals(instance.currency), "Server status change cost must be in the registry's currency"); + checkArgument( + instance.getRegistryLockOrUnlockBillingCost().getCurrencyUnit().equals(instance.currency), + "Registry lock/unlock cost must be in the registry's currency"); Predicate currencyCheck = (Money money) -> money.getCurrencyUnit().equals(instance.currency); checkArgument( diff --git a/core/src/main/java/google/registry/tools/CreateOrUpdateTldCommand.java b/core/src/main/java/google/registry/tools/CreateOrUpdateTldCommand.java index 2f283cc77..d95f183e2 100644 --- a/core/src/main/java/google/registry/tools/CreateOrUpdateTldCommand.java +++ b/core/src/main/java/google/registry/tools/CreateOrUpdateTldCommand.java @@ -110,6 +110,12 @@ abstract class CreateOrUpdateTldCommand extends MutatingCommand { description = "One-time billing cost for a server status change") private Money serverStatusChangeCost; + @Nullable + @Parameter( + names = "--registry_lock_or_unlock_cost", + description = "One-time billing cost for a registry lock or unlock") + private Money registryLockOrUnlockCost; + @Nullable @Parameter( names = "--tld_type", @@ -326,6 +332,8 @@ abstract class CreateOrUpdateTldCommand extends MutatingCommand { Optional.ofNullable(roidSuffix).ifPresent(builder::setRoidSuffix); Optional.ofNullable(serverStatusChangeCost) .ifPresent(builder::setServerStatusChangeBillingCost); + Optional.ofNullable(registryLockOrUnlockCost) + .ifPresent(builder::setRegistryLockOrUnlockBillingCost); Optional.ofNullable(tldType).ifPresent(builder::setTldType); Optional.ofNullable(invoicingEnabled).ifPresent(builder::setInvoicingEnabled); Optional.ofNullable(lordnUsername).ifPresent(u -> builder.setLordnUsername(u.orElse(null))); diff --git a/core/src/main/java/google/registry/tools/DomainLockUtils.java b/core/src/main/java/google/registry/tools/DomainLockUtils.java index db71b6fad..f1cf8497e 100644 --- a/core/src/main/java/google/registry/tools/DomainLockUtils.java +++ b/core/src/main/java/google/registry/tools/DomainLockUtils.java @@ -380,7 +380,7 @@ public final class DomainLockUtils { .setReason(Reason.SERVER_STATUS) .setTargetId(domain.getForeignKey()) .setClientId(domain.getCurrentSponsorClientId()) - .setCost(Registry.get(domain.getTld()).getServerStatusChangeCost()) + .setCost(Registry.get(domain.getTld()).getRegistryLockOrUnlockBillingCost()) .setEventTime(now) .setBillingTime(now) .setParent(historyEntry) diff --git a/core/src/test/java/google/registry/flows/domain/DomainRenewFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainRenewFlowTest.java index 797d34c77..5307ab1a2 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainRenewFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainRenewFlowTest.java @@ -597,6 +597,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase { assertThat(registry.getRedemptionGracePeriodLength()) .isEqualTo(Registry.DEFAULT_REDEMPTION_GRACE_PERIOD); assertThat(registry.getPendingDeleteLength()).isEqualTo(Registry.DEFAULT_PENDING_DELETE_LENGTH); + assertThat(registry.getRegistryLockOrUnlockBillingCost()) + .isEqualTo(Registry.DEFAULT_REGISTRY_LOCK_OR_UNLOCK_BILLING_COST); } @Test @@ -230,6 +232,17 @@ class CreateTldCommandTest extends CommandTestCase { .isEqualTo(Money.of(USD, 42.42)); } + @Test + void testSuccess_registryLockOrUnlockCostFlag() throws Exception { + runCommandForced( + "--registry_lock_or_unlock_cost=\"USD 42.42\"", + "--roid_suffix=Q9JYB4C", + "--dns_writers=VoidDnsWriter", + "xn--q9jyb4c"); + assertThat(Registry.get("xn--q9jyb4c").getRegistryLockOrUnlockBillingCost()) + .isEqualTo(Money.of(USD, 42.42)); + } + @Test void testSuccess_nonUsdBillingCostFlag() throws Exception { runCommandForced( @@ -237,6 +250,7 @@ class CreateTldCommandTest extends CommandTestCase { "--restore_billing_cost=\"JPY 67890\"", "--initial_renew_billing_cost=\"JPY 101112\"", "--server_status_change_cost=\"JPY 97865\"", + "--registry_lock_or_unlock_cost=\"JPY 9001\"", "--roid_suffix=Q9JYB4C", "--dns_writers=VoidDnsWriter", "xn--q9jyb4c"); diff --git a/core/src/test/java/google/registry/tools/DomainLockUtilsTest.java b/core/src/test/java/google/registry/tools/DomainLockUtilsTest.java index bc4f89658..77f4899df 100644 --- a/core/src/test/java/google/registry/tools/DomainLockUtilsTest.java +++ b/core/src/test/java/google/registry/tools/DomainLockUtilsTest.java @@ -528,7 +528,7 @@ public final class DomainLockUtilsTest { .setReason(Reason.SERVER_STATUS) .setTargetId(domain.getForeignKey()) .setClientId(domain.getCurrentSponsorClientId()) - .setCost(Registry.get(domain.getTld()).getServerStatusChangeCost()) + .setCost(Registry.get(domain.getTld()).getRegistryLockOrUnlockBillingCost()) .setEventTime(clock.nowUtc()) .setBillingTime(clock.nowUtc()) .setParent(entry) diff --git a/core/src/test/java/google/registry/tools/UpdateTldCommandTest.java b/core/src/test/java/google/registry/tools/UpdateTldCommandTest.java index 25794fdcd..726a6c46f 100644 --- a/core/src/test/java/google/registry/tools/UpdateTldCommandTest.java +++ b/core/src/test/java/google/registry/tools/UpdateTldCommandTest.java @@ -212,19 +212,21 @@ class UpdateTldCommandTest extends CommandTestCase { ImmutableSortedMap.of(START_OF_TIME, Money.ofMajor(JPY, 1))) .setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.zero(JPY))) .setServerStatusChangeBillingCost(Money.ofMajor(JPY, 1)) + .setRegistryLockOrUnlockBillingCost(Money.ofMajor(JPY, 1)) .build()); runCommandForced( "--create_billing_cost=\"JPY 12345\"", "--restore_billing_cost=\"JPY 67890\"", "--renew_billing_cost_transitions=\"0=JPY 101112\"", "--server_status_change_cost=\"JPY 97865\"", + "--registry_lock_or_unlock_cost=\"JPY 9001\"", "xn--q9jyb4c"); - assertThat(Registry.get("xn--q9jyb4c").getStandardCreateCost()) - .isEqualTo(Money.ofMajor(JPY, 12345)); - assertThat(Registry.get("xn--q9jyb4c").getStandardRestoreCost()) - .isEqualTo(Money.ofMajor(JPY, 67890)); - assertThat(Registry.get("xn--q9jyb4c").getStandardRenewCost(START_OF_TIME)) - .isEqualTo(Money.ofMajor(JPY, 101112)); + Registry registry = Registry.get("xn--q9jyb4c"); + assertThat(registry.getStandardCreateCost()).isEqualTo(Money.ofMajor(JPY, 12345)); + assertThat(registry.getStandardRestoreCost()).isEqualTo(Money.ofMajor(JPY, 67890)); + assertThat(registry.getStandardRenewCost(START_OF_TIME)).isEqualTo(Money.ofMajor(JPY, 101112)); + assertThat(registry.getServerStatusChangeCost()).isEqualTo(Money.ofMajor(JPY, 97865)); + assertThat(registry.getRegistryLockOrUnlockBillingCost()).isEqualTo(Money.ofMajor(JPY, 9001)); } @Test diff --git a/core/src/test/java/google/registry/ui/server/registrar/RegistryLockVerifyActionTest.java b/core/src/test/java/google/registry/ui/server/registrar/RegistryLockVerifyActionTest.java index 9458681d3..cb2be1b48 100644 --- a/core/src/test/java/google/registry/ui/server/registrar/RegistryLockVerifyActionTest.java +++ b/core/src/test/java/google/registry/ui/server/registrar/RegistryLockVerifyActionTest.java @@ -317,7 +317,7 @@ final class RegistryLockVerifyActionTest { .setReason(Reason.SERVER_STATUS) .setTargetId(domain.getForeignKey()) .setClientId(domain.getCurrentSponsorClientId()) - .setCost(Registry.get(domain.getTld()).getServerStatusChangeCost()) + .setCost(Registry.get(domain.getTld()).getRegistryLockOrUnlockBillingCost()) .setEventTime(fakeClock.nowUtc()) .setBillingTime(fakeClock.nowUtc()) .setParent(historyEntry) diff --git a/core/src/test/resources/google/registry/model/schema.txt b/core/src/test/resources/google/registry/model/schema.txt index fe487b033..da603505d 100644 --- a/core/src/test/resources/google/registry/model/schema.txt +++ b/core/src/test/resources/google/registry/model/schema.txt @@ -640,6 +640,7 @@ class google.registry.model.registry.Registry { java.util.Set dnsWriters; org.joda.money.CurrencyUnit currency; org.joda.money.Money createBillingCost; + org.joda.money.Money registryLockOrUnlockBillingCost; org.joda.money.Money restoreBillingCost; org.joda.money.Money serverStatusChangeBillingCost; org.joda.time.DateTime claimsPeriodEnd;