mirror of
https://github.com/google/nomulus.git
synced 2025-05-13 16:07:15 +02:00
Add new reserved domain creation from allocation tokens mechanism
Note that this gets rid of anchor tenant codes in reserved lists (yay!), which are no longer valid. They have to come from allocation tokens now. This removes support for LRP from domain application create flow (that's fine, we never used it and I'm going to delete all of LRP later). It also uses allocation tokens from EPP authcodes as a fallback, for now, but that will be removed later once we switch fully to the allocation token mechanism. This doesn't yet allow registration of RESERVED_FOR_SPECIFIC_USE domains using the allocation token extension; that will come in the next CL. Ditto for showing these reserved domains as available on domain checks when the allocation token is specified. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=209019617
This commit is contained in:
parent
782643ce33
commit
d2f849ac0f
19 changed files with 184 additions and 346 deletions
|
@ -23,12 +23,18 @@ a price, it has a reservation type. The valid values for reservation types are:
|
|||
period by a registrant with a valid claim but it is reserved thereafter.
|
||||
* **`MISTAKEN_PREMIUM`** - The label is reserved because it was mistakenly put
|
||||
on a premium list. It may be registered during sunrise by a registrant with
|
||||
a valid claim but is reserved thereafter.
|
||||
* **`RESERVED_FOR_ANCHOR_TENANT`** - The label is reserved for the use of an
|
||||
anchor tenant, and can only be registered by someone sending along the EPP
|
||||
passcode specified here at time of registration. If a label has different
|
||||
passcodes in different lists that are applied to the same TLD, an error will
|
||||
occur.
|
||||
a valid claim but is reserved thereafter. This is deprecated.
|
||||
* **RESERVED_FOR_SPECIFIC_USE** - The label is reserved for the use of a
|
||||
specific registrant, and can only be registered by someone sending along the
|
||||
allocation token at time of registration. This token is configured on an
|
||||
`AllocationToken` entity with a matching `domainName`, and is sent by the
|
||||
registrar using the [allocation token EPP
|
||||
extension](https://tools.ietf.org/id/draft-ietf-regext-allocation-token-07.html).
|
||||
* **`RESERVED_FOR_ANCHOR_TENANT`** - Like `RESERVED_FOR_SPECIFIC_USE`, except
|
||||
for an anchor tenant (i.e. a registrant participating in a [Qualified Launch
|
||||
Program](https://newgtlds.icann.org/en/announcements-and-media/announcement-10apr14-en)),
|
||||
meaning that registrations can occur during sunrise ahead of GA, and must be
|
||||
for a two year term.
|
||||
* **`NAME_COLLISION`** - The label is reserved because it is on an [ICANN
|
||||
collision
|
||||
list](https://www.icann.org/resources/pages/name-collision-2013-12-06-en).
|
||||
|
@ -48,17 +54,15 @@ label is reserved due to name collision (with message "Cannot be delegated"). In
|
|||
general `FULLY_BLOCKED` is by far the most widely used reservation type for
|
||||
typical TLD use cases.
|
||||
|
||||
Here's an example of a small reserved list. Note that
|
||||
`RESERVED_FOR_ANCHOR_TENANT` has a third entry on the line, being the EPP
|
||||
passcode required to register the domain (`hunter2` in this case); and that
|
||||
`NAMESERVER_RESERVED` also has a third entry, a colon separated list of
|
||||
Here's an example of a small reserved list. Note that the
|
||||
`NAMESERVER_RESTRICTED` label has a third entry, a colon separated list of
|
||||
nameservers that the label can be delegated to:
|
||||
|
||||
```
|
||||
reserveddomain,FULLY_BLOCKED
|
||||
availableinga,ALLOWED_IN_SUNRISE
|
||||
fourletterword,FULLY_BLOCKED
|
||||
acmecorp,RESERVED_FOR_ANCHOR_TENANT,hunter2
|
||||
acmecorp,RESERVED_FOR_ANCHOR_TENANT
|
||||
internaldomain,NAMESERVER_RESTRICTED,ns1.internal.tld:ns1.internal.tld
|
||||
```
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ import static google.registry.flows.domain.DomainFlowUtils.COLLISION_MESSAGE;
|
|||
import static google.registry.flows.domain.DomainFlowUtils.cloneAndLinkReferences;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.createFeeCreateResponse;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.getReservationTypes;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.prepareMarkedLrpTokenEntity;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.validateCreateCommandContactsAndNameservers;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.validateDomainName;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.validateDomainNameWithIdnTables;
|
||||
|
@ -31,7 +30,6 @@ import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears;
|
|||
import static google.registry.model.EppResourceUtils.createDomainRepoId;
|
||||
import static google.registry.model.EppResourceUtils.loadDomainApplication;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.registry.label.ReservedList.matchesAnchorTenantReservation;
|
||||
import static google.registry.pricing.PricingEngineProxy.getDomainCreateCost;
|
||||
import static google.registry.util.CollectionUtils.isNullOrEmpty;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
|
@ -200,11 +198,6 @@ public class DomainAllocateFlow implements TransactionalFlow {
|
|||
updateApplication(application),
|
||||
ForeignKeyIndex.create(newDomain, newDomain.getDeletionTime()),
|
||||
EppResourceIndex.create(Key.create(newDomain)));
|
||||
// Anchor tenant registrations override LRP.
|
||||
String authInfoToken = authInfo.getPw().getValue();
|
||||
if (hasLrpToken(domainName, registry, authInfoToken, now)) {
|
||||
entitiesToSave.add(prepareMarkedLrpTokenEntity(authInfoToken, domainName, historyEntry));
|
||||
}
|
||||
ofy().save().entities(entitiesToSave.build());
|
||||
enqueueTasks(allocateCreate, newDomain);
|
||||
return responseBuilder
|
||||
|
@ -387,12 +380,6 @@ public class DomainAllocateFlow implements TransactionalFlow {
|
|||
.build();
|
||||
}
|
||||
|
||||
private boolean hasLrpToken(
|
||||
InternetDomainName domainName, Registry registry, String authInfoToken, DateTime now) {
|
||||
return registry.getLrpPeriod().contains(now)
|
||||
&& !matchesAnchorTenantReservation(domainName, authInfoToken);
|
||||
}
|
||||
|
||||
private void enqueueTasks(AllocateCreateExtension allocateCreate, DomainResource newDomain) {
|
||||
if (newDomain.shouldPublishToDns()) {
|
||||
dnsQueue.get().addDomainRefreshTask(newDomain.getFullyQualifiedDomainName());
|
||||
|
|
|
@ -22,6 +22,7 @@ import static google.registry.flows.ResourceFlowUtils.verifyResourceDoesNotExist
|
|||
import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.cloneAndLinkReferences;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.createFeeCreateResponse;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.isAnchorTenant;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.prepareMarkedLrpTokenEntity;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.validateCreateCommandContactsAndNameservers;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.validateDomainName;
|
||||
|
@ -42,7 +43,6 @@ import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears;
|
|||
import static google.registry.model.EppResourceUtils.createDomainRepoId;
|
||||
import static google.registry.model.index.DomainApplicationIndex.loadActiveApplicationsByDomainName;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.registry.label.ReservedList.matchesAnchorTenantReservation;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
@ -223,7 +223,7 @@ public final class DomainApplicationCreateFlow implements TransactionalFlow {
|
|||
eppInput.getSingleExtension(LaunchCreateExtension.class).get();
|
||||
validateLaunchCreateExtension(launchCreate, registry, domainName, now);
|
||||
boolean isAnchorTenant =
|
||||
matchesAnchorTenantReservation(domainName, authInfo.getPw().getValue());
|
||||
isAnchorTenant(domainName, Optional.empty(), authInfo.getPw().getValue(), Optional.empty());
|
||||
// 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.
|
||||
if (!isSuperuser) {
|
||||
|
|
|
@ -22,6 +22,7 @@ import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToT
|
|||
import static google.registry.flows.domain.DomainFlowUtils.cloneAndLinkReferences;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.createFeeCreateResponse;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.getReservationTypes;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.isAnchorTenant;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.prepareMarkedLrpTokenEntity;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.validateCreateCommandContactsAndNameservers;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.validateDomainAllowedOnCreateRestrictedTld;
|
||||
|
@ -50,7 +51,6 @@ import static google.registry.model.registry.Registry.TldState.START_DATE_SUNRIS
|
|||
import static google.registry.model.registry.Registry.TldState.SUNRISE;
|
||||
import static google.registry.model.registry.Registry.TldState.SUNRUSH;
|
||||
import static google.registry.model.registry.label.ReservationType.NAME_COLLISION;
|
||||
import static google.registry.model.registry.label.ReservedList.matchesAnchorTenantReservation;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
import static google.registry.util.DateTimeUtils.leapSafeAddYears;
|
||||
|
||||
|
@ -251,8 +251,6 @@ public class DomainCreateFlow implements TransactionalFlow {
|
|||
validateDomainAllowedOnCreateRestrictedTld(domainName);
|
||||
}
|
||||
TldState tldState = registry.getTldState(now);
|
||||
boolean isAnchorTenant = isAnchorTenant(domainName);
|
||||
verifyAnchorTenantValidPeriod(isAnchorTenant, years);
|
||||
Optional<LaunchCreateExtension> launchCreate =
|
||||
eppInput.getSingleExtension(LaunchCreateExtension.class);
|
||||
boolean hasSignedMarks =
|
||||
|
@ -263,6 +261,15 @@ public class DomainCreateFlow implements TransactionalFlow {
|
|||
validateLaunchCreateNotice(launchCreate.get().getNotice(), domainLabel, isSuperuser, now);
|
||||
}
|
||||
boolean isSunriseCreate = hasSignedMarks && SUNRISE_STATES.contains(tldState);
|
||||
Optional<AllocationToken> allocationToken =
|
||||
verifyAllocationTokenIfPresent(command, registry, clientId, now);
|
||||
boolean isAnchorTenant =
|
||||
isAnchorTenant(
|
||||
domainName,
|
||||
allocationToken,
|
||||
authInfo.getPw().getValue(),
|
||||
eppInput.getSingleExtension(MetadataExtension.class));
|
||||
verifyAnchorTenantValidPeriod(isAnchorTenant, years);
|
||||
// Superusers can create reserved domains, force creations on domains that require a claims
|
||||
// notice without specifying a claims key, ignore the registry phase, and override blocks on
|
||||
// registering premium domains.
|
||||
|
@ -294,8 +301,6 @@ public class DomainCreateFlow implements TransactionalFlow {
|
|||
.verifySignedMarks(launchCreate.get().getSignedMarks(), domainLabel, now)
|
||||
.getId();
|
||||
}
|
||||
Optional<AllocationToken> allocationToken =
|
||||
verifyAllocationTokenIfPresent(command, registry, clientId, now);
|
||||
flowCustomLogic.afterValidation(
|
||||
DomainCreateFlowCustomLogic.AfterValidationParameters.newBuilder()
|
||||
.setDomainName(domainName)
|
||||
|
@ -400,13 +405,6 @@ public class DomainCreateFlow implements TransactionalFlow {
|
|||
.build();
|
||||
}
|
||||
|
||||
private boolean isAnchorTenant(InternetDomainName domainName) {
|
||||
Optional<MetadataExtension> metadataExtension =
|
||||
eppInput.getSingleExtension(MetadataExtension.class);
|
||||
return matchesAnchorTenantReservation(domainName, authInfo.getPw().getValue())
|
||||
|| (metadataExtension.isPresent() && metadataExtension.get().getIsAnchorTenant());
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that signed marks are only sent during sunrise.
|
||||
*
|
||||
|
|
|
@ -30,6 +30,7 @@ import static google.registry.model.registry.Registries.getTlds;
|
|||
import static google.registry.model.registry.label.ReservationType.FULLY_BLOCKED;
|
||||
import static google.registry.model.registry.label.ReservationType.NAMESERVER_RESTRICTED;
|
||||
import static google.registry.model.registry.label.ReservationType.RESERVED_FOR_ANCHOR_TENANT;
|
||||
import static google.registry.model.registry.label.ReservationType.RESERVED_FOR_SPECIFIC_USE;
|
||||
import static google.registry.model.registry.label.ReservedList.getAllowedNameservers;
|
||||
import static google.registry.pricing.PricingEngineProxy.isDomainPremium;
|
||||
import static google.registry.tldconfig.idn.IdnLabelValidator.findValidIdnTableForTld;
|
||||
|
@ -93,12 +94,14 @@ import google.registry.model.domain.launch.LaunchExtension;
|
|||
import google.registry.model.domain.launch.LaunchNotice;
|
||||
import google.registry.model.domain.launch.LaunchNotice.InvalidChecksumException;
|
||||
import google.registry.model.domain.launch.LaunchPhase;
|
||||
import google.registry.model.domain.metadata.MetadataExtension;
|
||||
import google.registry.model.domain.secdns.DelegationSignerData;
|
||||
import google.registry.model.domain.secdns.SecDnsCreateExtension;
|
||||
import google.registry.model.domain.secdns.SecDnsInfoExtension;
|
||||
import google.registry.model.domain.secdns.SecDnsUpdateExtension;
|
||||
import google.registry.model.domain.secdns.SecDnsUpdateExtension.Add;
|
||||
import google.registry.model.domain.secdns.SecDnsUpdateExtension.Remove;
|
||||
import google.registry.model.domain.token.AllocationToken;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
|
||||
import google.registry.model.host.HostResource;
|
||||
|
@ -142,7 +145,7 @@ public class DomainFlowUtils {
|
|||
.put(LaunchPhase.OPEN, TldState.GENERAL_AVAILABILITY)
|
||||
.build();
|
||||
|
||||
/** Reservation types that are allowed in sunrise by policy. */
|
||||
/** Reservation types that are only allowed in sunrise by policy. */
|
||||
public static final ImmutableSet<ReservationType> TYPES_ALLOWED_FOR_CREATE_ONLY_IN_SUNRISE =
|
||||
Sets.immutableEnumSet(
|
||||
ReservationType.ALLOWED_IN_SUNRISE,
|
||||
|
@ -247,6 +250,37 @@ public class DomainFlowUtils {
|
|||
return idnTableName.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the information for a given domain create request is for a valid anchor tenant.
|
||||
*/
|
||||
public static boolean isAnchorTenant(
|
||||
InternetDomainName domainName,
|
||||
Optional<AllocationToken> token,
|
||||
String authInfoPw,
|
||||
Optional<MetadataExtension> metadataExtension) {
|
||||
// If the domain is reserved for anchor tenants, then check if the allocation token exists and
|
||||
// is for this domain.
|
||||
if (getReservationTypes(domainName).contains(RESERVED_FOR_ANCHOR_TENANT)) {
|
||||
// If there wasn't an allocation token specified, then use the fallback of attempting to load
|
||||
// the token with the specified EPP authcode.
|
||||
// TODO(b/111827374): Remove the authInfoPw fallback and only accept an allocation token.
|
||||
if (!token.isPresent()) {
|
||||
token =
|
||||
Optional.ofNullable(
|
||||
ofy().load().key(Key.create(AllocationToken.class, authInfoPw)).now());
|
||||
}
|
||||
// If the token exists, check if it's valid for this domain.
|
||||
if (token.isPresent()
|
||||
&& token.get().getDomainName().isPresent()
|
||||
&& token.get().getDomainName().get().equals(domainName.toString())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Otherwise check whether the metadata extension is being used by a superuser to specify that
|
||||
// it's an anchor tenant creation.
|
||||
return metadataExtension.isPresent() && metadataExtension.get().getIsAnchorTenant();
|
||||
}
|
||||
|
||||
/** Check if the registrar running the flow has access to the TLD in question. */
|
||||
public static void checkAllowedAccessToTld(String clientId, String tld) throws EppException {
|
||||
if (!Registrar.loadByClientIdCached(clientId).get().getAllowedTlds().contains(tld)) {
|
||||
|
@ -411,10 +445,12 @@ public class DomainFlowUtils {
|
|||
}
|
||||
}
|
||||
|
||||
private static final ImmutableSet<ReservationType> RESERVED_TYPES =
|
||||
ImmutableSet.of(RESERVED_FOR_SPECIFIC_USE, RESERVED_FOR_ANCHOR_TENANT, FULLY_BLOCKED);
|
||||
|
||||
private static boolean isReserved(InternetDomainName domainName, boolean isSunrise) {
|
||||
ImmutableSet<ReservationType> types = getReservationTypes(domainName);
|
||||
return types.contains(FULLY_BLOCKED)
|
||||
|| types.contains(RESERVED_FOR_ANCHOR_TENANT)
|
||||
return !Sets.intersection(types, RESERVED_TYPES).isEmpty()
|
||||
|| !(isSunrise || intersection(TYPES_ALLOWED_FOR_CREATE_ONLY_IN_SUNRISE, types).isEmpty());
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkArgument;
|
|||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
|
@ -100,7 +101,8 @@ public class AllocationToken extends BackupGroupRoot implements Buildable {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder setCreationTime(DateTime creationTime) {
|
||||
@VisibleForTesting
|
||||
public Builder setCreationTimeForTest(DateTime creationTime) {
|
||||
checkState(
|
||||
getInstance().creationTime.getTimestamp() == null, "creationTime can only be set once");
|
||||
getInstance().creationTime = CreateAutoTimestamp.create(creationTime);
|
||||
|
|
|
@ -18,7 +18,6 @@ import static com.google.common.base.Preconditions.checkArgument;
|
|||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Predicates.equalTo;
|
||||
import static com.google.common.base.Predicates.not;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static google.registry.config.RegistryConfig.getSingletonCacheRefreshDuration;
|
||||
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
|
@ -36,8 +35,6 @@ import com.google.common.cache.LoadingCache;
|
|||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.LinkedHashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Ordering;
|
||||
import com.google.common.collect.Range;
|
||||
import com.google.common.net.InternetDomainName;
|
||||
|
@ -61,10 +58,7 @@ import google.registry.model.domain.fee.Fee;
|
|||
import google.registry.model.registry.label.PremiumList;
|
||||
import google.registry.model.registry.label.ReservationType;
|
||||
import google.registry.model.registry.label.ReservedList;
|
||||
import google.registry.model.registry.label.ReservedList.ReservedListEntry;
|
||||
import google.registry.util.Idn;
|
||||
import java.util.Collection;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
@ -837,7 +831,6 @@ public class Registry extends ImmutableObject implements Buildable {
|
|||
|
||||
public Builder setReservedLists(Set<ReservedList> reservedLists) {
|
||||
checkArgumentNotNull(reservedLists, "reservedLists must not be null");
|
||||
checkAuthCodeConflicts(reservedLists);
|
||||
ImmutableSet.Builder<Key<ReservedList>> builder = new ImmutableSet.Builder<>();
|
||||
for (ReservedList reservedList : reservedLists) {
|
||||
builder.add(Key.create(reservedList));
|
||||
|
@ -846,31 +839,6 @@ public class Registry extends ImmutableObject implements Buildable {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that domain names don't have conflicting auth codes across different reserved lists.
|
||||
*/
|
||||
private static void checkAuthCodeConflicts(Set<ReservedList> reservedLists) {
|
||||
Multimap<String, String> allAuthCodes = LinkedHashMultimap.create();
|
||||
for (ReservedList list : reservedLists) {
|
||||
for (ReservedListEntry entry : list.getReservedListEntries().values()) {
|
||||
if (entry.getAuthCode() != null) {
|
||||
allAuthCodes.put(entry.getLabel(), entry.getAuthCode());
|
||||
}
|
||||
}
|
||||
}
|
||||
ImmutableSet<Entry<String, Collection<String>>> conflicts =
|
||||
allAuthCodes
|
||||
.asMap()
|
||||
.entrySet()
|
||||
.stream()
|
||||
.filter((Entry<String, Collection<String>> entry) -> entry.getValue().size() > 1)
|
||||
.collect(toImmutableSet());
|
||||
checkArgument(
|
||||
conflicts.isEmpty(),
|
||||
"Cannot set reserved lists because of auth code conflicts for labels: %s",
|
||||
conflicts);
|
||||
}
|
||||
|
||||
public Builder setPremiumList(PremiumList premiumList) {
|
||||
getInstance().premiumList = (premiumList == null) ? null : Key.create(premiumList);
|
||||
return this;
|
||||
|
|
|
@ -22,7 +22,11 @@ import com.google.common.collect.Ordering;
|
|||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/** Enum describing reservation on a label in a {@link ReservedList} */
|
||||
/**
|
||||
* Enum describing reservation on a label in a {@link ReservedList}.
|
||||
*
|
||||
* <p>Note that superusers can override reservations and register a domain no matter what.
|
||||
*/
|
||||
public enum ReservationType {
|
||||
|
||||
// We explicitly set the severity, even though we have a checkState that makes it equal to the
|
||||
|
@ -30,12 +34,30 @@ public enum ReservationType {
|
|||
// label has multiple reservation types, its message is the that of the one with the highest
|
||||
// severity.
|
||||
|
||||
/** Nameservers on the domain are restricted to a given set. */
|
||||
NAMESERVER_RESTRICTED("Nameserver restricted", 0),
|
||||
|
||||
/** The domain can only be registered during sunrise, and is reserved thereafter. */
|
||||
ALLOWED_IN_SUNRISE("Reserved for non-sunrise", 1),
|
||||
|
||||
/** The domain can only be registered during sunrise, and is reserved thereafter. */
|
||||
@Deprecated
|
||||
MISTAKEN_PREMIUM("Reserved", 2),
|
||||
RESERVED_FOR_ANCHOR_TENANT("Reserved", 3),
|
||||
NAME_COLLISION("Cannot be delegated", 4),
|
||||
FULLY_BLOCKED("Reserved", 5);
|
||||
|
||||
/** The domain can only be registered by providing a specific token. */
|
||||
RESERVED_FOR_SPECIFIC_USE("Reserved", 3),
|
||||
|
||||
/** The domain is for an anchor tenant and can only be registered using a specific token. */
|
||||
RESERVED_FOR_ANCHOR_TENANT("Reserved", 4),
|
||||
|
||||
/**
|
||||
* The domain can only be registered during sunrise for defensive purposes, and will never
|
||||
* resolve.
|
||||
*/
|
||||
NAME_COLLISION("Cannot be delegated", 5),
|
||||
|
||||
/** The domain can never be registered. */
|
||||
FULLY_BLOCKED("Reserved", 6);
|
||||
|
||||
@Nullable
|
||||
private final String messageForCheck;
|
||||
|
|
|
@ -16,15 +16,12 @@ package google.registry.model.registry.label;
|
|||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static com.google.common.collect.Iterables.getOnlyElement;
|
||||
import static google.registry.config.RegistryConfig.getDomainLabelListCacheDuration;
|
||||
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.registry.label.ReservationType.FULLY_BLOCKED;
|
||||
import static google.registry.model.registry.label.ReservationType.NAMESERVER_RESTRICTED;
|
||||
import static google.registry.model.registry.label.ReservationType.RESERVED_FOR_ANCHOR_TENANT;
|
||||
import static google.registry.util.CollectionUtils.nullToEmpty;
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
|
@ -77,12 +74,6 @@ public final class ReservedList
|
|||
|
||||
ReservationType reservationType;
|
||||
|
||||
/**
|
||||
* Contains the auth code necessary to register a domain with this label. Note that this field
|
||||
* will only ever be populated for entries with type RESERVED_FOR_ANCHOR_TENANT.
|
||||
*/
|
||||
String authCode;
|
||||
|
||||
/**
|
||||
* Contains a comma-delimited list of the fully qualified hostnames of the nameservers that can
|
||||
* be set on a domain with this label (only applicable to NAMESERVER_RESTRICTED).
|
||||
|
@ -114,34 +105,21 @@ public final class ReservedList
|
|||
public static ReservedListEntry create(
|
||||
String label,
|
||||
ReservationType reservationType,
|
||||
@Nullable String restrictions,
|
||||
@Nullable String allowedNameservers,
|
||||
@Nullable String comment) {
|
||||
ReservedListEntry.Builder builder =
|
||||
ReservedListEntry.Builder entry =
|
||||
new ReservedListEntry.Builder()
|
||||
.setLabel(label)
|
||||
.setComment(comment)
|
||||
.setReservationType(reservationType);
|
||||
if (restrictions != null) {
|
||||
checkArgument(
|
||||
reservationType == RESERVED_FOR_ANCHOR_TENANT
|
||||
|| reservationType == NAMESERVER_RESTRICTED,
|
||||
"Only anchor tenant and nameserver restricted reservations "
|
||||
+ "should have restrictions imposed");
|
||||
if (reservationType == RESERVED_FOR_ANCHOR_TENANT) {
|
||||
builder.setAuthCode(restrictions);
|
||||
} else if (reservationType == NAMESERVER_RESTRICTED) {
|
||||
builder.setAllowedNameservers(
|
||||
ImmutableSet.copyOf(Splitter.on(':').trimResults().split(restrictions)));
|
||||
}
|
||||
} else {
|
||||
checkArgument(
|
||||
reservationType != RESERVED_FOR_ANCHOR_TENANT,
|
||||
"Anchor tenant reservations must have an auth code configured");
|
||||
checkArgument(
|
||||
reservationType != NAMESERVER_RESTRICTED,
|
||||
"Nameserver restricted reservations must have at least one nameserver configured");
|
||||
checkArgument(
|
||||
(reservationType == NAMESERVER_RESTRICTED) ^ (allowedNameservers == null),
|
||||
"Allowed nameservers must be specified for NAMESERVER_RESTRICTED reservations only");
|
||||
if (allowedNameservers != null) {
|
||||
entry.setAllowedNameservers(
|
||||
ImmutableSet.copyOf(Splitter.on(':').trimResults().split(allowedNameservers)));
|
||||
}
|
||||
return builder.build();
|
||||
return entry.build();
|
||||
}
|
||||
|
||||
private static void checkNameserversAreValid(Set<String> nameservers) {
|
||||
|
@ -159,10 +137,6 @@ public final class ReservedList
|
|||
return reservationType;
|
||||
}
|
||||
|
||||
public String getAuthCode() {
|
||||
return authCode;
|
||||
}
|
||||
|
||||
public ImmutableSet<String> getAllowedNameservers() {
|
||||
return ImmutableSet.copyOf(Splitter.on(',').splitToList(allowedNameservers));
|
||||
}
|
||||
|
@ -188,11 +162,6 @@ public final class ReservedList
|
|||
return this;
|
||||
}
|
||||
|
||||
ReservedListEntry.Builder setAuthCode(String authCode) {
|
||||
getInstance().authCode = authCode;
|
||||
return this;
|
||||
}
|
||||
|
||||
ReservedListEntry.Builder setReservationType(ReservationType reservationType) {
|
||||
getInstance().reservationType = reservationType;
|
||||
return this;
|
||||
|
@ -256,27 +225,6 @@ public final class ReservedList
|
|||
.collect(toImmutableSet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given label and TLD is reserved for an anchor tenant, and the given auth
|
||||
* code matches the one set on the reservation. If there are multiple anchor tenant entries for
|
||||
* this label, all the auth codes need to be the same and match the given one, otherwise an
|
||||
* exception is thrown.
|
||||
*/
|
||||
public static boolean matchesAnchorTenantReservation(
|
||||
InternetDomainName domainName, String authCode) {
|
||||
|
||||
ImmutableSet<String> domainAuthCodes =
|
||||
getReservedListEntries(domainName.parts().get(0), domainName.parent().toString())
|
||||
.stream()
|
||||
.filter((entry) -> entry.reservationType == RESERVED_FOR_ANCHOR_TENANT)
|
||||
.map(ReservedListEntry::getAuthCode)
|
||||
.collect(toImmutableSet());
|
||||
checkState(
|
||||
domainAuthCodes.size() <= 1, "There are conflicting auth codes for domain: %s", domainName);
|
||||
|
||||
return !domainAuthCodes.isEmpty() && getOnlyElement(domainAuthCodes).equals(authCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of nameservers that can be set on the given domain.
|
||||
*
|
||||
|
|
|
@ -82,10 +82,12 @@ public class DomainCheckFlowTest
|
|||
}
|
||||
|
||||
private ReservedList createReservedList() {
|
||||
persistResource(
|
||||
new AllocationToken.Builder().setDomainName("anchor.tld").setToken("2fooBAR").build());
|
||||
return persistReservedList(
|
||||
"tld-reserved",
|
||||
"reserved,FULLY_BLOCKED",
|
||||
"anchor,RESERVED_FOR_ANCHOR_TENANT,foo2BAR",
|
||||
"anchor,RESERVED_FOR_ANCHOR_TENANT",
|
||||
"allowedinsunrise,ALLOWED_IN_SUNRISE",
|
||||
"collision,NAME_COLLISION",
|
||||
"premiumcollision,NAME_COLLISION");
|
||||
|
|
|
@ -180,6 +180,8 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
|
|||
@Before
|
||||
public void initCreateTest() {
|
||||
createTld("tld");
|
||||
persistResource(
|
||||
new AllocationToken.Builder().setToken("abcDEF23456").setDomainName("anchor.tld").build());
|
||||
persistResource(
|
||||
Registry.get("tld")
|
||||
.asBuilder()
|
||||
|
@ -187,7 +189,8 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
|
|||
persistReservedList(
|
||||
"tld-reserved",
|
||||
"reserved,FULLY_BLOCKED",
|
||||
"anchor,RESERVED_FOR_ANCHOR_TENANT,2fooBAR",
|
||||
"resdom,RESERVED_FOR_SPECIFIC_USE",
|
||||
"anchor,RESERVED_FOR_ANCHOR_TENANT",
|
||||
"test-and-validate,NAME_COLLISION",
|
||||
"badcrash,NAME_COLLISION"))
|
||||
.build());
|
||||
|
@ -404,7 +407,7 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
|
|||
|
||||
@Test
|
||||
public void testFailure_invalidAllocationToken() {
|
||||
setEppInput("domain_create_allocationtoken.xml");
|
||||
setEppInput("domain_create_allocationtoken.xml", ImmutableMap.of("DOMAIN", "example.tld"));
|
||||
persistContactsAndHosts();
|
||||
EppException thrown = assertThrows(InvalidAllocationTokenException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
|
@ -412,7 +415,7 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
|
|||
|
||||
@Test
|
||||
public void testFailure_alreadyRedemeedAllocationToken() {
|
||||
setEppInput("domain_create_allocationtoken.xml");
|
||||
setEppInput("domain_create_allocationtoken.xml", ImmutableMap.of("DOMAIN", "example.tld"));
|
||||
persistContactsAndHosts();
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
|
@ -427,7 +430,7 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
|
|||
|
||||
@Test
|
||||
public void testSuccess_validAllocationToken_isRedeemed() throws Exception {
|
||||
setEppInput("domain_create_allocationtoken.xml");
|
||||
setEppInput("domain_create_allocationtoken.xml", ImmutableMap.of("DOMAIN", "example.tld"));
|
||||
persistContactsAndHosts();
|
||||
AllocationToken token =
|
||||
persistResource(new AllocationToken.Builder().setToken("abc123").build());
|
||||
|
@ -1066,7 +1069,7 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_anchorTenantViaAuthCode_wrongAuthCode() {
|
||||
public void testFailure_anchorTenant_viaAuthCode_wrongAuthCode() {
|
||||
setEppInput("domain_create_anchor_wrong_authcode.xml");
|
||||
persistContactsAndHosts();
|
||||
EppException thrown = assertThrows(DomainReservedException.class, this::runFlow);
|
||||
|
@ -1074,7 +1077,7 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_anchorTenantViaAuthCode_notTwoYearPeriod() {
|
||||
public void testFailure_anchorTenant_notTwoYearPeriod() {
|
||||
setEppInput("domain_create_anchor_authcode_invalid_years.xml");
|
||||
persistContactsAndHosts();
|
||||
EppException thrown = assertThrows(AnchorTenantCreatePeriodException.class, this::runFlow);
|
||||
|
@ -1082,7 +1085,7 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_anchorTenantViaAuthCode_matchingLrpToken() throws Exception {
|
||||
public void testSuccess_anchorTenant_viaAuthCode_matchingLrpToken() throws Exception {
|
||||
// This is definitely a corner case, as (without superuser) anchor tenants may only register
|
||||
// via auth code during GA. We're running this as superuser to bypass the state checks, though
|
||||
// anchor tenant code checks and LRP token redemption still happen regardless.
|
||||
|
@ -1091,7 +1094,7 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
|
|||
Registry.get("tld")
|
||||
.asBuilder()
|
||||
.setReservedLists(
|
||||
persistReservedList("tld-reserved", "anchor,RESERVED_FOR_ANCHOR_TENANT,2fooBAR"))
|
||||
persistReservedList("tld-reserved", "anchor,RESERVED_FOR_ANCHOR_TENANT"))
|
||||
.build());
|
||||
LrpTokenEntity token =
|
||||
persistResource(
|
||||
|
@ -1107,7 +1110,7 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_anchorTenantViaAuthCode() throws Exception {
|
||||
public void testSuccess_anchorTenant_viaAuthCode() throws Exception {
|
||||
setEppInput("domain_create_anchor_authcode.xml");
|
||||
persistContactsAndHosts();
|
||||
runFlowAssertResponse(loadFile("domain_create_anchor_response.xml"));
|
||||
|
@ -1116,7 +1119,21 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_anchorTenantViaAuthCode_duringLrp() throws Exception {
|
||||
public void testSuccess_anchorTenant_viaAllocationTokenExtension() throws Exception {
|
||||
setEppInput("domain_create_anchor_allocationtoken.xml");
|
||||
persistContactsAndHosts();
|
||||
runFlowAssertResponse(loadFile("domain_create_anchor_response.xml"));
|
||||
assertSuccessfulCreate("tld", ImmutableSet.of(ANCHOR_TENANT));
|
||||
assertNoLordn();
|
||||
AllocationToken reloadedToken =
|
||||
ofy().load().key(Key.create(AllocationToken.class, "abcDEF23456")).now();
|
||||
assertThat(reloadedToken.isRedeemed()).isTrue();
|
||||
assertThat(reloadedToken.getRedemptionHistoryEntry())
|
||||
.isEqualTo(Key.create(getHistoryEntries(reloadResourceByForeignKey()).get(0)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_anchorTenant_viaAuthCode_duringLrp() throws Exception {
|
||||
persistResource(
|
||||
Registry.get("tld")
|
||||
.asBuilder()
|
||||
|
@ -1130,7 +1147,7 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_anchorTenantViaExtension_duringLrp() throws Exception {
|
||||
public void testSuccess_anchorTenant_viaExtension_duringLrp() throws Exception {
|
||||
persistResource(
|
||||
Registry.get("tld")
|
||||
.asBuilder()
|
||||
|
@ -1146,13 +1163,15 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_anchorTenantViaAuthCode_withClaims() throws Exception {
|
||||
public void testSuccess_anchorTenant_viaAuthCode_withClaims() throws Exception {
|
||||
persistResource(
|
||||
new AllocationToken.Builder().setDomainName("example-one.tld").setToken("2fooBAR").build());
|
||||
persistResource(
|
||||
Registry.get("tld")
|
||||
.asBuilder()
|
||||
.setReservedLists(
|
||||
persistReservedList(
|
||||
"anchor-with-claims", "example-one,RESERVED_FOR_ANCHOR_TENANT,2fooBAR"))
|
||||
"anchor-with-claims", "example-one,RESERVED_FOR_ANCHOR_TENANT"))
|
||||
.build());
|
||||
setEppInput("domain_create_claim_notice.xml");
|
||||
clock.setTo(DateTime.parse("2009-08-16T09:00:00.0Z"));
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<create>
|
||||
<domain:create
|
||||
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
|
||||
<domain:name>example.tld</domain:name>
|
||||
<domain:name>%DOMAIN%</domain:name>
|
||||
<domain:period unit="y">2</domain:period>
|
||||
<domain:ns>
|
||||
<domain:hostObj>ns1.example.net</domain:hostObj>
|
||||
|
|
29
javatests/google/registry/flows/domain/testdata/domain_create_anchor_allocationtoken.xml
vendored
Normal file
29
javatests/google/registry/flows/domain/testdata/domain_create_anchor_allocationtoken.xml
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
|
||||
<command>
|
||||
<create>
|
||||
<domain:create
|
||||
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
|
||||
<domain:name>anchor.tld</domain:name>
|
||||
<domain:period unit="y">2</domain:period>
|
||||
<domain:ns>
|
||||
<domain:hostObj>ns1.example.net</domain:hostObj>
|
||||
<domain:hostObj>ns2.example.net</domain:hostObj>
|
||||
</domain:ns>
|
||||
<domain:registrant>jd1234</domain:registrant>
|
||||
<domain:contact type="admin">sh8013</domain:contact>
|
||||
<domain:contact type="tech">sh8013</domain:contact>
|
||||
<domain:authInfo>
|
||||
<domain:pw>2fooBAR</domain:pw>
|
||||
</domain:authInfo>
|
||||
</domain:create>
|
||||
</create>
|
||||
<extension>
|
||||
<allocationToken:allocationToken
|
||||
xmlns:allocationToken=
|
||||
"urn:ietf:params:xml:ns:allocationToken-1.0">
|
||||
abcDEF23456
|
||||
</allocationToken:allocationToken>
|
||||
</extension>
|
||||
<clTRID>ABC-12345</clTRID>
|
||||
</command>
|
||||
</epp>
|
|
@ -13,7 +13,7 @@
|
|||
<domain:contact type="admin">sh8013</domain:contact>
|
||||
<domain:contact type="tech">sh8013</domain:contact>
|
||||
<domain:authInfo>
|
||||
<domain:pw>2fooBAR</domain:pw>
|
||||
<domain:pw>abcDEF23456</domain:pw>
|
||||
</domain:authInfo>
|
||||
</domain:create>
|
||||
</create>
|
||||
|
|
|
@ -17,6 +17,13 @@
|
|||
</domain:authInfo>
|
||||
</domain:create>
|
||||
</create>
|
||||
<extension>
|
||||
<allocationToken:allocationToken
|
||||
xmlns:allocationToken=
|
||||
"urn:ietf:params:xml:ns:allocationToken-1.0">
|
||||
abcDEF23456
|
||||
</allocationToken:allocationToken>
|
||||
</extension>
|
||||
<clTRID>ABC-12345</clTRID>
|
||||
</command>
|
||||
</epp>
|
||||
|
|
|
@ -37,7 +37,7 @@ public class AllocationTokenTest extends EntityTestCase {
|
|||
.setToken("abc123")
|
||||
.setRedemptionHistoryEntry(Key.create(HistoryEntry.class, 1L))
|
||||
.setDomainName("foo.example")
|
||||
.setCreationTime(DateTime.parse("2010-11-12T05:00:00Z"))
|
||||
.setCreationTimeForTest(DateTime.parse("2010-11-12T05:00:00Z"))
|
||||
.build());
|
||||
assertThat(ofy().load().entity(token).now()).isEqualTo(token);
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ public class AllocationTokenTest extends EntityTestCase {
|
|||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setDomainName("blahdomain.fake")
|
||||
.setCreationTime(DateTime.parse("2010-11-12T05:00:00Z"))
|
||||
.setCreationTimeForTest(DateTime.parse("2010-11-12T05:00:00Z"))
|
||||
.build()),
|
||||
"token",
|
||||
"domainName");
|
||||
|
@ -69,11 +69,11 @@ public class AllocationTokenTest extends EntityTestCase {
|
|||
AllocationToken.Builder builder =
|
||||
new AllocationToken.Builder()
|
||||
.setToken("foobar")
|
||||
.setCreationTime(DateTime.parse("2010-11-12T05:00:00Z"));
|
||||
.setCreationTimeForTest(DateTime.parse("2010-11-12T05:00:00Z"));
|
||||
IllegalStateException thrown =
|
||||
assertThrows(
|
||||
IllegalStateException.class,
|
||||
() -> builder.setCreationTime(DateTime.parse("2010-11-13T05:00:00Z")));
|
||||
() -> builder.setCreationTimeForTest(DateTime.parse("2010-11-13T05:00:00Z")));
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("creationTime can only be set once");
|
||||
}
|
||||
|
||||
|
|
|
@ -180,46 +180,6 @@ public class RegistryTest extends EntityTestCase {
|
|||
assertThat(r.getReservedLists()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetReservedLists_succeedsWithDuplicateIdenticalAuthCodes() {
|
||||
ReservedList rl1 = persistReservedList(
|
||||
"tld-reserved007",
|
||||
"lol,RESERVED_FOR_ANCHOR_TENANT,identical",
|
||||
"cat,FULLY_BLOCKED");
|
||||
ReservedList rl2 = persistReservedList(
|
||||
"tld-reserved008",
|
||||
"lol,RESERVED_FOR_ANCHOR_TENANT,identical",
|
||||
"tim,FULLY_BLOCKED");
|
||||
Registry registry = Registry.get("tld").asBuilder().setReservedLists(rl1, rl2).build();
|
||||
assertThat(registry.getReservedLists()).containsExactly(Key.create(rl1), Key.create(rl2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetReservedLists_failsForConflictingAuthCodes() {
|
||||
ReservedList rl1 = persistReservedList(
|
||||
"tld-reserved055",
|
||||
"lol,RESERVED_FOR_ANCHOR_TENANT,conflict1",
|
||||
"cat,FULLY_BLOCKED");
|
||||
ReservedList rl2 = persistReservedList(
|
||||
"tld-reserved056",
|
||||
"lol,RESERVED_FOR_ANCHOR_TENANT,conflict2",
|
||||
"tim,FULLY_BLOCKED");
|
||||
ReservedList rl3 = persistReservedList(
|
||||
"tld-reserved057",
|
||||
"lol,RESERVED_FOR_ANCHOR_TENANT,another_conflict");
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> {
|
||||
@SuppressWarnings("unused")
|
||||
Registry unused =
|
||||
Registry.get("tld").asBuilder().setReservedLists(rl1, rl2, rl3).build();
|
||||
});
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.contains("auth code conflicts for labels: [lol=[conflict1, conflict2, another_conflict]]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetPremiumList() {
|
||||
PremiumList pl2 = persistPremiumList("tld2", "lol,USD 50", "cat,USD 700");
|
||||
|
|
|
@ -23,13 +23,10 @@ import static google.registry.model.registry.label.DomainLabelMetrics.reservedLi
|
|||
import static google.registry.model.registry.label.DomainLabelMetrics.reservedListProcessingTime;
|
||||
import static google.registry.model.registry.label.ReservationType.ALLOWED_IN_SUNRISE;
|
||||
import static google.registry.model.registry.label.ReservationType.FULLY_BLOCKED;
|
||||
import static google.registry.model.registry.label.ReservationType.MISTAKEN_PREMIUM;
|
||||
import static google.registry.model.registry.label.ReservationType.NAMESERVER_RESTRICTED;
|
||||
import static google.registry.model.registry.label.ReservationType.NAME_COLLISION;
|
||||
import static google.registry.model.registry.label.ReservationType.RESERVED_FOR_ANCHOR_TENANT;
|
||||
import static google.registry.model.registry.label.ReservedList.getAllowedNameservers;
|
||||
import static google.registry.model.registry.label.ReservedList.getReservationTypes;
|
||||
import static google.registry.model.registry.label.ReservedList.matchesAnchorTenantReservation;
|
||||
import static google.registry.testing.DatastoreHelper.createTld;
|
||||
import static google.registry.testing.DatastoreHelper.persistReservedList;
|
||||
import static google.registry.testing.DatastoreHelper.persistResource;
|
||||
|
@ -118,47 +115,6 @@ public class ReservedListTest {
|
|||
verifyUnreservedCheckCount(26);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchesAnchorTenantReservation() {
|
||||
persistResource(
|
||||
Registry.get("tld")
|
||||
.asBuilder()
|
||||
.setReservedLists(ImmutableSet.of(
|
||||
persistReservedList(
|
||||
"reserved1",
|
||||
"lol,RESERVED_FOR_ANCHOR_TENANT,foobar1",
|
||||
"lol2,RESERVED_FOR_ANCHOR_TENANT,abcdefg # This is a comment")))
|
||||
.build());
|
||||
assertThat(getReservationTypes("lol", "tld")).containsExactly(RESERVED_FOR_ANCHOR_TENANT);
|
||||
assertThat(getReservationTypes("lol2", "tld")).containsExactly(RESERVED_FOR_ANCHOR_TENANT);
|
||||
assertThat(matchesAnchorTenantReservation(InternetDomainName.from("lol.tld"), "foobar1"))
|
||||
.isTrue();
|
||||
assertThat(matchesAnchorTenantReservation(InternetDomainName.from("lol.tld"), "foobar"))
|
||||
.isFalse();
|
||||
assertThat(matchesAnchorTenantReservation(InternetDomainName.from("lol2.tld"), "abcdefg"))
|
||||
.isTrue();
|
||||
assertThat(matchesAnchorTenantReservation(InternetDomainName.from("lol2.tld"), "abcdefg "))
|
||||
.isFalse();
|
||||
assertThat(matchesAnchorTenantReservation(InternetDomainName.from("random.tld"), "abcdefg"))
|
||||
.isFalse();
|
||||
assertThat(reservedListChecks)
|
||||
.hasValueForLabels(1, "tld", "0", "(none)", "(none)")
|
||||
.and()
|
||||
.hasValueForLabels(6, "tld", "1", "reserved1", RESERVED_FOR_ANCHOR_TENANT.toString())
|
||||
.and()
|
||||
.hasNoOtherValues();
|
||||
assertThat(reservedListProcessingTime)
|
||||
.hasAnyValueForLabels("tld", "0", "(none)", "(none)")
|
||||
.and()
|
||||
.hasAnyValueForLabels("tld", "1", "reserved1", RESERVED_FOR_ANCHOR_TENANT.toString())
|
||||
.and()
|
||||
.hasNoOtherValues();
|
||||
assertThat(reservedListHits)
|
||||
.hasValueForLabels(6, "tld", "reserved1", RESERVED_FOR_ANCHOR_TENANT.toString())
|
||||
.and()
|
||||
.hasNoOtherValues();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAllowedNameservers() {
|
||||
ReservedList rl1 =
|
||||
|
@ -191,87 +147,6 @@ public class ReservedListTest {
|
|||
assertThat(getAllowedNameservers(InternetDomainName.from("lol4.tld"))).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchesAnchorTenantReservation_falseOnOtherReservationTypes() {
|
||||
persistResource(
|
||||
Registry.get("tld")
|
||||
.asBuilder()
|
||||
.setReservedLists(
|
||||
ImmutableSet.of(
|
||||
persistReservedList(
|
||||
"reserved2",
|
||||
"lol,FULLY_BLOCKED",
|
||||
"lol2,NAME_COLLISION",
|
||||
"lol3,MISTAKEN_PREMIUM",
|
||||
"lol4,ALLOWED_IN_SUNRISE",
|
||||
"lol5,NAMESERVER_RESTRICTED,na1.domain.tld")))
|
||||
.build());
|
||||
assertThat(matchesAnchorTenantReservation(InternetDomainName.from("lol.tld"), "")).isFalse();
|
||||
assertThat(matchesAnchorTenantReservation(InternetDomainName.from("lol2.tld"), "")).isFalse();
|
||||
assertThat(matchesAnchorTenantReservation(InternetDomainName.from("lol3.tld"), "")).isFalse();
|
||||
assertThat(matchesAnchorTenantReservation(InternetDomainName.from("lol4.tld"), "")).isFalse();
|
||||
assertThat(matchesAnchorTenantReservation(InternetDomainName.from("lol5.tld"), "")).isFalse();
|
||||
assertThat(matchesAnchorTenantReservation(InternetDomainName.from("lol6.tld"), "")).isFalse();
|
||||
assertThat(reservedListChecks)
|
||||
.hasValueForLabels(1, "tld", "1", "reserved2", FULLY_BLOCKED.toString())
|
||||
.and()
|
||||
.hasValueForLabels(1, "tld", "1", "reserved2", NAME_COLLISION.toString())
|
||||
.and()
|
||||
.hasValueForLabels(1, "tld", "1", "reserved2", MISTAKEN_PREMIUM.toString())
|
||||
.and()
|
||||
.hasValueForLabels(1, "tld", "1", "reserved2", ALLOWED_IN_SUNRISE.toString())
|
||||
.and()
|
||||
.hasValueForLabels(1, "tld", "1", "reserved2", NAMESERVER_RESTRICTED.toString())
|
||||
.and()
|
||||
.hasValueForLabels(1, "tld", "0", "(none)", "(none)")
|
||||
.and()
|
||||
.hasNoOtherValues();
|
||||
assertThat(reservedListProcessingTime)
|
||||
.hasAnyValueForLabels("tld", "1", "reserved2", FULLY_BLOCKED.toString())
|
||||
.and()
|
||||
.hasAnyValueForLabels("tld", "1", "reserved2", NAME_COLLISION.toString())
|
||||
.and()
|
||||
.hasAnyValueForLabels("tld", "1", "reserved2", MISTAKEN_PREMIUM.toString())
|
||||
.and()
|
||||
.hasAnyValueForLabels("tld", "1", "reserved2", ALLOWED_IN_SUNRISE.toString())
|
||||
.and()
|
||||
.hasAnyValueForLabels("tld", "1", "reserved2", NAMESERVER_RESTRICTED.toString())
|
||||
.and()
|
||||
.hasAnyValueForLabels("tld", "0", "(none)", "(none)")
|
||||
.and()
|
||||
.hasNoOtherValues();
|
||||
assertThat(reservedListHits)
|
||||
.hasValueForLabels(1, "tld", "reserved2", FULLY_BLOCKED.toString())
|
||||
.and()
|
||||
.hasValueForLabels(1, "tld", "reserved2", NAME_COLLISION.toString())
|
||||
.and()
|
||||
.hasValueForLabels(1, "tld", "reserved2", MISTAKEN_PREMIUM.toString())
|
||||
.and()
|
||||
.hasValueForLabels(1, "tld", "reserved2", ALLOWED_IN_SUNRISE.toString())
|
||||
.and()
|
||||
.hasValueForLabels(1, "tld", "reserved2", NAMESERVER_RESTRICTED.toString())
|
||||
.and()
|
||||
.hasNoOtherValues();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchesAnchorTenantReservation_duplicatingAuthCodes() {
|
||||
ReservedList rl1 = persistReservedList("reserved1", "lol,RESERVED_FOR_ANCHOR_TENANT,foo");
|
||||
ReservedList rl2 = persistReservedList("reserved2", "lol,RESERVED_FOR_ANCHOR_TENANT,foo");
|
||||
createTld("tld");
|
||||
persistResource(Registry.get("tld").asBuilder().setReservedLists(rl1, rl2).build());
|
||||
assertThat(matchesAnchorTenantReservation(InternetDomainName.from("lol.tld"), "foo")).isTrue();
|
||||
assertThat(matchesAnchorTenantReservation(InternetDomainName.from("lol.tld"), "bar")).isFalse();
|
||||
persistReservedList("reserved2", "lol,RESERVED_FOR_ANCHOR_TENANT,bar");
|
||||
IllegalStateException thrown =
|
||||
assertThrows(
|
||||
IllegalStateException.class,
|
||||
() -> matchesAnchorTenantReservation(InternetDomainName.from("lol.tld"), "bar"));
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.contains("There are conflicting auth codes for domain: lol.tld");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetReservationTypes_concatsMultipleListsCorrectly() {
|
||||
ReservedList rl1 = persistReservedList(
|
||||
|
@ -494,8 +369,7 @@ public class ReservedListTest {
|
|||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.contains(
|
||||
"Only anchor tenant and nameserver restricted reservations "
|
||||
+ "should have restrictions imposed");
|
||||
"Allowed nameservers must be specified for NAMESERVER_RESTRICTED reservations only");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -524,24 +398,6 @@ public class ReservedListTest {
|
|||
assertThat(thrown).hasMessageThat().contains("domain.tld is not a valid nameserver hostname");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSave_noPasswordWithAnchorTenantReservation() {
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() ->
|
||||
persistResource(
|
||||
Registry.get("tld")
|
||||
.asBuilder()
|
||||
.setReservedLists(
|
||||
ImmutableSet.of(
|
||||
persistReservedList("reserved1", "lol,RESERVED_FOR_ANCHOR_TENANT")))
|
||||
.build()));
|
||||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.contains("Anchor tenant reservations must have an auth code configured");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSave_noNameserversWithNameserverRestrictedReservation() {
|
||||
IllegalArgumentException thrown =
|
||||
|
@ -558,7 +414,7 @@ public class ReservedListTest {
|
|||
assertThat(thrown)
|
||||
.hasMessageThat()
|
||||
.contains(
|
||||
"Nameserver restricted reservations must have at least one nameserver configured");
|
||||
"Allowed nameservers must be specified for NAMESERVER_RESTRICTED reservations only");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -723,6 +723,7 @@ enum google.registry.model.registry.label.ReservationType {
|
|||
NAMESERVER_RESTRICTED;
|
||||
NAME_COLLISION;
|
||||
RESERVED_FOR_ANCHOR_TENANT;
|
||||
RESERVED_FOR_SPECIFIC_USE;
|
||||
}
|
||||
class google.registry.model.registry.label.ReservedList {
|
||||
@Id java.lang.String name;
|
||||
|
@ -737,7 +738,6 @@ class google.registry.model.registry.label.ReservedList$ReservedListEntry {
|
|||
@Id java.lang.String label;
|
||||
google.registry.model.registry.label.ReservationType reservationType;
|
||||
java.lang.String allowedNameservers;
|
||||
java.lang.String authCode;
|
||||
java.lang.String comment;
|
||||
}
|
||||
class google.registry.model.reporting.DomainTransactionRecord {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue