mirror of
https://github.com/google/nomulus.git
synced 2025-04-29 19:47:51 +02:00
Add defaultPromoTokens to Registry (#1850)
* Add defaultPromoTokens to Registry * Remove flyway files from this PR * Fix merge conflicts * Add back flyway file * Add more info to error messages * Change to a list * Fix javadoc * Change error message * Add note to field declaration
This commit is contained in:
parent
c13962554e
commit
fa3f2a2f21
6 changed files with 232 additions and 0 deletions
|
@ -30,6 +30,7 @@ import com.github.benmanes.caffeine.cache.CacheLoader;
|
||||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.ImmutableSortedMap;
|
import com.google.common.collect.ImmutableSortedMap;
|
||||||
|
@ -45,11 +46,14 @@ import google.registry.model.UnsafeSerializable;
|
||||||
import google.registry.model.common.TimedTransitionProperty;
|
import google.registry.model.common.TimedTransitionProperty;
|
||||||
import google.registry.model.domain.fee.BaseFee.FeeType;
|
import google.registry.model.domain.fee.BaseFee.FeeType;
|
||||||
import google.registry.model.domain.fee.Fee;
|
import google.registry.model.domain.fee.Fee;
|
||||||
|
import google.registry.model.domain.token.AllocationToken;
|
||||||
|
import google.registry.model.domain.token.AllocationToken.TokenType;
|
||||||
import google.registry.model.tld.label.PremiumList;
|
import google.registry.model.tld.label.PremiumList;
|
||||||
import google.registry.model.tld.label.ReservedList;
|
import google.registry.model.tld.label.ReservedList;
|
||||||
import google.registry.persistence.VKey;
|
import google.registry.persistence.VKey;
|
||||||
import google.registry.persistence.converter.JodaMoneyType;
|
import google.registry.persistence.converter.JodaMoneyType;
|
||||||
import google.registry.util.Idn;
|
import google.registry.util.Idn;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -451,6 +455,18 @@ public class Registry extends ImmutableObject implements Buildable, UnsafeSerial
|
||||||
/** An allowlist of hosts allowed to be used on domains on this TLD (ignored if empty). */
|
/** An allowlist of hosts allowed to be used on domains on this TLD (ignored if empty). */
|
||||||
@Nullable Set<String> allowedFullyQualifiedHostNames;
|
@Nullable Set<String> allowedFullyQualifiedHostNames;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* References to allocation tokens that can be used on the TLD if no other token is passed in on a
|
||||||
|
* domain create.
|
||||||
|
*
|
||||||
|
* <p>Ordering is important for this field as it will determine which token is used if multiple
|
||||||
|
* tokens in the list are valid for a specific registration. It is crucial that modifications to
|
||||||
|
* this field only modify the entire list contents. Modifications to a single token in the list
|
||||||
|
* (ex: add a token to the list or remove a token from the list) should not be allowed without
|
||||||
|
* resetting the entire list contents.
|
||||||
|
*/
|
||||||
|
List<VKey<AllocationToken>> defaultPromoTokens;
|
||||||
|
|
||||||
public String getTldStr() {
|
public String getTldStr() {
|
||||||
return tldStr;
|
return tldStr;
|
||||||
}
|
}
|
||||||
|
@ -639,6 +655,10 @@ public class Registry extends ImmutableObject implements Buildable, UnsafeSerial
|
||||||
return nullToEmptyImmutableCopy(allowedFullyQualifiedHostNames);
|
return nullToEmptyImmutableCopy(allowedFullyQualifiedHostNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ImmutableList<VKey<AllocationToken>> getDefaultPromoTokens() {
|
||||||
|
return nullToEmptyImmutableCopy(defaultPromoTokens);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Builder asBuilder() {
|
public Builder asBuilder() {
|
||||||
return new Builder(clone(this));
|
return new Builder(clone(this));
|
||||||
|
@ -900,6 +920,28 @@ public class Registry extends ImmutableObject implements Buildable, UnsafeSerial
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder setDefaultPromoTokens(ImmutableList<VKey<AllocationToken>> promoTokens) {
|
||||||
|
tm().transact(
|
||||||
|
() -> {
|
||||||
|
for (VKey<AllocationToken> tokenKey : promoTokens) {
|
||||||
|
AllocationToken token = tm().loadByKey(tokenKey);
|
||||||
|
checkArgument(
|
||||||
|
token.getTokenType().equals(TokenType.DEFAULT_PROMO),
|
||||||
|
String.format(
|
||||||
|
"Token %s has an invalid token type of %s. DefaultPromoTokens must be of"
|
||||||
|
+ " the type DEFAULT_PROMO",
|
||||||
|
token.getToken(), token.getTokenType()));
|
||||||
|
checkArgument(
|
||||||
|
token.getAllowedTlds().contains(getInstance().tldStr),
|
||||||
|
String.format(
|
||||||
|
"The token %s is not valid for this TLD. The valid TLDs for it are %s",
|
||||||
|
token.getToken(), token.getAllowedTlds()));
|
||||||
|
}
|
||||||
|
getInstance().defaultPromoTokens = promoTokens;
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Registry build() {
|
public Registry build() {
|
||||||
final Registry instance = getInstance();
|
final Registry instance = getInstance();
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
// Copyright 2022 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.persistence.converter;
|
||||||
|
|
||||||
|
import google.registry.model.domain.token.AllocationToken;
|
||||||
|
import google.registry.persistence.VKey;
|
||||||
|
import javax.persistence.Converter;
|
||||||
|
|
||||||
|
@Converter(autoApply = true)
|
||||||
|
public class AllocationTokenListConverter extends StringListConverterBase<VKey<AllocationToken>> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String toString(VKey<AllocationToken> element) {
|
||||||
|
return element.getKey().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
VKey<AllocationToken> fromString(String value) {
|
||||||
|
return VKey.create(AllocationToken.class, value);
|
||||||
|
}
|
||||||
|
}
|
|
@ -78,6 +78,7 @@
|
||||||
<class>google.registry.model.domain.RegistryLock</class>
|
<class>google.registry.model.domain.RegistryLock</class>
|
||||||
|
|
||||||
<!-- Customized type converters -->
|
<!-- Customized type converters -->
|
||||||
|
<class>google.registry.persistence.converter.AllocationTokenListConverter</class>
|
||||||
<class>google.registry.persistence.converter.AllocationTokenStatusTransitionConverter</class>
|
<class>google.registry.persistence.converter.AllocationTokenStatusTransitionConverter</class>
|
||||||
<class>google.registry.persistence.converter.BillingCostTransitionConverter</class>
|
<class>google.registry.persistence.converter.BillingCostTransitionConverter</class>
|
||||||
<class>google.registry.persistence.converter.BillingEventFlagSetConverter</class>
|
<class>google.registry.persistence.converter.BillingEventFlagSetConverter</class>
|
||||||
|
|
|
@ -17,6 +17,8 @@ package google.registry.model.tld;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static com.google.common.truth.Truth.assertWithMessage;
|
import static com.google.common.truth.Truth.assertWithMessage;
|
||||||
import static com.google.common.truth.Truth8.assertThat;
|
import static com.google.common.truth.Truth8.assertThat;
|
||||||
|
import static google.registry.model.domain.token.AllocationToken.TokenType.DEFAULT_PROMO;
|
||||||
|
import static google.registry.model.domain.token.AllocationToken.TokenType.SINGLE_USE;
|
||||||
import static google.registry.model.tld.Registry.TldState.GENERAL_AVAILABILITY;
|
import static google.registry.model.tld.Registry.TldState.GENERAL_AVAILABILITY;
|
||||||
import static google.registry.model.tld.Registry.TldState.PREDELEGATION;
|
import static google.registry.model.tld.Registry.TldState.PREDELEGATION;
|
||||||
import static google.registry.model.tld.Registry.TldState.QUIET_PERIOD;
|
import static google.registry.model.tld.Registry.TldState.QUIET_PERIOD;
|
||||||
|
@ -26,6 +28,7 @@ import static google.registry.testing.DatabaseHelper.createTld;
|
||||||
import static google.registry.testing.DatabaseHelper.newRegistry;
|
import static google.registry.testing.DatabaseHelper.newRegistry;
|
||||||
import static google.registry.testing.DatabaseHelper.persistPremiumList;
|
import static google.registry.testing.DatabaseHelper.persistPremiumList;
|
||||||
import static google.registry.testing.DatabaseHelper.persistReservedList;
|
import static google.registry.testing.DatabaseHelper.persistReservedList;
|
||||||
|
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||||
import static java.math.RoundingMode.UNNECESSARY;
|
import static java.math.RoundingMode.UNNECESSARY;
|
||||||
|
@ -38,11 +41,13 @@ import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.ImmutableSortedMap;
|
import com.google.common.collect.ImmutableSortedMap;
|
||||||
import google.registry.dns.writer.VoidDnsWriter;
|
import google.registry.dns.writer.VoidDnsWriter;
|
||||||
import google.registry.model.EntityTestCase;
|
import google.registry.model.EntityTestCase;
|
||||||
|
import google.registry.model.domain.token.AllocationToken;
|
||||||
import google.registry.model.tld.Registry.RegistryNotFoundException;
|
import google.registry.model.tld.Registry.RegistryNotFoundException;
|
||||||
import google.registry.model.tld.Registry.TldState;
|
import google.registry.model.tld.Registry.TldState;
|
||||||
import google.registry.model.tld.label.PremiumList;
|
import google.registry.model.tld.label.PremiumList;
|
||||||
import google.registry.model.tld.label.PremiumListDao;
|
import google.registry.model.tld.label.PremiumListDao;
|
||||||
import google.registry.model.tld.label.ReservedList;
|
import google.registry.model.tld.label.ReservedList;
|
||||||
|
import google.registry.persistence.VKey;
|
||||||
import google.registry.util.SerializeUtils;
|
import google.registry.util.SerializeUtils;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
@ -628,4 +633,81 @@ public final class RegistryTest extends EntityTestCase {
|
||||||
IllegalArgumentException.class,
|
IllegalArgumentException.class,
|
||||||
() -> Registry.get("tld").asBuilder().setRoidSuffix("ABC-DEF"));
|
() -> Registry.get("tld").asBuilder().setRoidSuffix("ABC-DEF"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSuccess_setDefaultPromoTokens() {
|
||||||
|
Registry registry = Registry.get("tld");
|
||||||
|
assertThat(registry.getDefaultPromoTokens()).isEmpty();
|
||||||
|
AllocationToken token1 =
|
||||||
|
persistResource(
|
||||||
|
new AllocationToken()
|
||||||
|
.asBuilder()
|
||||||
|
.setToken("abc123")
|
||||||
|
.setTokenType(DEFAULT_PROMO)
|
||||||
|
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||||
|
.build());
|
||||||
|
AllocationToken token2 =
|
||||||
|
persistResource(
|
||||||
|
new AllocationToken()
|
||||||
|
.asBuilder()
|
||||||
|
.setToken("token")
|
||||||
|
.setTokenType(DEFAULT_PROMO)
|
||||||
|
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||||
|
.build());
|
||||||
|
ImmutableList<VKey<AllocationToken>> tokens =
|
||||||
|
ImmutableList.of(token1.createVKey(), token2.createVKey());
|
||||||
|
registry = registry.asBuilder().setDefaultPromoTokens(tokens).build();
|
||||||
|
assertThat(registry.getDefaultPromoTokens()).isEqualTo(tokens);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testFailure_setDefaultPromoTokensWrongTokenType() {
|
||||||
|
Registry registry = Registry.get("tld");
|
||||||
|
assertThat(registry.getDefaultPromoTokens()).isEmpty();
|
||||||
|
AllocationToken token1 =
|
||||||
|
persistResource(
|
||||||
|
new AllocationToken()
|
||||||
|
.asBuilder()
|
||||||
|
.setToken("abc123")
|
||||||
|
.setTokenType(SINGLE_USE)
|
||||||
|
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||||
|
.build());
|
||||||
|
IllegalArgumentException thrown =
|
||||||
|
assertThrows(
|
||||||
|
IllegalArgumentException.class,
|
||||||
|
() ->
|
||||||
|
registry
|
||||||
|
.asBuilder()
|
||||||
|
.setDefaultPromoTokens(ImmutableList.of(token1.createVKey()))
|
||||||
|
.build());
|
||||||
|
assertThat(thrown.getMessage())
|
||||||
|
.isEqualTo(
|
||||||
|
"Token abc123 has an invalid token type of SINGLE_USE. DefaultPromoTokens must be of"
|
||||||
|
+ " the type DEFAULT_PROMO");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testFailure_setDefaultPromoTokensNotValidForTld() {
|
||||||
|
Registry registry = Registry.get("tld");
|
||||||
|
assertThat(registry.getDefaultPromoTokens()).isEmpty();
|
||||||
|
AllocationToken token1 =
|
||||||
|
persistResource(
|
||||||
|
new AllocationToken()
|
||||||
|
.asBuilder()
|
||||||
|
.setToken("abc123")
|
||||||
|
.setTokenType(DEFAULT_PROMO)
|
||||||
|
.setAllowedTlds(ImmutableSet.of("example"))
|
||||||
|
.build());
|
||||||
|
IllegalArgumentException thrown =
|
||||||
|
assertThrows(
|
||||||
|
IllegalArgumentException.class,
|
||||||
|
() ->
|
||||||
|
registry
|
||||||
|
.asBuilder()
|
||||||
|
.setDefaultPromoTokens(ImmutableList.of(token1.createVKey()))
|
||||||
|
.build());
|
||||||
|
assertThat(thrown.getMessage())
|
||||||
|
.isEqualTo(
|
||||||
|
"The token abc123 is not valid for this TLD. The valid TLDs for it are [example]");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
// Copyright 2022 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.persistence.converter;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static google.registry.model.domain.token.AllocationToken.TokenType.SINGLE_USE;
|
||||||
|
import static google.registry.model.domain.token.AllocationToken.TokenType.UNLIMITED_USE;
|
||||||
|
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||||
|
import static google.registry.testing.DatabaseHelper.insertInDb;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import google.registry.model.ImmutableObject;
|
||||||
|
import google.registry.model.domain.token.AllocationToken;
|
||||||
|
import google.registry.persistence.VKey;
|
||||||
|
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||||
|
import google.registry.persistence.transaction.JpaTestExtensions.JpaUnitTestExtension;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
|
||||||
|
/** Unit tests for {@link google.registry.persistence.converter.AllocationTokenListConverter}. */
|
||||||
|
public class AllocationTokenListConverterTest {
|
||||||
|
|
||||||
|
@RegisterExtension
|
||||||
|
public final JpaUnitTestExtension jpaExtension =
|
||||||
|
new JpaTestExtensions.Builder()
|
||||||
|
.withEntityClass(TestAllocationTokenVKeyList.class)
|
||||||
|
.buildUnitTestExtension();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRoundTrip() {
|
||||||
|
AllocationToken token1 =
|
||||||
|
new AllocationToken().asBuilder().setToken("abc123").setTokenType(SINGLE_USE).build();
|
||||||
|
AllocationToken token2 =
|
||||||
|
new AllocationToken().asBuilder().setToken("token").setTokenType(UNLIMITED_USE).build();
|
||||||
|
List<VKey<AllocationToken>> tokens = ImmutableList.of(token1.createVKey(), token2.createVKey());
|
||||||
|
TestAllocationTokenVKeyList testAllocationTokenVKeyList =
|
||||||
|
new TestAllocationTokenVKeyList(tokens);
|
||||||
|
insertInDb(testAllocationTokenVKeyList);
|
||||||
|
TestAllocationTokenVKeyList persisted =
|
||||||
|
jpaTm()
|
||||||
|
.transact(
|
||||||
|
() -> jpaTm().getEntityManager().find(TestAllocationTokenVKeyList.class, "id"));
|
||||||
|
assertThat(persisted.tokenList).isEqualTo(tokens);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "TestAllocationTokenVKeyList")
|
||||||
|
static class TestAllocationTokenVKeyList extends ImmutableObject {
|
||||||
|
@Id String id = "id";
|
||||||
|
|
||||||
|
List<VKey<AllocationToken>> tokenList;
|
||||||
|
|
||||||
|
TestAllocationTokenVKeyList() {}
|
||||||
|
|
||||||
|
TestAllocationTokenVKeyList(List<VKey<AllocationToken>> tokenList) {
|
||||||
|
this.tokenList = tokenList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -704,6 +704,7 @@
|
||||||
create_billing_cost_currency text,
|
create_billing_cost_currency text,
|
||||||
creation_time timestamptz not null,
|
creation_time timestamptz not null,
|
||||||
currency text not null,
|
currency text not null,
|
||||||
|
default_promo_tokens text[],
|
||||||
dns_paused boolean not null,
|
dns_paused boolean not null,
|
||||||
dns_writers text[] not null,
|
dns_writers text[] not null,
|
||||||
drive_folder_id text,
|
drive_folder_id text,
|
||||||
|
|
Loading…
Add table
Reference in a new issue