Delete all Limited Release Program (LRP) code

We never used it and don't have any plans to use it going forward. All
conceivable parts of its functionality that we might use going forward have
already been subsumed into allocation tokens, which are a simpler way of
handling the same use case that are also standards-compliant.

Also gets rid of the hideous ANCHOR_ prefix on anchor tenant EPP authcodes
that was only ever necessary because of overloading the authcode for
anchor tenant creation. Going forward it'll be based on allocation tokens,
so there's no risk of conflicts.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=209418194
This commit is contained in:
mcilwain 2018-08-20 08:03:41 -07:00 committed by jianglai
parent f7bc17fbe8
commit 7b87ba41c7
34 changed files with 12 additions and 1601 deletions

View file

@ -296,8 +296,6 @@ An EPP flow that creates a new application for a domain resource.
* 2201 * 2201
* Registrar is not authorized to access this TLD. * Registrar is not authorized to access this TLD.
* Registrar must be active in order to create domains or applications. * Registrar must be active in order to create domains or applications.
* 2202
* Invalid limited registration period token.
* 2302 * 2302
* Resource with this id already exists. * Resource with this id already exists.
* This name has already been claimed by a sunrise applicant. * This name has already been claimed by a sunrise applicant.
@ -559,8 +557,6 @@ An EPP flow that creates a new domain resource.
* Only a tool can pass a metadata extension. * Only a tool can pass a metadata extension.
* Registrar is not authorized to access this TLD. * Registrar is not authorized to access this TLD.
* Registrar must be active in order to create domains or applications. * Registrar must be active in order to create domains or applications.
* 2202
* Invalid limited registration period token.
* 2302 * 2302
* Resource with this id already exists. * Resource with this id already exists.
* 2303 * 2303

View file

@ -23,7 +23,6 @@ import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToT
import static google.registry.flows.domain.DomainFlowUtils.cloneAndLinkReferences; import static google.registry.flows.domain.DomainFlowUtils.cloneAndLinkReferences;
import static google.registry.flows.domain.DomainFlowUtils.createFeeCreateResponse; import static google.registry.flows.domain.DomainFlowUtils.createFeeCreateResponse;
import static google.registry.flows.domain.DomainFlowUtils.isAnchorTenant; 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.validateCreateCommandContactsAndNameservers;
import static google.registry.flows.domain.DomainFlowUtils.validateDomainName; import static google.registry.flows.domain.DomainFlowUtils.validateDomainName;
import static google.registry.flows.domain.DomainFlowUtils.validateDomainNameWithIdnTables; import static google.registry.flows.domain.DomainFlowUtils.validateDomainNameWithIdnTables;
@ -128,7 +127,6 @@ import org.joda.time.DateTime;
* @error {@link DomainFlowUtils.FeesMismatchException} * @error {@link DomainFlowUtils.FeesMismatchException}
* @error {@link DomainFlowUtils.FeesRequiredForPremiumNameException} * @error {@link DomainFlowUtils.FeesRequiredForPremiumNameException}
* @error {@link DomainFlowUtils.InvalidIdnDomainLabelException} * @error {@link DomainFlowUtils.InvalidIdnDomainLabelException}
* @error {@link DomainFlowUtils.InvalidLrpTokenException}
* @error {@link DomainFlowUtils.InvalidPunycodeException} * @error {@link DomainFlowUtils.InvalidPunycodeException}
* @error {@link DomainFlowUtils.InvalidTcnIdChecksumException} * @error {@link DomainFlowUtils.InvalidTcnIdChecksumException}
* @error {@link DomainFlowUtils.InvalidTrademarkValidatorException} * @error {@link DomainFlowUtils.InvalidTrademarkValidatorException}
@ -277,12 +275,7 @@ public final class DomainApplicationCreateFlow implements TransactionalFlow {
historyEntry, historyEntry,
DomainApplicationIndex.createUpdatedInstance(newApplication), DomainApplicationIndex.createUpdatedInstance(newApplication),
EppResourceIndex.create(Key.create(newApplication))); EppResourceIndex.create(Key.create(newApplication)));
// Anchor tenant registrations override LRP, and landrush applications can skip it.
// If a token is passed in outside of an LRP phase, it is simply ignored (i.e. never redeemed).
if (registry.getLrpPeriod().contains(now) && !isAnchorTenant) {
entitiesToSave.add(
prepareMarkedLrpTokenEntity(authInfo.getPw().getValue(), domainName, historyEntry));
}
EntityChanges entityChanges = EntityChanges entityChanges =
flowCustomLogic.beforeSave( flowCustomLogic.beforeSave(
DomainApplicationCreateFlowCustomLogic.BeforeSaveParameters.newBuilder() DomainApplicationCreateFlowCustomLogic.BeforeSaveParameters.newBuilder()

View file

@ -23,7 +23,6 @@ import static google.registry.flows.domain.DomainFlowUtils.cloneAndLinkReference
import static google.registry.flows.domain.DomainFlowUtils.createFeeCreateResponse; import static google.registry.flows.domain.DomainFlowUtils.createFeeCreateResponse;
import static google.registry.flows.domain.DomainFlowUtils.getReservationTypes; import static google.registry.flows.domain.DomainFlowUtils.getReservationTypes;
import static google.registry.flows.domain.DomainFlowUtils.isAnchorTenant; 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.validateCreateCommandContactsAndNameservers;
import static google.registry.flows.domain.DomainFlowUtils.validateDomainAllowedOnCreateRestrictedTld; import static google.registry.flows.domain.DomainFlowUtils.validateDomainAllowedOnCreateRestrictedTld;
import static google.registry.flows.domain.DomainFlowUtils.validateDomainName; import static google.registry.flows.domain.DomainFlowUtils.validateDomainName;
@ -159,7 +158,6 @@ import org.joda.time.Duration;
* @error {@link DomainFlowUtils.FeesRequiredDuringEarlyAccessProgramException} * @error {@link DomainFlowUtils.FeesRequiredDuringEarlyAccessProgramException}
* @error {@link DomainFlowUtils.FeesRequiredForPremiumNameException} * @error {@link DomainFlowUtils.FeesRequiredForPremiumNameException}
* @error {@link DomainFlowUtils.InvalidIdnDomainLabelException} * @error {@link DomainFlowUtils.InvalidIdnDomainLabelException}
* @error {@link DomainFlowUtils.InvalidLrpTokenException}
* @error {@link DomainFlowUtils.InvalidPunycodeException} * @error {@link DomainFlowUtils.InvalidPunycodeException}
* @error {@link DomainFlowUtils.InvalidTcnIdChecksumException} * @error {@link DomainFlowUtils.InvalidTcnIdChecksumException}
* @error {@link DomainFlowUtils.InvalidTrademarkValidatorException} * @error {@link DomainFlowUtils.InvalidTrademarkValidatorException}
@ -371,15 +369,8 @@ public class DomainCreateFlow implements TransactionalFlow {
newDomain, newDomain,
ForeignKeyIndex.create(newDomain, newDomain.getDeletionTime()), ForeignKeyIndex.create(newDomain, newDomain.getDeletionTime()),
EppResourceIndex.create(Key.create(newDomain))); EppResourceIndex.create(Key.create(newDomain)));
allocationToken.ifPresent( allocationToken.ifPresent(
t -> entitiesToSave.add(allocationTokenFlowUtils.redeemToken(t, Key.create(historyEntry)))); t -> entitiesToSave.add(allocationTokenFlowUtils.redeemToken(t, Key.create(historyEntry))));
// Anchor tenant registrations override LRP, and landrush applications can skip it.
// If a token is passed in outside of an LRP phase, it is simply ignored (i.e. never redeemed).
if (isLrpCreate(registry, isAnchorTenant, now)) {
entitiesToSave.add(
prepareMarkedLrpTokenEntity(authInfo.getPw().getValue(), domainName, historyEntry));
}
enqueueTasks(newDomain, hasSignedMarks, hasClaimsNotice); enqueueTasks(newDomain, hasSignedMarks, hasClaimsNotice);
EntityChanges entityChanges = EntityChanges entityChanges =
@ -596,10 +587,6 @@ public class DomainCreateFlow implements TransactionalFlow {
.build(); .build();
} }
private boolean isLrpCreate(Registry registry, boolean isAnchorTenant, DateTime now) {
return registry.getLrpPeriod().contains(now) && !isAnchorTenant;
}
private void enqueueTasks( private void enqueueTasks(
DomainResource newDomain, boolean hasSignedMarks, boolean hasClaimsNotice) { DomainResource newDomain, boolean hasSignedMarks, boolean hasClaimsNotice) {
if (newDomain.shouldPublishToDns()) { if (newDomain.shouldPublishToDns()) {

View file

@ -22,7 +22,6 @@ import static com.google.common.collect.Iterables.any;
import static com.google.common.collect.Sets.difference; import static com.google.common.collect.Sets.difference;
import static com.google.common.collect.Sets.intersection; import static com.google.common.collect.Sets.intersection;
import static com.google.common.collect.Sets.union; import static com.google.common.collect.Sets.union;
import static google.registry.flows.domain.DomainPricingLogic.getMatchingLrpToken;
import static google.registry.model.domain.DomainResource.MAX_REGISTRATION_YEARS; import static google.registry.model.domain.DomainResource.MAX_REGISTRATION_YEARS;
import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.registry.Registries.findTldForName; import static google.registry.model.registry.Registries.findTldForName;
@ -55,7 +54,6 @@ import com.googlecode.objectify.Key;
import google.registry.flows.EppException; import google.registry.flows.EppException;
import google.registry.flows.EppException.AuthorizationErrorException; import google.registry.flows.EppException.AuthorizationErrorException;
import google.registry.flows.EppException.CommandUseErrorException; import google.registry.flows.EppException.CommandUseErrorException;
import google.registry.flows.EppException.InvalidAuthorizationInformationErrorException;
import google.registry.flows.EppException.ObjectDoesNotExistException; import google.registry.flows.EppException.ObjectDoesNotExistException;
import google.registry.flows.EppException.ParameterValuePolicyErrorException; import google.registry.flows.EppException.ParameterValuePolicyErrorException;
import google.registry.flows.EppException.ParameterValueRangeErrorException; import google.registry.flows.EppException.ParameterValueRangeErrorException;
@ -80,7 +78,6 @@ import google.registry.model.domain.DomainCommand.InvalidReferencesException;
import google.registry.model.domain.DomainCommand.Update; import google.registry.model.domain.DomainCommand.Update;
import google.registry.model.domain.DomainResource; import google.registry.model.domain.DomainResource;
import google.registry.model.domain.ForeignKeyedDesignatedContact; import google.registry.model.domain.ForeignKeyedDesignatedContact;
import google.registry.model.domain.LrpTokenEntity;
import google.registry.model.domain.Period; import google.registry.model.domain.Period;
import google.registry.model.domain.fee.BaseFee.FeeType; import google.registry.model.domain.fee.BaseFee.FeeType;
import google.registry.model.domain.fee.Credit; import google.registry.model.domain.fee.Credit;
@ -992,17 +989,6 @@ public class DomainFlowUtils {
} }
} }
/** Create a {@link LrpTokenEntity} object that records this LRP registration. */
static LrpTokenEntity prepareMarkedLrpTokenEntity(
String lrpTokenString, InternetDomainName domainName, HistoryEntry historyEntry)
throws InvalidLrpTokenException {
Optional<LrpTokenEntity> lrpToken = getMatchingLrpToken(lrpTokenString, domainName);
if (!lrpToken.isPresent()) {
throw new InvalidLrpTokenException();
}
return lrpToken.get().asBuilder().setRedemptionHistoryEntry(Key.create(historyEntry)).build();
}
/** Check that there are no code marks, which is a type of mark we don't support. */ /** Check that there are no code marks, which is a type of mark we don't support. */
static void verifyNoCodeMarks(LaunchCreateExtension launchCreate) static void verifyNoCodeMarks(LaunchCreateExtension launchCreate)
throws UnsupportedMarkTypeException { throws UnsupportedMarkTypeException {
@ -1587,13 +1573,6 @@ public class DomainFlowUtils {
} }
} }
/** Invalid limited registration period token. */
static class InvalidLrpTokenException extends InvalidAuthorizationInformationErrorException {
public InvalidLrpTokenException() {
super("Invalid limited registration period token");
}
}
/** Only encoded signed marks are supported. */ /** Only encoded signed marks are supported. */
static class UnsupportedMarkTypeException extends ParameterValuePolicyErrorException { static class UnsupportedMarkTypeException extends ParameterValuePolicyErrorException {
public UnsupportedMarkTypeException() { public UnsupportedMarkTypeException() {

View file

@ -14,13 +14,11 @@
package google.registry.flows.domain; package google.registry.flows.domain;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.pricing.PricingEngineProxy.getDomainCreateCost; import static google.registry.pricing.PricingEngineProxy.getDomainCreateCost;
import static google.registry.pricing.PricingEngineProxy.getDomainFeeClass; import static google.registry.pricing.PricingEngineProxy.getDomainFeeClass;
import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost; import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost;
import com.google.common.net.InternetDomainName; import com.google.common.net.InternetDomainName;
import com.googlecode.objectify.Key;
import google.registry.flows.EppException; import google.registry.flows.EppException;
import google.registry.flows.FlowScope; import google.registry.flows.FlowScope;
import google.registry.flows.custom.DomainPricingCustomLogic; import google.registry.flows.custom.DomainPricingCustomLogic;
@ -31,7 +29,6 @@ import google.registry.flows.custom.DomainPricingCustomLogic.RestorePriceParamet
import google.registry.flows.custom.DomainPricingCustomLogic.TransferPriceParameters; import google.registry.flows.custom.DomainPricingCustomLogic.TransferPriceParameters;
import google.registry.flows.custom.DomainPricingCustomLogic.UpdatePriceParameters; import google.registry.flows.custom.DomainPricingCustomLogic.UpdatePriceParameters;
import google.registry.model.domain.DomainApplication; import google.registry.model.domain.DomainApplication;
import google.registry.model.domain.LrpTokenEntity;
import google.registry.model.domain.fee.BaseFee; import google.registry.model.domain.fee.BaseFee;
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;
@ -186,28 +183,4 @@ public final class DomainPricingLogic {
public Optional<String> getFeeClass(String domainName, DateTime date) { public Optional<String> getFeeClass(String domainName, DateTime date) {
return getDomainFeeClass(domainName, date); return getDomainFeeClass(domainName, date);
} }
/**
* Checks whether an LRP token String maps to a valid {@link LrpTokenEntity} for the domain name's
* TLD, and return that entity (wrapped in an {@link Optional}) if one exists.
*
* <p>This method has no knowledge of whether or not an auth code (interpreted here as an LRP
* token) has already been checked against the reserved list for QLP (anchor tenant), as auth
* codes are used for both types of registrations.
*/
public static Optional<LrpTokenEntity> getMatchingLrpToken(
String lrpToken, InternetDomainName domainName) {
// Note that until the actual per-TLD logic is built out, what's being done here is a basic
// domain-name-to-assignee match.
if (!lrpToken.isEmpty()) {
LrpTokenEntity token = ofy().load().key(Key.create(LrpTokenEntity.class, lrpToken)).now();
if (token != null
&& token.getAssignee().equalsIgnoreCase(domainName.toString())
&& token.getRedemptionHistoryEntry() == null
&& token.getValidTlds().contains(domainName.parent().toString())) {
return Optional.of(token);
}
}
return Optional.empty();
}
} }

View file

@ -23,7 +23,6 @@ import google.registry.model.contact.ContactResource;
import google.registry.model.domain.DomainApplication; import google.registry.model.domain.DomainApplication;
import google.registry.model.domain.DomainBase; import google.registry.model.domain.DomainBase;
import google.registry.model.domain.DomainResource; import google.registry.model.domain.DomainResource;
import google.registry.model.domain.LrpTokenEntity;
import google.registry.model.domain.token.AllocationToken; import google.registry.model.domain.token.AllocationToken;
import google.registry.model.host.HostResource; import google.registry.model.host.HostResource;
import google.registry.model.index.DomainApplicationIndex; import google.registry.model.index.DomainApplicationIndex;
@ -91,7 +90,6 @@ public final class EntityClasses {
KmsSecret.class, KmsSecret.class,
KmsSecretRevision.class, KmsSecretRevision.class,
Lock.class, Lock.class,
LrpTokenEntity.class,
PollMessage.class, PollMessage.class,
PollMessage.Autorenew.class, PollMessage.Autorenew.class,
PollMessage.OneTime.class, PollMessage.OneTime.class,

View file

@ -1,130 +0,0 @@
// Copyright 2017 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.model.domain;
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.EmbedMap;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.annotation.Index;
import google.registry.model.BackupGroupRoot;
import google.registry.model.Buildable;
import google.registry.model.annotations.ReportedOn;
import google.registry.model.reporting.HistoryEntry;
import java.util.Map;
import java.util.Set;
/** An entity representing a token distributed to eligible LRP registrants. */
@ReportedOn
@Entity
public class LrpTokenEntity extends BackupGroupRoot implements Buildable {
/**
* The secret token assigned to a registrant for the purposes of LRP registration.
*/
@Id
String token;
/**
* The token's assignee (additional metadata for identifying the owner of the token, the details
* of which might differ from TLD to TLD).
*/
@Index
String assignee;
/**
* A list of TLDs for which this LRP token is valid.
*/
Set<String> validTlds;
/**
* The key of the history entry for which the token was used.
*/
Key<HistoryEntry> redemptionHistoryEntry;
/**
* A set of key-value properties associated with the LRP token. This map can be used to store
* additional metadata about the assignee or space of domain names for which this token can be
* valid.
*/
@EmbedMap
Map<String, String> metadata;
public String getToken() {
return token;
}
public String getAssignee() {
return assignee;
}
public Key<HistoryEntry> getRedemptionHistoryEntry() {
return redemptionHistoryEntry;
}
public boolean isRedeemed() {
return redemptionHistoryEntry != null;
}
public Set<String> getValidTlds() {
return nullToEmptyImmutableCopy(validTlds);
}
public Map<String, String> getMetadata() {
return nullToEmptyImmutableCopy(metadata);
}
@Override
public Builder asBuilder() {
return new Builder(clone(this));
}
/** A builder for constructing {@link LrpTokenEntity} objects, since they are immutable. */
public static class Builder extends Buildable.Builder<LrpTokenEntity> {
public Builder() {}
private Builder(LrpTokenEntity instance) {
super(instance);
}
public Builder setAssignee(String assignee) {
getInstance().assignee = assignee;
return this;
}
public Builder setToken(String token) {
getInstance().token = checkArgumentNotNull(token);
return this;
}
public Builder setRedemptionHistoryEntry(Key<HistoryEntry> redemptionHistoryEntry) {
getInstance().redemptionHistoryEntry = checkArgumentNotNull(redemptionHistoryEntry);
return this;
}
public Builder setValidTlds(Set<String> validTlds) {
getInstance().validTlds = validTlds;
return this;
}
public Builder setMetadata(Map<String, String> metadata) {
getInstance().metadata = metadata;
return this;
}
}
}

View file

@ -68,7 +68,6 @@ import org.joda.money.CurrencyUnit;
import org.joda.money.Money; import org.joda.money.Money;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.joda.time.Duration; import org.joda.time.Duration;
import org.joda.time.Interval;
/** Persisted per-TLD configuration data. */ /** Persisted per-TLD configuration data. */
@ReportedOn @ReportedOn
@ -430,20 +429,6 @@ public class Registry extends ImmutableObject implements Buildable {
/** The end of the claims period (at or after this time, claims no longer applies). */ /** The end of the claims period (at or after this time, claims no longer applies). */
DateTime claimsPeriodEnd = END_OF_TIME; DateTime claimsPeriodEnd = END_OF_TIME;
/**
* The (inclusive) start {@link DateTime} of LRP. This (and lrpPeriodEnd) exist for serialization
* purposes, though everything else that interacts with the LRP period should use getLrpPeriod()
* and setLrpPeriod(), which uses an {@link Interval}.
*/
DateTime lrpPeriodStart;
/**
* The (exclusive) end {@link DateTime} of LRP. This (and lrpPeriodStart) exist for serialization
* purposes, though everything else that interacts with the LRP period should use getLrpPeriod()
* and setLrpPeriod(), which uses an {@link Interval}.
*/
DateTime lrpPeriodEnd;
/** A whitelist of clients allowed to be used on domains on this TLD (ignored if empty). */ /** A whitelist of clients allowed to be used on domains on this TLD (ignored if empty). */
Set<String> allowedRegistrantContactIds; Set<String> allowedRegistrantContactIds;
@ -646,12 +631,6 @@ public class Registry extends ImmutableObject implements Buildable {
return nullToEmptyImmutableCopy(allowedFullyQualifiedHostNames); return nullToEmptyImmutableCopy(allowedFullyQualifiedHostNames);
} }
public Interval getLrpPeriod() {
return (lrpPeriodStart == null && lrpPeriodEnd == null)
? new Interval(START_OF_TIME, Duration.ZERO) // An empty duration.
: new Interval(lrpPeriodStart, lrpPeriodEnd);
}
@Override @Override
public Builder asBuilder() { public Builder asBuilder() {
return new Builder(clone(this)); return new Builder(clone(this));
@ -920,12 +899,6 @@ public class Registry extends ImmutableObject implements Buildable {
return this; return this;
} }
public Builder setLrpPeriod(@Nullable Interval lrpPeriod) {
getInstance().lrpPeriodStart = (lrpPeriod == null ? null : lrpPeriod.getStart());
getInstance().lrpPeriodEnd = (lrpPeriod == null ? null : lrpPeriod.getEnd());
return this;
}
@Override @Override
public Registry build() { public Registry build() {
final Registry instance = getInstance(); final Registry instance = getInstance();

View file

@ -18,8 +18,7 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Strings.isNullOrEmpty; import static com.google.common.base.Strings.isNullOrEmpty;
import static google.registry.model.registry.Registries.findTldForNameOrThrow; import static google.registry.model.registry.Registries.findTldForNameOrThrow;
import static google.registry.pricing.PricingEngineProxy.getDomainCreateCost; import static google.registry.pricing.PricingEngineProxy.getDomainCreateCost;
import static google.registry.util.TokenUtils.TokenType.ANCHOR_TENANT; import static google.registry.util.StringGenerator.DEFAULT_PASSWORD_LENGTH;
import static google.registry.util.TokenUtils.createToken;
import static org.joda.time.DateTimeZone.UTC; import static org.joda.time.DateTimeZone.UTC;
import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameter;
@ -80,7 +79,7 @@ final class CreateAnchorTenantCommand extends MutatingEppToolCommand {
checkArgument(superuser, "This command must be run as a superuser."); checkArgument(superuser, "This command must be run as a superuser.");
findTldForNameOrThrow(InternetDomainName.from(domainName)); // Check that the tld exists. findTldForNameOrThrow(InternetDomainName.from(domainName)); // Check that the tld exists.
if (isNullOrEmpty(password)) { if (isNullOrEmpty(password)) {
password = createToken(ANCHOR_TENANT, passwordGenerator); password = passwordGenerator.createString(DEFAULT_PASSWORD_LENGTH);
} }
Money cost = null; Money cost = null;

View file

@ -1,202 +0,0 @@
// Copyright 2017 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.tools;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Strings.isNullOrEmpty;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.collect.Sets.difference;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.registry.Registries.assertTldsExist;
import static google.registry.util.TokenUtils.TokenType.LRP;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
import com.google.appengine.tools.remoteapi.RemoteApiException;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.CharMatcher;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.Files;
import com.google.common.io.LineReader;
import com.googlecode.objectify.Key;
import google.registry.model.domain.LrpTokenEntity;
import google.registry.tools.Command.RemoteApiCommand;
import google.registry.tools.params.KeyValueMapParameter.StringToIntegerMap;
import google.registry.tools.params.KeyValueMapParameter.StringToStringMap;
import google.registry.tools.params.PathParameter;
import google.registry.util.NonFinalForTesting;
import google.registry.util.Retrier;
import google.registry.util.StringGenerator;
import google.registry.util.TokenUtils;
import java.io.StringReader;
import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
import javax.inject.Inject;
/**
* Command to create one or more LRP tokens, given assignee(s) as either a parameter or a text file.
*/
@NonFinalForTesting
@Parameters(
separators = " =",
commandDescription = "Create an LRP token for a given assignee (using -a) or import a text"
+ " file of assignees for bulk token creation (using -i). Assignee/token pairs are printed"
+ " to stdout, and should be piped to a file for distribution to assignees or for cleanup"
+ " in the event of a command interruption.")
public class CreateLrpTokensCommand implements RemoteApiCommand {
@Parameter(
names = {"-a", "--assignee"},
description = "LRP token assignee")
private String assignee;
@Parameter(
names = {"-t", "--tlds"},
description = "Comma-delimited list of TLDs that the tokens to create will be valid on",
required = true)
private List<String> tlds;
@Parameter(
names = {"-i", "--input"},
description = "Filename containing a list of assignees, newline-delimited",
validateWith = PathParameter.InputFile.class)
private Path assigneesFile;
@Parameter(
names = {"-m", "--metadata"},
description = "Token metadata key-value pairs (formatted as key=value[,key=value...]). Used"
+ " only in conjunction with -a/--assignee when creating a single token.",
converter = StringToStringMap.class,
validateWith = StringToStringMap.class)
private ImmutableMap<String, String> metadata;
@Parameter(
names = {"-c", "--metadata_columns"},
description = "Token metadata columns (formatted as key=index[,key=index...], columns are"
+ " zero-indexed). Used only in conjunction with -i/--input to map additional fields in"
+ " the CSV file to metadata stored on the LRP token. The index corresponds to the column"
+ " number in the CSV file (where the assignee is assigned column 0).",
converter = StringToIntegerMap.class,
validateWith = StringToIntegerMap.class)
private ImmutableMap<String, Integer> metadataColumns;
@Inject StringGenerator stringGenerator;
@Inject Retrier retrier;
private static final int BATCH_SIZE = 20;
// Ensures that all of the double quotes to the right of a comma are balanced. In a well-formed
// CSV line, there can be no leading double quote preceding the comma.
private static final String COMMA_EXCEPT_WHEN_QUOTED_REGEX =
",(?=([^\\\"]*\\\"[^\\\"]*\\\")*[^\\\"]*$)";
@Override
public void run() throws Exception {
checkArgument(
(assignee == null) == (assigneesFile != null),
"Exactly one of either assignee or filename must be specified.");
checkArgument(
(assigneesFile == null) || (metadata == null),
"Metadata cannot be specified along with a filename.");
checkArgument(
(assignee == null) || (metadataColumns == null),
"Metadata columns cannot be specified along with an assignee.");
ImmutableSet<String> validTlds = ImmutableSet.copyOf(assertTldsExist(tlds));
LineReader reader = new LineReader(
(assigneesFile != null)
? Files.newReader(assigneesFile.toFile(), UTF_8)
: new StringReader(assignee));
String line = null;
do {
ImmutableSet.Builder<LrpTokenEntity> tokensToSaveBuilder = new ImmutableSet.Builder<>();
for (String token : generateTokens(BATCH_SIZE)) {
line = reader.readLine();
if (!isNullOrEmpty(line)) {
ImmutableList<String> values =
ImmutableList.copyOf(
Splitter.onPattern(COMMA_EXCEPT_WHEN_QUOTED_REGEX)
// Results should not be surrounded in double quotes.
.trimResults(CharMatcher.is('\"'))
.split(line));
LrpTokenEntity.Builder tokenBuilder = new LrpTokenEntity.Builder()
.setAssignee(values.get(0))
.setToken(token)
.setValidTlds(validTlds);
if (metadata != null) {
tokenBuilder.setMetadata(metadata);
} else if (metadataColumns != null) {
ImmutableMap.Builder<String, String> metadataBuilder = ImmutableMap.builder();
for (ImmutableMap.Entry<String, Integer> entry : metadataColumns.entrySet()) {
checkArgument(
values.size() > entry.getValue(),
"Entry for %s does not have a value for %s (index %s)",
values.get(0),
entry.getKey(),
entry.getValue());
metadataBuilder.put(entry.getKey(), values.get(entry.getValue()));
}
tokenBuilder.setMetadata(metadataBuilder.build());
}
tokensToSaveBuilder.add(tokenBuilder.build());
}
}
final ImmutableSet<LrpTokenEntity> tokensToSave = tokensToSaveBuilder.build();
// Wrap in a retrier to deal with transient 404 errors (thrown as RemoteApiExceptions).
retrier.callWithRetry(() -> saveTokens(tokensToSave), RemoteApiException.class);
} while (line != null);
}
@VisibleForTesting
void saveTokens(final ImmutableSet<LrpTokenEntity> tokens) {
Collection<LrpTokenEntity> savedTokens =
ofy().transact(() -> ofy().save().entities(tokens).now().values());
for (LrpTokenEntity token : savedTokens) {
System.out.printf("%s,%s%n", token.getAssignee(), token.getToken());
}
}
/**
* This function generates at MOST {@code count} tokens, after filtering out any token strings
* that already exist.
*
* <p>Note that in the incredibly rare case that all generated tokens already exist, this function
* may return an empty set.
*/
private ImmutableSet<String> generateTokens(int count) {
final ImmutableSet<String> candidates =
ImmutableSet.copyOf(TokenUtils.createTokens(LRP, stringGenerator, count));
ImmutableSet<Key<LrpTokenEntity>> existingTokenKeys =
candidates
.stream()
.map(input -> Key.create(LrpTokenEntity.class, input))
.collect(toImmutableSet());
ImmutableSet<String> existingTokenStrings =
ofy()
.load()
.keys(existingTokenKeys)
.values()
.stream()
.map(LrpTokenEntity::getToken)
.collect(toImmutableSet());
return ImmutableSet.copyOf(difference(candidates, existingTokenStrings));
}
}

View file

@ -32,7 +32,6 @@ import google.registry.model.registry.Registry;
import google.registry.model.registry.Registry.TldState; import google.registry.model.registry.Registry.TldState;
import google.registry.model.registry.Registry.TldType; import google.registry.model.registry.Registry.TldType;
import google.registry.model.registry.label.PremiumList; import google.registry.model.registry.label.PremiumList;
import google.registry.tools.params.OptionalIntervalParameter;
import google.registry.tools.params.OptionalStringParameter; import google.registry.tools.params.OptionalStringParameter;
import google.registry.tools.params.TransitionListParameter.BillingCostTransitions; import google.registry.tools.params.TransitionListParameter.BillingCostTransitions;
import google.registry.tools.params.TransitionListParameter.TldStateTransitions; import google.registry.tools.params.TransitionListParameter.TldStateTransitions;
@ -46,7 +45,6 @@ import javax.inject.Named;
import org.joda.money.Money; import org.joda.money.Money;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.joda.time.Duration; import org.joda.time.Duration;
import org.joda.time.Interval;
/** Shared base class for commands to create or update a TLD. */ /** Shared base class for commands to create or update a TLD. */
abstract class CreateOrUpdateTldCommand extends MutatingCommand { abstract class CreateOrUpdateTldCommand extends MutatingCommand {
@ -242,15 +240,6 @@ abstract class CreateOrUpdateTldCommand extends MutatingCommand {
) )
Integer numDnsPublishShards; Integer numDnsPublishShards;
@Nullable
@Parameter(
names = "--lrp_period",
description =
"LRP period (in ISO-8601 format, e.g. 2004-06-09T12:30:00Z/2004-07-10T13:30:00Z",
converter = OptionalIntervalParameter.class,
validateWith = OptionalIntervalParameter.class)
private Optional<Interval> lrpPeriod;
/** Returns the existing registry (for update) or null (for creates). */ /** Returns the existing registry (for update) or null (for creates). */
@Nullable @Nullable
abstract Registry getOldRegistry(String tld); abstract Registry getOldRegistry(String tld);
@ -358,7 +347,6 @@ abstract class CreateOrUpdateTldCommand extends MutatingCommand {
Optional.ofNullable(claimsPeriodEnd).ifPresent(builder::setClaimsPeriodEnd); Optional.ofNullable(claimsPeriodEnd).ifPresent(builder::setClaimsPeriodEnd);
Optional.ofNullable(domainCreateRestricted).ifPresent(builder::setDomainCreateRestricted); Optional.ofNullable(domainCreateRestricted).ifPresent(builder::setDomainCreateRestricted);
Optional.ofNullable(numDnsPublishShards).ifPresent(builder::setNumDnsPublishLocks); Optional.ofNullable(numDnsPublishShards).ifPresent(builder::setNumDnsPublishLocks);
Optional.ofNullable(lrpPeriod).ifPresent(p -> builder.setLrpPeriod(p.orElse(null)));
if (premiumListName != null) { if (premiumListName != null) {
if (premiumListName.isPresent()) { if (premiumListName.isPresent()) {

View file

@ -19,6 +19,7 @@ import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.collect.Queues.newArrayDeque; import static com.google.common.collect.Queues.newArrayDeque;
import static com.google.common.collect.Sets.difference; import static com.google.common.collect.Sets.difference;
import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.util.StringGenerator.DEFAULT_PASSWORD_LENGTH;
import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.charset.StandardCharsets.UTF_8;
import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameter;
@ -73,7 +74,7 @@ public class GenerateAllocationTokensCommand implements RemoteApiCommand {
names = {"-l", "--length"}, names = {"-l", "--length"},
description = "The length of each token, exclusive of the prefix (if specified); defaults to 16" description = "The length of each token, exclusive of the prefix (if specified); defaults to 16"
) )
private int tokenLength = 16; private int tokenLength = DEFAULT_PASSWORD_LENGTH;
@Parameter( @Parameter(
names = {"--dry_run"}, names = {"--dry_run"},

View file

@ -1,79 +0,0 @@
// Copyright 2017 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.tools;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.model.ofy.ObjectifyService.ofy;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
import google.registry.model.domain.LrpTokenEntity;
import google.registry.tools.Command.RemoteApiCommand;
/** Command to show token information for LRP participants. */
@Parameters(
separators = " =",
commandDescription = "Show token information for LRP participants by matching on a "
+ "known token or a unique ID (assignee).")
public final class GetLrpTokenCommand implements RemoteApiCommand {
@Parameter(
names = {"-t", "--token"},
description = "LRP access token (auth code) to check")
private String tokenString;
@Parameter(
names = {"-a", "--assignee"},
description = "LRP token assignee")
private String assignee;
@Parameter(
names = {"-h", "--history"},
description = "Return expanded history entry (including domain application)")
private boolean includeHistory = false;
@Override
public void run() {
checkArgument(
(tokenString == null) == (assignee != null),
"Exactly one of either token or assignee must be specified.");
ImmutableSet.Builder<LrpTokenEntity> tokensBuilder = new ImmutableSet.Builder<>();
if (tokenString != null) {
LrpTokenEntity token =
ofy().load().key(Key.create(LrpTokenEntity.class, tokenString)).now();
if (token != null) {
tokensBuilder.add(token);
}
} else {
tokensBuilder.addAll(ofy().load().type(LrpTokenEntity.class).filter("assignee", assignee));
}
ImmutableSet<LrpTokenEntity> tokens = tokensBuilder.build();
if (!tokens.isEmpty()) {
for (LrpTokenEntity token : tokens) {
System.out.println(token);
if (includeHistory && token.getRedemptionHistoryEntry() != null) {
System.out.println(
ofy().load().key(token.getRedemptionHistoryEntry()).now().toHydratedString());
}
}
} else {
System.out.println("Token not found.");
}
}
}

View file

@ -41,7 +41,6 @@ public final class RegistryTool {
.put("create_contact", CreateContactCommand.class) .put("create_contact", CreateContactCommand.class)
.put("create_domain", CreateDomainCommand.class) .put("create_domain", CreateDomainCommand.class)
.put("create_host", CreateHostCommand.class) .put("create_host", CreateHostCommand.class)
.put("create_lrp_tokens", CreateLrpTokensCommand.class)
.put("create_premium_list", CreatePremiumListCommand.class) .put("create_premium_list", CreatePremiumListCommand.class)
.put("create_registrar", CreateRegistrarCommand.class) .put("create_registrar", CreateRegistrarCommand.class)
.put("create_registrar_groups", CreateRegistrarGroupsCommand.class) .put("create_registrar_groups", CreateRegistrarGroupsCommand.class)
@ -74,7 +73,6 @@ public final class RegistryTool {
.put("get_history_entries", GetHistoryEntriesCommand.class) .put("get_history_entries", GetHistoryEntriesCommand.class)
.put("get_host", GetHostCommand.class) .put("get_host", GetHostCommand.class)
.put("get_keyring_secret", GetKeyringSecretCommand.class) .put("get_keyring_secret", GetKeyringSecretCommand.class)
.put("get_lrp_token", GetLrpTokenCommand.class)
.put("get_registrar", GetRegistrarCommand.class) .put("get_registrar", GetRegistrarCommand.class)
.put("get_resource_by_key", GetResourceByKeyCommand.class) .put("get_resource_by_key", GetResourceByKeyCommand.class)
.put("get_routing_map", GetRoutingMapCommand.class) .put("get_routing_map", GetRoutingMapCommand.class)

View file

@ -80,7 +80,6 @@ interface RegistryToolComponent {
void inject(CreateCdnsTld command); void inject(CreateCdnsTld command);
void inject(CreateContactCommand command); void inject(CreateContactCommand command);
void inject(CreateDomainCommand command); void inject(CreateDomainCommand command);
void inject(CreateLrpTokensCommand command);
void inject(CreateTldCommand command); void inject(CreateTldCommand command);
void inject(DeployInvoicingPipelineCommand command); void inject(DeployInvoicingPipelineCommand command);
void inject(DeploySpec11PipelineCommand command); void inject(DeploySpec11PipelineCommand command);

View file

@ -23,6 +23,8 @@ import java.util.Collection;
/** String generator. */ /** String generator. */
public abstract class StringGenerator { public abstract class StringGenerator {
public static final int DEFAULT_PASSWORD_LENGTH = 16;
/** A class containing different alphabets used to generate strings. */ /** A class containing different alphabets used to generate strings. */
public static class Alphabets { public static class Alphabets {

View file

@ -1,71 +0,0 @@
// Copyright 2017 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.util;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
/**
* A utility class for generating various auth tokens using a common prefixed-based format.
* These tokens are generally of the form [TYPE]_[randomstring].
*/
public final class TokenUtils {
/** An enum containing definitions (prefix and length) for token types. */
public enum TokenType {
ANCHOR_TENANT("ANCHOR", 16),
LRP("LRP", 16);
private final String prefix;
private final int length;
TokenType(String prefix, int length) {
this.prefix = prefix;
this.length = length;
}
/** Returns the prefix for a given type. */
public String getPrefix() {
return prefix;
}
/** Returns the set token length for a given type (not including the prefix). */
public int getLength() {
return length;
}
}
/** Generates a single token of a given {@link TokenType}. */
public static String createToken(TokenType type, StringGenerator generator) {
return Iterables.getOnlyElement(createTokens(type, generator, 1));
}
/** Generates an {@link ImmutableSet} of tokens of a given {@link TokenType}. */
public static ImmutableSet<String> createTokens(
final TokenType type,
StringGenerator generator,
int count) {
return generator
.createStrings(type.getLength(), count)
.stream()
.map(token -> String.format("%s_%s", type.getPrefix(), token))
.collect(toImmutableSet());
}
private TokenUtils() {}
}

View file

@ -13,7 +13,6 @@ HistoryEntry
HostResource HostResource
KmsSecret KmsSecret
KmsSecretRevision KmsSecretRevision
LrpTokenEntity
Modification Modification
OneTime OneTime
PollMessage PollMessage

View file

@ -11,7 +11,6 @@ HistoryEntry
HostResource HostResource
KmsSecret KmsSecret
KmsSecretRevision KmsSecretRevision
LrpTokenEntity
Modification Modification
OneTime OneTime
PremiumList PremiumList

View file

@ -42,7 +42,6 @@ import com.google.common.base.Strings;
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;
import com.googlecode.objectify.Key;
import google.registry.flows.EppException; import google.registry.flows.EppException;
import google.registry.flows.EppException.UnimplementedExtensionException; import google.registry.flows.EppException.UnimplementedExtensionException;
import google.registry.flows.ResourceFlowTestCase; import google.registry.flows.ResourceFlowTestCase;
@ -84,7 +83,6 @@ import google.registry.flows.domain.DomainFlowUtils.ExpiredClaimException;
import google.registry.flows.domain.DomainFlowUtils.FeesMismatchException; import google.registry.flows.domain.DomainFlowUtils.FeesMismatchException;
import google.registry.flows.domain.DomainFlowUtils.FeesRequiredForPremiumNameException; import google.registry.flows.domain.DomainFlowUtils.FeesRequiredForPremiumNameException;
import google.registry.flows.domain.DomainFlowUtils.InvalidIdnDomainLabelException; import google.registry.flows.domain.DomainFlowUtils.InvalidIdnDomainLabelException;
import google.registry.flows.domain.DomainFlowUtils.InvalidLrpTokenException;
import google.registry.flows.domain.DomainFlowUtils.InvalidPunycodeException; import google.registry.flows.domain.DomainFlowUtils.InvalidPunycodeException;
import google.registry.flows.domain.DomainFlowUtils.InvalidTcnIdChecksumException; import google.registry.flows.domain.DomainFlowUtils.InvalidTcnIdChecksumException;
import google.registry.flows.domain.DomainFlowUtils.InvalidTrademarkValidatorException; import google.registry.flows.domain.DomainFlowUtils.InvalidTrademarkValidatorException;
@ -112,7 +110,6 @@ import google.registry.flows.domain.DomainFlowUtils.UnsupportedFeeAttributeExcep
import google.registry.flows.domain.DomainFlowUtils.UnsupportedMarkTypeException; import google.registry.flows.domain.DomainFlowUtils.UnsupportedMarkTypeException;
import google.registry.flows.exceptions.ResourceAlreadyExistsException; import google.registry.flows.exceptions.ResourceAlreadyExistsException;
import google.registry.model.domain.DomainApplication; import google.registry.model.domain.DomainApplication;
import google.registry.model.domain.LrpTokenEntity;
import google.registry.model.domain.launch.ApplicationStatus; import google.registry.model.domain.launch.ApplicationStatus;
import google.registry.model.domain.launch.LaunchNotice; import google.registry.model.domain.launch.LaunchNotice;
import google.registry.model.domain.launch.LaunchPhase; import google.registry.model.domain.launch.LaunchPhase;
@ -130,7 +127,6 @@ import java.util.List;
import org.joda.money.CurrencyUnit; import org.joda.money.CurrencyUnit;
import org.joda.money.Money; import org.joda.money.Money;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.joda.time.Interval;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -930,181 +926,6 @@ public class DomainApplicationCreateFlowTest
doSuccessfulTest("domain_create_landrush_response.xml", false, 2); doSuccessfulTest("domain_create_landrush_response.xml", false, 2);
} }
@Test
public void testSuccess_landrushLrpApplication() throws Exception {
createTld("tld", TldState.LANDRUSH);
persistResource(
Registry.get("tld")
.asBuilder()
.setLrpPeriod(new Interval(clock.nowUtc().minusDays(1), clock.nowUtc().plusDays(1)))
.build());
LrpTokenEntity token =
persistResource(
new LrpTokenEntity.Builder()
.setToken("lrptokentest")
.setAssignee("test-validate.tld")
.setValidTlds(ImmutableSet.of("tld"))
.build());
setEppInput("domain_create_landrush_lrp.xml");
persistContactsAndHosts();
clock.advanceOneMilli();
doSuccessfulTest("domain_create_landrush_response.xml", false);
assertThat(ofy().load().entity(token).now().getRedemptionHistoryEntry()).isNotNull();
}
@Test
public void testSuccess_landrushLrpApplication_superuser() throws Exception {
// Using an LRP token as superuser should still mark the token as redeemed (i.e. same effect
// as non-superuser).
createTld("tld", TldState.LANDRUSH);
persistResource(
Registry.get("tld")
.asBuilder()
.setLrpPeriod(new Interval(clock.nowUtc().minusDays(1), clock.nowUtc().plusDays(1)))
.build());
LrpTokenEntity token =
persistResource(
new LrpTokenEntity.Builder()
.setToken("lrptokentest")
.setAssignee("test-validate.tld")
.setValidTlds(ImmutableSet.of("tld"))
.build());
setEppInput("domain_create_landrush_lrp.xml");
persistContactsAndHosts();
clock.advanceOneMilli();
runSuperuserFlow("domain_create_landrush_response.xml");
assertThat(ofy().load().entity(token).now().getRedemptionHistoryEntry()).isNotNull();
}
@Test
public void testFailure_landrushLrpApplication_badToken() {
createTld("tld", TldState.LANDRUSH);
persistResource(
Registry.get("tld")
.asBuilder()
.setLrpPeriod(new Interval(clock.nowUtc().minusDays(1), clock.nowUtc().plusDays(1)))
.build());
persistResource(
new LrpTokenEntity.Builder()
.setToken("lrptokentest2")
.setAssignee("test-validate.tld")
.setValidTlds(ImmutableSet.of("tld"))
.build());
setEppInput("domain_create_landrush_lrp.xml");
persistContactsAndHosts();
clock.advanceOneMilli();
EppException thrown = assertThrows(InvalidLrpTokenException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
public void testFailure_landrushLrpApplication_tokenForWrongTld() {
createTld("tld", TldState.LANDRUSH);
persistResource(
Registry.get("tld")
.asBuilder()
.setLrpPeriod(new Interval(clock.nowUtc().minusDays(1), clock.nowUtc().plusDays(1)))
.build());
persistResource(
new LrpTokenEntity.Builder()
.setToken("lrptokentest")
// The below assignee doesn't really make sense here, but as of right now the validation
// in DomainPricingLogic is just a match on the domain name, so this test ensures that
// the registration fails due to invalid TLDs even if everything else otherwise matches.
.setAssignee("test-validate.tld")
.setValidTlds(ImmutableSet.of("other"))
.build());
setEppInput("domain_create_landrush_lrp.xml");
persistContactsAndHosts();
clock.advanceOneMilli();
EppException thrown = assertThrows(InvalidLrpTokenException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
public void testFailure_landrushLrpApplication_usedToken() {
createTld("tld", TldState.LANDRUSH);
persistResource(
Registry.get("tld")
.asBuilder()
.setLrpPeriod(new Interval(clock.nowUtc().minusDays(1), clock.nowUtc().plusDays(1)))
.build());
persistResource(
new LrpTokenEntity.Builder()
.setToken("lrptokentest")
.setAssignee("test-validate.tld")
.setValidTlds(ImmutableSet.of("tld"))
.setRedemptionHistoryEntry(
Key.create(HistoryEntry.class, "1")) // as long as it's not null
.build());
setEppInput("domain_create_landrush_lrp.xml");
persistContactsAndHosts();
clock.advanceOneMilli();
EppException thrown = assertThrows(InvalidLrpTokenException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
public void testSuccess_landrushApplicationWithLrpToken_notInLrp() throws Exception {
createTld("tld", TldState.LANDRUSH);
LrpTokenEntity token =
persistResource(
new LrpTokenEntity.Builder()
.setToken("lrptokentest")
.setAssignee("test-validate.tld")
.setValidTlds(ImmutableSet.of("tld"))
.build());
setEppInput("domain_create_landrush_lrp.xml");
persistContactsAndHosts();
clock.advanceOneMilli();
// Application should continue as normal, since the LRP token will just be ignored
doSuccessfulTest("domain_create_landrush_response.xml", false);
// Token should not be marked as used, since this isn't an LRP state
assertThat(ofy().load().entity(token).now().getRedemptionHistoryEntry()).isNull();
}
@Test
public void testSuccess_landrushApplicationWithLrpToken_noLongerLrp() throws Exception {
createTld("tld");
persistResource(
Registry.get("tld")
.asBuilder()
.setLrpPeriod(new Interval(clock.nowUtc().minusDays(2), clock.nowUtc().minusDays(1)))
.setTldStateTransitions(
ImmutableSortedMap.of(
START_OF_TIME, TldState.SUNRISE, clock.nowUtc(), TldState.LANDRUSH))
.build());
LrpTokenEntity token =
persistResource(
new LrpTokenEntity.Builder()
.setToken("lrptokentest")
.setAssignee("test-validate.tld")
.setValidTlds(ImmutableSet.of("tld"))
.build());
setEppInput("domain_create_landrush_lrp.xml");
persistContactsAndHosts();
clock.advanceOneMilli();
// Application should continue as normal, since the LRP token will just be ignored
doSuccessfulTest("domain_create_landrush_response.xml", false);
// Token should not be marked as used, since this isn't an LRP state
assertThat(ofy().load().entity(token).now().getRedemptionHistoryEntry()).isNull();
}
@Test
public void testFailure_landrush_duringLrpWithMissingToken() {
createTld("tld", TldState.LANDRUSH);
persistResource(
Registry.get("tld")
.asBuilder()
.setLrpPeriod(new Interval(clock.nowUtc().minusDays(1), clock.nowUtc().plusDays(1)))
.build());
setEppInput("domain_create_landrush.xml");
persistContactsAndHosts();
clock.advanceOneMilli();
EppException thrown = assertThrows(InvalidLrpTokenException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test @Test
public void testFailure_landrushWithPeriodInMonths() { public void testFailure_landrushWithPeriodInMonths() {
createTld("tld", TldState.LANDRUSH); createTld("tld", TldState.LANDRUSH);

View file

@ -101,7 +101,6 @@ import google.registry.flows.domain.DomainFlowUtils.FeesMismatchException;
import google.registry.flows.domain.DomainFlowUtils.FeesRequiredDuringEarlyAccessProgramException; import google.registry.flows.domain.DomainFlowUtils.FeesRequiredDuringEarlyAccessProgramException;
import google.registry.flows.domain.DomainFlowUtils.FeesRequiredForPremiumNameException; import google.registry.flows.domain.DomainFlowUtils.FeesRequiredForPremiumNameException;
import google.registry.flows.domain.DomainFlowUtils.InvalidIdnDomainLabelException; import google.registry.flows.domain.DomainFlowUtils.InvalidIdnDomainLabelException;
import google.registry.flows.domain.DomainFlowUtils.InvalidLrpTokenException;
import google.registry.flows.domain.DomainFlowUtils.InvalidPunycodeException; import google.registry.flows.domain.DomainFlowUtils.InvalidPunycodeException;
import google.registry.flows.domain.DomainFlowUtils.InvalidTcnIdChecksumException; import google.registry.flows.domain.DomainFlowUtils.InvalidTcnIdChecksumException;
import google.registry.flows.domain.DomainFlowUtils.InvalidTrademarkValidatorException; import google.registry.flows.domain.DomainFlowUtils.InvalidTrademarkValidatorException;
@ -139,7 +138,6 @@ import google.registry.model.billing.BillingEvent.Flag;
import google.registry.model.billing.BillingEvent.Reason; import google.registry.model.billing.BillingEvent.Reason;
import google.registry.model.domain.DomainResource; import google.registry.model.domain.DomainResource;
import google.registry.model.domain.GracePeriod; import google.registry.model.domain.GracePeriod;
import google.registry.model.domain.LrpTokenEntity;
import google.registry.model.domain.launch.ApplicationStatus; import google.registry.model.domain.launch.ApplicationStatus;
import google.registry.model.domain.launch.LaunchNotice; import google.registry.model.domain.launch.LaunchNotice;
import google.registry.model.domain.rgp.GracePeriodStatus; import google.registry.model.domain.rgp.GracePeriodStatus;
@ -163,7 +161,6 @@ import org.joda.money.CurrencyUnit;
import org.joda.money.Money; import org.joda.money.Money;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.joda.time.Duration; import org.joda.time.Duration;
import org.joda.time.Interval;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -485,66 +482,6 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
assertNoLordn(); assertNoLordn();
} }
@Test
public void testSuccess_lrp() throws Exception {
persistResource(
Registry.get("tld")
.asBuilder()
.setLrpPeriod(new Interval(clock.nowUtc().minusDays(1), clock.nowUtc().plusDays(1)))
.build());
LrpTokenEntity token =
persistResource(
new LrpTokenEntity.Builder()
.setToken("lrptokentest")
.setAssignee("example.tld")
.setValidTlds(ImmutableSet.of("tld"))
.build());
setEppInput("domain_create_lrp.xml");
persistContactsAndHosts();
runFlowAssertResponse(
loadFile("domain_create_response.xml", ImmutableMap.of("DOMAIN", "example.tld")));
assertSuccessfulCreate("tld", ImmutableSet.of());
assertNoLordn();
assertThat(ofy().load().entity(token).now().getRedemptionHistoryEntry()).isNotNull();
}
@Test
public void testSuccess_withLrpToken_outsideOfLrp() throws Exception {
// If a valid LRP token is passed in even though the TLD is not currently in an LRP phase,
// just ignore the token and proceed with normal GA registration (i.e. LRP token should
// remain unredeemed).
persistResource(
Registry.get("tld")
.asBuilder()
.setLrpPeriod(new Interval(clock.nowUtc().minusDays(2), clock.nowUtc().minusDays(1)))
.build());
LrpTokenEntity token =
persistResource(
new LrpTokenEntity.Builder()
.setToken("lrptokentest")
.setAssignee("example.tld")
.setValidTlds(ImmutableSet.of("tld"))
.build());
setEppInput("domain_create_lrp.xml");
persistContactsAndHosts();
runFlowAssertResponse(
loadFile("domain_create_response.xml", ImmutableMap.of("DOMAIN", "example.tld")));
assertSuccessfulCreate("tld", ImmutableSet.of());
assertNoLordn();
assertThat(ofy().load().entity(token).now().getRedemptionHistoryEntry()).isNull();
}
@Test
public void testSuccess_outsideOfLrp() throws Exception {
persistResource(
Registry.get("tld")
.asBuilder()
.setLrpPeriod(new Interval(clock.nowUtc().minusDays(2), clock.nowUtc().minusDays(1)))
.build());
persistContactsAndHosts();
doSuccessfulTest();
}
@Test @Test
public void testFailure_generalAvailability_withEncodedSignedMark() { public void testFailure_generalAvailability_withEncodedSignedMark() {
createTld("tld", GENERAL_AVAILABILITY); createTld("tld", GENERAL_AVAILABILITY);
@ -715,39 +652,6 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test
public void testFailure_lrp_badToken() {
persistResource(
Registry.get("tld")
.asBuilder()
.setLrpPeriod(new Interval(clock.nowUtc().minusDays(1), clock.nowUtc().plusDays(1)))
.build());
LrpTokenEntity token =
persistResource(
new LrpTokenEntity.Builder()
.setToken("otherlrptoken")
.setAssignee("example.tld")
.setValidTlds(ImmutableSet.of("tld"))
.build());
setEppInput("domain_create_lrp.xml");
persistContactsAndHosts();
Exception e = assertThrows(InvalidLrpTokenException.class, this::runFlow);
assertThat(e).hasMessageThat().isEqualTo("Invalid limited registration period token");
assertThat(ofy().load().entity(token).now().getRedemptionHistoryEntry()).isNull();
}
@Test
public void testFailure_lrp_noToken() {
persistResource(
Registry.get("tld")
.asBuilder()
.setLrpPeriod(new Interval(clock.nowUtc().minusDays(1), clock.nowUtc().plusDays(1)))
.build());
persistContactsAndHosts();
InvalidLrpTokenException thrown = assertThrows(InvalidLrpTokenException.class, this::runFlow);
assertThat(thrown).hasMessageThat().contains("Invalid limited registration period token");
}
@Test @Test
public void testSuccess_premium() throws Exception { public void testSuccess_premium() throws Exception {
createTld("example"); createTld("example");
@ -1084,31 +988,6 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test
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.
createTld("tld", TldState.LANDRUSH);
persistResource(
Registry.get("tld")
.asBuilder()
.setReservedLists(
persistReservedList("tld-reserved", "anchor,RESERVED_FOR_ANCHOR_TENANT"))
.build());
LrpTokenEntity token =
persistResource(
new LrpTokenEntity.Builder().setToken("2fooBAR").setAssignee("anchor.tld").build());
setEppInput("domain_create_anchor_authcode.xml");
persistContactsAndHosts();
runFlowAssertResponse(
CommitMode.LIVE, SUPERUSER, loadFile("domain_create_anchor_response.xml"));
assertSuccessfulCreate("tld", ImmutableSet.of(ANCHOR_TENANT));
// Token should not be marked as used, since interpreting the authcode as anchor tenant should
// take precedence.
assertThat(ofy().load().entity(token).now().getRedemptionHistoryEntry()).isNull();
}
@Test @Test
public void testSuccess_anchorTenant_viaAuthCode() throws Exception { public void testSuccess_anchorTenant_viaAuthCode() throws Exception {
setEppInput("domain_create_anchor_authcode.xml"); setEppInput("domain_create_anchor_authcode.xml");
@ -1132,36 +1011,6 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
.isEqualTo(Key.create(getHistoryEntries(reloadResourceByForeignKey()).get(0))); .isEqualTo(Key.create(getHistoryEntries(reloadResourceByForeignKey()).get(0)));
} }
@Test
public void testSuccess_anchorTenant_viaAuthCode_duringLrp() throws Exception {
persistResource(
Registry.get("tld")
.asBuilder()
.setLrpPeriod(new Interval(clock.nowUtc().minusDays(1), clock.nowUtc().plusDays(1)))
.build());
setEppInput("domain_create_anchor_authcode.xml");
persistContactsAndHosts();
runFlowAssertResponse(loadFile("domain_create_anchor_response.xml"));
assertSuccessfulCreate("tld", ImmutableSet.of(ANCHOR_TENANT));
assertNoLordn();
}
@Test
public void testSuccess_anchorTenant_viaExtension_duringLrp() throws Exception {
persistResource(
Registry.get("tld")
.asBuilder()
.setLrpPeriod(new Interval(clock.nowUtc().minusDays(1), clock.nowUtc().plusDays(1)))
.build());
eppRequestSource = EppRequestSource.TOOL;
setEppInput("domain_create_anchor_tenant.xml");
persistContactsAndHosts();
runFlowAssertResponse(
loadFile("domain_create_response.xml", ImmutableMap.of("DOMAIN", "example.tld")));
assertSuccessfulCreate("tld", ImmutableSet.of(ANCHOR_TENANT));
assertNoLordn();
}
@Test @Test
public void testSuccess_anchorTenant_viaAuthCode_withClaims() throws Exception { public void testSuccess_anchorTenant_viaAuthCode_withClaims() throws Exception {
persistResource( persistResource(

View file

@ -1,28 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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>test-validate.tld</domain:name>
<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>lrptokentest</domain:pw>
</domain:authInfo>
</domain:create>
</create>
<extension>
<launch:create
xmlns:launch="urn:ietf:params:xml:ns:launch-1.0">
<launch:phase>landrush</launch:phase>
</launch:create>
</extension>
<clTRID>ABC-12345</clTRID>
</command>
</epp>

View file

@ -1,22 +0,0 @@
<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>example.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>lrptokentest</domain:pw>
</domain:authInfo>
</domain:create>
</create>
<clTRID>ABC-12345</clTRID>
</command>
</epp>

View file

@ -1,89 +0,0 @@
// Copyright 2017 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.model.domain;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.testing.DatastoreHelper.createTld;
import static google.registry.testing.DatastoreHelper.persistActiveDomainApplication;
import static google.registry.testing.DatastoreHelper.persistResource;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
import google.registry.model.EntityTestCase;
import google.registry.model.reporting.HistoryEntry;
import org.junit.Before;
import org.junit.Test;
/** Unit tests for {@link LrpTokenEntity}. */
public class LrpTokenEntityTest extends EntityTestCase {
LrpTokenEntity unredeemedToken;
LrpTokenEntity redeemedToken;
@Before
public void setUp() {
createTld("tld");
DomainApplication lrpApplication = persistActiveDomainApplication("domain.tld");
HistoryEntry applicationCreateHistoryEntry = persistResource(new HistoryEntry.Builder()
.setParent(lrpApplication)
.setType(HistoryEntry.Type.DOMAIN_APPLICATION_CREATE)
.build());
unredeemedToken = persistResource(
new LrpTokenEntity.Builder()
.setAssignee("1:1020304")
.setToken("a0b1c2d3e4f5g6")
.setValidTlds(ImmutableSet.of("tld"))
.setMetadata(ImmutableMap.of("foo", "bar"))
.build());
redeemedToken = persistResource(
new LrpTokenEntity.Builder()
.setAssignee("2:org.testdomain")
.setToken("h0i1j2k3l4m")
.setRedemptionHistoryEntry(Key.create(applicationCreateHistoryEntry))
.setValidTlds(ImmutableSet.of("tld"))
.setMetadata(ImmutableMap.of("bar", "foo"))
.build());
}
@Test
public void testPersistence() {
assertThat(ofy().load().entity(redeemedToken).now()).isEqualTo(redeemedToken);
}
@Test
public void testSuccess_loadByToken() {
assertThat(ofy().load().key(Key.create(LrpTokenEntity.class, "a0b1c2d3e4f5g6")).now())
.isEqualTo(unredeemedToken);
}
@Test
public void testSuccess_loadByAssignee() {
assertThat(
ofy().load().type(LrpTokenEntity.class).filter("assignee", "1:1020304").first().now())
.isEqualTo(unredeemedToken);
}
@Test
public void testSuccess_isRedeemed() {
assertThat(redeemedToken.isRedeemed()).isTrue();
assertThat(unredeemedToken.isRedeemed()).isFalse();
}
@Test
public void testIndexing() throws Exception {
verifyIndexing(redeemedToken, "assignee", "token");
}
}

View file

@ -243,14 +243,6 @@ class google.registry.model.domain.GracePeriod {
java.lang.String clientId; java.lang.String clientId;
org.joda.time.DateTime expirationTime; org.joda.time.DateTime expirationTime;
} }
class google.registry.model.domain.LrpTokenEntity {
@Id java.lang.String token;
com.googlecode.objectify.Key<google.registry.model.reporting.HistoryEntry> redemptionHistoryEntry;
google.registry.model.UpdateAutoTimestamp updateTimestamp;
java.lang.String assignee;
java.util.Map<java.lang.String, java.lang.String> metadata;
java.util.Set<java.lang.String> validTlds;
}
class google.registry.model.domain.Period { class google.registry.model.domain.Period {
google.registry.model.domain.Period$Unit unit; google.registry.model.domain.Period$Unit unit;
java.lang.Integer value; java.lang.Integer value;
@ -663,8 +655,6 @@ class google.registry.model.registry.Registry {
org.joda.money.Money restoreBillingCost; org.joda.money.Money restoreBillingCost;
org.joda.money.Money serverStatusChangeBillingCost; org.joda.money.Money serverStatusChangeBillingCost;
org.joda.time.DateTime claimsPeriodEnd; org.joda.time.DateTime claimsPeriodEnd;
org.joda.time.DateTime lrpPeriodEnd;
org.joda.time.DateTime lrpPeriodStart;
org.joda.time.Duration addGracePeriodLength; org.joda.time.Duration addGracePeriodLength;
org.joda.time.Duration anchorTenantAddGracePeriodLength; org.joda.time.Duration anchorTenantAddGracePeriodLength;
org.joda.time.Duration autoRenewGracePeriodLength; org.joda.time.Duration autoRenewGracePeriodLength;

View file

@ -1,335 +0,0 @@
// Copyright 2017 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.tools;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.testing.DatastoreHelper.createTld;
import static google.registry.testing.DatastoreHelper.persistResource;
import static google.registry.testing.JUnitBackports.assertThrows;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.spy;
import com.google.appengine.tools.remoteapi.RemoteApiException;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.Files;
import com.googlecode.objectify.Key;
import google.registry.model.domain.LrpTokenEntity;
import google.registry.model.reporting.HistoryEntry;
import google.registry.testing.DeterministicStringGenerator;
import google.registry.testing.DeterministicStringGenerator.Rule;
import google.registry.testing.FakeClock;
import google.registry.testing.FakeSleeper;
import google.registry.util.Retrier;
import java.io.File;
import java.io.IOException;
import java.util.Set;
import javax.annotation.Nullable;
import org.joda.time.DateTime;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
/** Unit tests for {@link CreateLrpTokensCommand}. */
public class CreateLrpTokensCommandTest extends CommandTestCase<CreateLrpTokensCommand> {
DeterministicStringGenerator stringGenerator =
new DeterministicStringGenerator("abcdefghijklmnopqrstuvwxyz");
File assigneeFile;
String assigneeFilePath;
@Before
public void init() throws IOException {
assigneeFile = tmpDir.newFile("lrp_assignees.txt");
assigneeFilePath = assigneeFile.getPath();
command.stringGenerator = stringGenerator;
command.retrier =
new Retrier(new FakeSleeper(new FakeClock(DateTime.parse("2000-01-01TZ"))), 3);
createTld("tld");
}
@Test
public void testSuccess_oneAssignee() throws Exception {
runCommand("--assignee=domain.tld", "--tlds=tld");
assertLrpTokens(
createToken("LRP_abcdefghijklmnop", "domain.tld", ImmutableSet.of("tld"), null, null));
assertInStdout("domain.tld,LRP_abcdefghijklmnop");
}
@Test
public void testSuccess_oneAssignee_retry() throws Exception {
CreateLrpTokensCommand spyCommand = spy(command);
RemoteApiException fakeException = new RemoteApiException("foo", "foo", "foo", new Exception());
doThrow(fakeException)
.doThrow(fakeException)
.doCallRealMethod()
.when(spyCommand)
.saveTokens(Mockito.any());
runCommand("--assignee=domain.tld", "--tlds=tld");
assertLrpTokens(
createToken("LRP_abcdefghijklmnop", "domain.tld", ImmutableSet.of("tld"), null, null));
assertInStdout("domain.tld,LRP_abcdefghijklmnop");
}
@Test
public void testSuccess_oneAssignee_withMetadata() throws Exception {
runCommand("--assignee=domain.tld", "--tlds=tld", "--metadata=key=foo,key2=bar");
assertLrpTokens(
createToken(
"LRP_abcdefghijklmnop",
"domain.tld",
ImmutableSet.of("tld"),
null,
ImmutableMap.of("key", "foo", "key2", "bar")));
assertInStdout("domain.tld,LRP_abcdefghijklmnop");
}
@Test
public void testSuccess_oneAssignee_tokenCollision() throws Exception {
LrpTokenEntity existingToken = persistResource(new LrpTokenEntity.Builder()
.setToken("LRP_abcdefghijklmnop")
.setAssignee("otherdomain.tld")
.setValidTlds(ImmutableSet.of("tld"))
.build());
runCommand("--assignee=domain.tld", "--tlds=tld");
assertLrpTokens(
existingToken,
createToken("LRP_qrstuvwxyzabcdef", "domain.tld", ImmutableSet.of("tld"), null, null));
assertInStdout("domain.tld,LRP_qrstuvwxyzabcdef");
}
@Test
public void testSuccess_oneAssignee_byFile() throws Exception {
Files.asCharSink(assigneeFile, UTF_8).write("domain.tld");
runCommand("--input=" + assigneeFilePath, "--tlds=tld");
assertLrpTokens(
createToken("LRP_abcdefghijklmnop", "domain.tld", ImmutableSet.of("tld"), null, null));
assertInStdout("domain.tld,LRP_abcdefghijklmnop");
}
@Test
public void testSuccess_oneAssignee_byFile_withMetadata() throws Exception {
Files.asCharSink(assigneeFile, UTF_8).write("domain.tld,foo,bar");
runCommand("--input=" + assigneeFilePath, "--tlds=tld", "--metadata_columns=key=1,key2=2");
assertLrpTokens(
createToken(
"LRP_abcdefghijklmnop",
"domain.tld",
ImmutableSet.of("tld"),
null,
ImmutableMap.of("key", "foo", "key2", "bar")));
assertInStdout("domain.tld,LRP_abcdefghijklmnop");
}
@Test
public void testSuccess_oneAssignee_byFile_withMetadata_quotedString() throws Exception {
Files.asCharSink(assigneeFile, UTF_8).write("domain.tld,\"foo,foo\",bar");
runCommand("--input=" + assigneeFilePath, "--tlds=tld", "--metadata_columns=key=1,key2=2");
assertLrpTokens(
createToken(
"LRP_abcdefghijklmnop",
"domain.tld",
ImmutableSet.of("tld"),
null,
ImmutableMap.of("key", "foo,foo", "key2", "bar")));
assertInStdout("domain.tld,LRP_abcdefghijklmnop");
}
@Test
public void testSuccess_oneAssignee_byFile_withMetadata_twoQuotedStrings() throws Exception {
Files.asCharSink(assigneeFile, UTF_8).write("domain.tld,\"foo,foo\",\"bar,bar\"");
runCommand("--input=" + assigneeFilePath, "--tlds=tld", "--metadata_columns=key=1,key2=2");
assertLrpTokens(
createToken(
"LRP_abcdefghijklmnop",
"domain.tld",
ImmutableSet.of("tld"),
null,
ImmutableMap.of("key", "foo,foo", "key2", "bar,bar")));
assertInStdout("domain.tld,LRP_abcdefghijklmnop");
}
@Test
public void testSuccess_emptyFile() throws Exception {
Files.asCharSink(assigneeFile, UTF_8).write("");
runCommand("--input=" + assigneeFilePath, "--tlds=tld");
assertLrpTokens(); // no tokens exist
assertThat(getStdoutAsString()).isEmpty();
}
@Test
public void testSuccess_multipleAssignees_byFile() throws Exception {
Files.asCharSink(assigneeFile, UTF_8).write("domain1.tld\ndomain2.tld\ndomain3.tld");
runCommand("--input=" + assigneeFilePath, "--tlds=tld");
assertLrpTokens(
createToken("LRP_abcdefghijklmnop", "domain1.tld", ImmutableSet.of("tld"), null, null),
createToken("LRP_qrstuvwxyzabcdef", "domain2.tld", ImmutableSet.of("tld"), null, null),
createToken("LRP_ghijklmnopqrstuv", "domain3.tld", ImmutableSet.of("tld"), null, null));
assertInStdout("domain1.tld,LRP_abcdefghijklmnop");
assertInStdout("domain2.tld,LRP_qrstuvwxyzabcdef");
assertInStdout("domain3.tld,LRP_ghijklmnopqrstuv");
}
@Test
public void testSuccess_multipleAssignees_byFile_ignoreBlankLine() throws Exception {
Files.asCharSink(assigneeFile, UTF_8).write("domain1.tld\n\ndomain2.tld");
runCommand("--input=" + assigneeFilePath, "--tlds=tld");
assertLrpTokens(
createToken("LRP_abcdefghijklmnop", "domain1.tld", ImmutableSet.of("tld"), null, null),
// Second deterministic token (LRP_qrstuvwxyzabcdef) still consumed but not assigned
createToken("LRP_ghijklmnopqrstuv", "domain2.tld", ImmutableSet.of("tld"), null, null));
assertInStdout("domain1.tld,LRP_abcdefghijklmnop");
assertInStdout("domain2.tld,LRP_ghijklmnopqrstuv");
}
@Test
public void testSuccess_largeFile_withMetadata() throws Exception {
int numberOfTokens = 67;
LrpTokenEntity[] expectedTokens = new LrpTokenEntity[numberOfTokens];
// Prepend a counter to avoid collisions, 16-char alphabet will always generate the same string.
stringGenerator =
new DeterministicStringGenerator("abcdefghijklmnop", Rule.PREPEND_COUNTER);
command.stringGenerator = stringGenerator;
StringBuilder assigneeFileBuilder = new StringBuilder();
for (int i = 0; i < numberOfTokens; i++) {
assigneeFileBuilder.append(String.format("domain%d.tld,%d,%d\n", i, i * 2, i * 3));
expectedTokens[i] =
createToken(
String.format("LRP_%04d_abcdefghijklmnop", i),
String.format("domain%d.tld", i),
ImmutableSet.of("tld"),
null,
ImmutableMap.of("key", Integer.toString(i * 2), "key2", Integer.toString(i * 3)));
}
Files.asCharSink(assigneeFile, UTF_8).write(assigneeFileBuilder);
runCommand("--input=" + assigneeFilePath, "--tlds=tld", "--metadata_columns=key=1,key2=2");
assertLrpTokens(expectedTokens);
for (int i = 0; i < numberOfTokens; i++) {
assertInStdout(String.format("domain%d.tld,LRP_%04d_abcdefghijklmnop", i, i));
}
}
@Test
public void testFailure_missingAssigneeOrFile() {
IllegalArgumentException thrown =
assertThrows(IllegalArgumentException.class, () -> runCommand("--tlds=tld"));
assertThat(thrown)
.hasMessageThat()
.contains("Exactly one of either assignee or filename must be specified.");
}
@Test
public void testFailure_bothAssigneeAndFile() {
IllegalArgumentException thrown =
assertThrows(
IllegalArgumentException.class,
() -> runCommand("--assignee=domain.tld", "--tlds=tld", "--input=" + assigneeFilePath));
assertThat(thrown)
.hasMessageThat()
.contains("Exactly one of either assignee or filename must be specified.");
}
@Test
public void testFailure_bothMetadataAndFile() {
IllegalArgumentException thrown =
assertThrows(
IllegalArgumentException.class,
() -> runCommand("--tlds=tld", "--input=" + assigneeFilePath, "--metadata=key=foo"));
assertThat(thrown)
.hasMessageThat()
.contains("Metadata cannot be specified along with a filename.");
}
@Test
public void testFailure_bothAssigneeAndMetadataColumns() {
IllegalArgumentException thrown =
assertThrows(
IllegalArgumentException.class,
() -> runCommand("--assignee=domain.tld", "--tlds=tld", "--metadata_columns=foo=1"));
assertThat(thrown)
.hasMessageThat()
.contains("Metadata columns cannot be specified along with an assignee.");
}
@Test
public void testFailure_badTld() {
IllegalArgumentException thrown =
assertThrows(
IllegalArgumentException.class,
() -> runCommand("--assignee=domain.tld", "--tlds=foo"));
assertThat(thrown).hasMessageThat().contains("TLDs do not exist: foo");
}
@Test
public void testFailure_oneAssignee_byFile_insufficientMetadata() throws Exception {
Files.asCharSink(assigneeFile, UTF_8).write("domain.tld,foo");
IllegalArgumentException thrown =
assertThrows(
IllegalArgumentException.class,
() ->
runCommand(
"--input=" + assigneeFilePath,
"--tlds=tld",
"--metadata_columns=key=1,key2=2"));
assertThat(thrown)
.hasMessageThat()
.contains("Entry for domain.tld does not have a value for key2 (index 2)");
}
private void assertLrpTokens(LrpTokenEntity... expected) {
// Using ImmutableObject comparison here is tricky because updateTimestamp is not set on the
// expected LrpToken objects and will cause the assert to fail.
Iterable<LrpTokenEntity> actual = ofy().load().type(LrpTokenEntity.class);
ImmutableMap.Builder<String, LrpTokenEntity> actualTokenMapBuilder =
new ImmutableMap.Builder<>();
for (LrpTokenEntity token : actual) {
actualTokenMapBuilder.put(token.getToken(), token);
}
ImmutableMap<String, LrpTokenEntity> actualTokenMap = actualTokenMapBuilder.build();
assertThat(actualTokenMap).hasSize(expected.length);
for (LrpTokenEntity expectedToken : expected) {
LrpTokenEntity match = actualTokenMap.get(expectedToken.getToken());
assertThat(match).isNotNull();
assertThat(match.getAssignee()).isEqualTo(expectedToken.getAssignee());
assertThat(match.getValidTlds()).containsExactlyElementsIn(expectedToken.getValidTlds());
assertThat(match.getRedemptionHistoryEntry())
.isEqualTo(expectedToken.getRedemptionHistoryEntry());
assertThat(match.getMetadata()).containsExactlyEntriesIn(expectedToken.getMetadata());
}
}
private LrpTokenEntity createToken(
String token,
String assignee,
Set<String> validTlds,
@Nullable Key<HistoryEntry> redemptionHistoryEntry,
@Nullable ImmutableMap<String, String> metadata) {
LrpTokenEntity.Builder tokenBuilder = new LrpTokenEntity.Builder()
.setAssignee(assignee)
.setValidTlds(validTlds)
.setToken(token);
if (redemptionHistoryEntry != null) {
tokenBuilder.setRedemptionHistoryEntry(redemptionHistoryEntry);
}
if (metadata != null) {
tokenBuilder.setMetadata(metadata);
}
return tokenBuilder.build();
}
}

View file

@ -39,7 +39,6 @@ import java.math.BigDecimal;
import org.joda.money.Money; import org.joda.money.Money;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.joda.time.Duration; import org.joda.time.Duration;
import org.joda.time.Interval;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -287,18 +286,6 @@ public class CreateTldCommandTest extends CommandTestCase<CreateTldCommand> {
.containsExactly("xn--q9jyb4c_abuse", "common_abuse"); .containsExactly("xn--q9jyb4c_abuse", "common_abuse");
} }
@Test
public void testSuccess_addLrpPeriod() throws Exception {
runCommandForced(
"--lrp_period=2004-06-09T12:30:00Z/2004-07-10T13:30:00Z",
"--roid_suffix=Q9JYB4C",
"--dns_writers=VoidDnsWriter",
"xn--q9jyb4c");
assertThat(Registry.get("xn--q9jyb4c").getLrpPeriod()).isEqualTo(
new Interval(
DateTime.parse("2004-06-09T12:30:00Z"), DateTime.parse("2004-07-10T13:30:00Z")));
}
@Test @Test
public void testSuccess_setPremiumPriceAckRequired() throws Exception { public void testSuccess_setPremiumPriceAckRequired() throws Exception {
runCommandForced( runCommandForced(
@ -611,37 +598,6 @@ public class CreateTldCommandTest extends CommandTestCase<CreateTldCommand> {
assertThat(thrown).hasMessageThat().contains("The premium list 'phonies' doesn't exist"); assertThat(thrown).hasMessageThat().contains("The premium list 'phonies' doesn't exist");
} }
@Test
public void testFailure_addLrpPeriod_backwardsInterval() {
ParameterException thrown =
assertThrows(
ParameterException.class,
() ->
runCommandForced(
"--lrp_period=2005-06-09T12:30:00Z/2004-07-10T13:30:00Z",
"--roid_suffix=Q9JYB4C",
"--dns_writers=VoidDnsWriter",
"xn--q9jyb4c"));
assertThat(thrown)
.hasMessageThat()
.contains(
"--lrp_period=2005-06-09T12:30:00Z/2004-07-10T13:30:00Z not an ISO-8601 interval");
}
@Test
public void testFailure_addLrpPeriod_badInterval() {
ParameterException thrown =
assertThrows(
ParameterException.class,
() ->
runCommandForced(
"--lrp_period=foobar",
"--roid_suffix=Q9JYB4C",
"--dns_writers=VoidDnsWriter",
"xn--q9jyb4c"));
assertThat(thrown).hasMessageThat().contains("--lrp_period=foobar not an ISO-8601 interval");
}
@Test @Test
public void testFailure_specifiedDnsWriters_dontExist() { public void testFailure_specifiedDnsWriters_dontExist() {
IllegalArgumentException thrown = IllegalArgumentException thrown =

View file

@ -1,90 +0,0 @@
// Copyright 2017 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.tools;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.testing.DatastoreHelper.createTld;
import static google.registry.testing.DatastoreHelper.persistActiveDomainApplication;
import static google.registry.testing.DatastoreHelper.persistResource;
import static google.registry.testing.JUnitBackports.assertThrows;
import com.googlecode.objectify.Key;
import google.registry.model.domain.DomainApplication;
import google.registry.model.domain.LrpTokenEntity;
import google.registry.model.reporting.HistoryEntry;
import org.junit.Before;
import org.junit.Test;
/** Unit tests for {@link GetLrpTokenCommand}. */
public class GetLrpTokenCommandTest extends CommandTestCase<GetLrpTokenCommand> {
@Before
public void before() {
createTld("tld");
DomainApplication lrpApplication = persistActiveDomainApplication("domain.tld");
HistoryEntry applicationCreateHistoryEntry = persistResource(new HistoryEntry.Builder()
.setParent(lrpApplication)
.setType(HistoryEntry.Type.DOMAIN_APPLICATION_CREATE)
.build());
persistResource(
new LrpTokenEntity.Builder()
.setAssignee("domain.tld")
.setToken("domain_token")
.setRedemptionHistoryEntry(Key.create(applicationCreateHistoryEntry))
.build());
}
@Test
public void testSuccess_byAssignee() throws Exception {
runCommand("--assignee=domain.tld");
assertInStdout("domain_token");
}
@Test
public void testSuccess_byToken() throws Exception {
runCommand("--token=domain_token");
assertInStdout("domain.tld");
assertNotInStdout("fullyQualifiedDomainName=domain.tld"); // history param should be false
}
@Test
public void testSuccess_iosByToken_withHistory() throws Exception {
runCommand("--token=domain_token", "--history");
assertInStdout("domain.tld");
assertInStdout("fullyQualifiedDomainName=domain.tld");
assertInStdout("type=DOMAIN_APPLICATION_CREATE");
}
@Test
public void testSuccess_unknownAssignee() throws Exception {
runCommand("--assignee=nobody");
assertInStdout("Token not found");
}
@Test
public void testSuccess_unknownToken() throws Exception {
runCommand("--token=bogus_token");
assertInStdout("Token not found");
}
@Test
public void testFailure_noArgs() {
IllegalArgumentException thrown =
assertThrows(IllegalArgumentException.class, this::runCommand);
assertThat(thrown)
.hasMessageThat()
.contains("Exactly one of either token or assignee must be specified.");
}
}

View file

@ -41,7 +41,6 @@ import java.io.PrintStream;
import org.joda.money.Money; import org.joda.money.Money;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.joda.time.Duration; import org.joda.time.Duration;
import org.joda.time.Interval;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -450,18 +449,6 @@ public class UpdateTldCommandTest extends CommandTestCase<UpdateTldCommand> {
assertThat(Registry.get("xn--q9jyb4c").getDomainCreateRestricted()).isTrue(); assertThat(Registry.get("xn--q9jyb4c").getDomainCreateRestricted()).isTrue();
} }
@Test
public void testSuccess_removeLrpPeriod() throws Exception {
persistResource(
Registry.get("xn--q9jyb4c").asBuilder()
.setLrpPeriod(new Interval(
DateTime.parse("2004-06-09T12:30:00Z"), DateTime.parse("2004-07-10T13:30:00Z")))
.build());
runCommandForced("--lrp_period=null", "xn--q9jyb4c");
assertThat(Registry.get("xn--q9jyb4c").getLrpPeriod())
.isEqualTo(new Interval(START_OF_TIME, Duration.ZERO));
}
@Test @Test
public void testFailure_invalidAddGracePeriod() { public void testFailure_invalidAddGracePeriod() {
IllegalArgumentException thrown = IllegalArgumentException thrown =
@ -1009,36 +996,6 @@ public class UpdateTldCommandTest extends CommandTestCase<UpdateTldCommand> {
assertThat(thrown).hasMessageThat().contains("The premium list 'phonies' doesn't exist"); assertThat(thrown).hasMessageThat().contains("The premium list 'phonies' doesn't exist");
} }
@Test
public void testSuccess_updateLrpPeriod() throws Exception {
runCommandForced("--lrp_period=2004-06-09T12:30:00Z/2004-07-10T13:30:00Z", "xn--q9jyb4c");
assertThat(Registry.get("xn--q9jyb4c").getLrpPeriod()).isEqualTo(
new Interval(
DateTime.parse("2004-06-09T12:30:00Z"), DateTime.parse("2004-07-10T13:30:00Z")));
}
@Test
public void testFailure_updateLrpPeriod_backwardsInterval() {
ParameterException thrown =
assertThrows(
ParameterException.class,
() ->
runCommandForced(
"--lrp_period=2005-06-09T12:30:00Z/2004-07-10T13:30:00Z", "xn--q9jyb4c"));
assertThat(thrown)
.hasMessageThat()
.contains(
"--lrp_period=2005-06-09T12:30:00Z/2004-07-10T13:30:00Z not an ISO-8601 interval");
}
@Test
public void testFailure_updateLrpPeriod_badInterval() {
ParameterException thrown =
assertThrows(
ParameterException.class, () -> runCommandForced("--lrp_period=foobar", "xn--q9jyb4c"));
assertThat(thrown).hasMessageThat().contains("--lrp_period=foobar not an ISO-8601 interval");
}
private void runSuccessfulReservedListsTest(String reservedLists) throws Exception { private void runSuccessfulReservedListsTest(String reservedLists) throws Exception {
runCommandForced("--reserved_lists", reservedLists, "xn--q9jyb4c"); runCommandForced("--reserved_lists", reservedLists, "xn--q9jyb4c");
} }

View file

@ -9,7 +9,7 @@
<domain:contact type="admin">jd1234</domain:contact> <domain:contact type="admin">jd1234</domain:contact>
<domain:contact type="tech">jd1234</domain:contact> <domain:contact type="tech">jd1234</domain:contact>
<domain:authInfo> <domain:authInfo>
<domain:pw>ANCHOR_abcdefghijklmnop</domain:pw> <domain:pw>abcdefghijklmnop</domain:pw>
</domain:authInfo> </domain:authInfo>
</domain:create> </domain:create>
</create> </create>

View file

@ -9,7 +9,7 @@
<domain:contact type="admin">jd1234</domain:contact> <domain:contact type="admin">jd1234</domain:contact>
<domain:contact type="tech">jd1234</domain:contact> <domain:contact type="tech">jd1234</domain:contact>
<domain:authInfo> <domain:authInfo>
<domain:pw>ANCHOR_abcdefghijklmnop</domain:pw> <domain:pw>abcdefghijklmnop</domain:pw>
</domain:authInfo> </domain:authInfo>
</domain:create> </domain:create>
</create> </create>

View file

@ -9,7 +9,7 @@
<domain:contact type="admin">jd1234</domain:contact> <domain:contact type="admin">jd1234</domain:contact>
<domain:contact type="tech">jd1234</domain:contact> <domain:contact type="tech">jd1234</domain:contact>
<domain:authInfo> <domain:authInfo>
<domain:pw>ANCHOR_abcdefghijklmnop</domain:pw> <domain:pw>abcdefghijklmnop</domain:pw>
</domain:authInfo> </domain:authInfo>
</domain:create> </domain:create>
</create> </create>

View file

@ -9,7 +9,7 @@
<domain:contact type="admin">jd1234</domain:contact> <domain:contact type="admin">jd1234</domain:contact>
<domain:contact type="tech">jd1234</domain:contact> <domain:contact type="tech">jd1234</domain:contact>
<domain:authInfo> <domain:authInfo>
<domain:pw>ANCHOR_abcdefghijklmnop</domain:pw> <domain:pw>abcdefghijklmnop</domain:pw>
</domain:authInfo> </domain:authInfo>
</domain:create> </domain:create>
</create> </create>

View file

@ -9,7 +9,7 @@
<domain:contact type="admin">jd1234</domain:contact> <domain:contact type="admin">jd1234</domain:contact>
<domain:contact type="tech">jd1234</domain:contact> <domain:contact type="tech">jd1234</domain:contact>
<domain:authInfo> <domain:authInfo>
<domain:pw>ANCHOR_abcdefghijklmnop</domain:pw> <domain:pw>abcdefghijklmnop</domain:pw>
</domain:authInfo> </domain:authInfo>
</domain:create> </domain:create>
</create> </create>