Add a registration_behavior column to AllocationToken (#1695)

This is, as of now, unused but we can use it for b/237683906 and
b/237800445 in the future to allow for special behavior dictated by
allocation tokens rather than having to reserve specific domains.

Note that we enforce a tied domain for ANCHOR_TENANT tokens (because
they should be matched to a domain) but not for BYPASS_TLD_STATE tokens.
This commit is contained in:
gbrodman
2022-07-20 12:50:25 -04:00
committed by GitHub
parent 49b1b2d058
commit cf89d9354c
10 changed files with 217 additions and 6 deletions
@@ -86,6 +86,22 @@ public class AllocationToken extends BackupGroupRoot implements Buildable {
.putAll(VALID, ENDED, CANCELLED)
.build();
/** Any special behavior that should be used when registering domains using this token. */
public enum RegistrationBehavior {
/** No special behavior */
DEFAULT,
/**
* Bypasses the TLD state check, e.g. allowing registration during QUIET_PERIOD.
*
* <p>NB: while this means that, for instance, one can register non-trademarked domains in the
* sunrise period, any trademarked-domain registrations in the sunrise period must still include
* the proper signed marks. In other words, this only bypasses the TLD state check.
*/
BYPASS_TLD_STATE,
/** Bypasses most checks and creates the domain as an anchor tenant, with all that implies. */
ANCHOR_TENANT
}
/** Single-use tokens are invalid after use. Infinite-use tokens, predictably, are not. */
public enum TokenType {
SINGLE_USE,
@@ -153,6 +169,10 @@ public class AllocationToken extends BackupGroupRoot implements Buildable {
@Column(name = "renewalPriceBehavior", nullable = false)
RenewalPriceBehavior renewalPriceBehavior = RenewalPriceBehavior.DEFAULT;
@Enumerated(EnumType.STRING)
@Column(nullable = false)
RegistrationBehavior registrationBehavior = RegistrationBehavior.DEFAULT;
// TODO: Remove onLoad once all allocation tokens are migrated to have a discountYears of 1.
@OnLoad
void onLoad() {
@@ -225,6 +245,10 @@ public class AllocationToken extends BackupGroupRoot implements Buildable {
return renewalPriceBehavior;
}
public RegistrationBehavior getRegistrationBehavior() {
return registrationBehavior;
}
@Override
public VKey<AllocationToken> createVKey() {
return VKey.create(AllocationToken.class, getToken(), Key.create(this));
@@ -261,6 +285,10 @@ public class AllocationToken extends BackupGroupRoot implements Buildable {
checkArgument(
getInstance().discountFraction > 0 || getInstance().discountYears == 1,
"Discount years can only be specified along with a discount fraction");
if (getInstance().registrationBehavior.equals(RegistrationBehavior.ANCHOR_TENANT)) {
checkArgumentNotNull(
getInstance().domainName, "ANCHOR_TENANT tokens must be tied to a domain");
}
if (getInstance().domainName != null) {
try {
DomainFlowUtils.validateDomainName(getInstance().domainName);
@@ -352,5 +380,10 @@ public class AllocationToken extends BackupGroupRoot implements Buildable {
getInstance().renewalPriceBehavior = renewalPriceBehavior;
return this;
}
public Builder setRegistrationBehavior(RegistrationBehavior registrationBehavior) {
getInstance().registrationBehavior = registrationBehavior;
return this;
}
}
}
@@ -39,6 +39,7 @@ import com.google.common.collect.Streams;
import com.google.common.io.Files;
import google.registry.model.billing.BillingEvent.RenewalPriceBehavior;
import google.registry.model.domain.token.AllocationToken;
import google.registry.model.domain.token.AllocationToken.RegistrationBehavior;
import google.registry.model.domain.token.AllocationToken.TokenStatus;
import google.registry.model.domain.token.AllocationToken.TokenType;
import google.registry.persistence.VKey;
@@ -152,6 +153,14 @@ class GenerateAllocationTokensCommand implements CommandWithRemoteApi {
+ " same as the domain's calculated create price.")
private RenewalPriceBehavior renewalPriceBehavior = DEFAULT;
@Parameter(
names = {"--registration_behavior"},
description =
"Any special registration behavior, including DEFAULT (no special behavior),"
+ " BYPASS_TLD_STATE (allow registrations during e.g. QUIET_PERIOD), and"
+ " ANCHOR_TENANT (used for anchor tenant registrations")
private RegistrationBehavior registrationBehavior = RegistrationBehavior.DEFAULT;
@Parameter(
names = {"--dry_run"},
description = "Do not actually persist the tokens; defaults to false")
@@ -196,6 +205,7 @@ class GenerateAllocationTokensCommand implements CommandWithRemoteApi {
new AllocationToken.Builder()
.setToken(t)
.setRenewalPriceBehavior(renewalPriceBehavior)
.setRegistrationBehavior(registrationBehavior)
.setTokenType(tokenType == null ? SINGLE_USE : tokenType)
.setAllowedRegistrarIds(
ImmutableSet.copyOf(nullToEmpty(allowedClientIds)))
@@ -29,6 +29,7 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import google.registry.model.billing.BillingEvent.RenewalPriceBehavior;
import google.registry.model.domain.token.AllocationToken;
import google.registry.model.domain.token.AllocationToken.RegistrationBehavior;
import google.registry.model.domain.token.AllocationToken.TokenStatus;
import google.registry.tools.params.TransitionListParameter.TokenStatusTransitions;
import java.util.List;
@@ -100,6 +101,15 @@ final class UpdateAllocationTokensCommand extends UpdateOrDeleteAllocationTokens
@Nullable
private RenewalPriceBehavior renewalPriceBehavior;
@Parameter(
names = {"--registration_behavior"},
description =
"Any special registration behavior, including DEFAULT (no special behavior),"
+ " BYPASS_TLD_STATE (allow registrations during e.g. QUIET_PERIOD), and"
+ " ANCHOR_TENANT (used for anchor tenant registrations")
@Nullable
private RegistrationBehavior registrationBehavior;
private static final int BATCH_SIZE = 20;
private static final Joiner JOINER = Joiner.on(", ");
@@ -156,8 +166,8 @@ final class UpdateAllocationTokensCommand extends UpdateOrDeleteAllocationTokens
Optional.ofNullable(discountPremiums).ifPresent(builder::setDiscountPremiums);
Optional.ofNullable(discountYears).ifPresent(builder::setDiscountYears);
Optional.ofNullable(tokenStatusTransitions).ifPresent(builder::setTokenStatusTransitions);
Optional.ofNullable(renewalPriceBehavior)
.ifPresent(behavior -> builder.setRenewalPriceBehavior(renewalPriceBehavior));
Optional.ofNullable(renewalPriceBehavior).ifPresent(builder::setRenewalPriceBehavior);
Optional.ofNullable(registrationBehavior).ifPresent(builder::setRegistrationBehavior);
return builder.build();
}