mirror of
https://github.com/google/nomulus
synced 2026-08-03 05:46:08 +00:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
efd5244ebd | ||
|
|
87e5d19fe5 | ||
|
|
bbb6174c9f | ||
|
|
2b826651e6 |
@@ -1300,6 +1300,30 @@ public final class RegistryConfig {
|
||||
return config.sslCertificateValidation.expirationWarningEmailSubjectText;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("dnsUpdateFailEmailSubjectText")
|
||||
public static String provideDnsUpdateFailEmailSubjectText(RegistryConfigSettings config) {
|
||||
return config.dnsUpdate.dnsUpdateFailEmailSubjectText;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("dnsUpdateFailEmailBodyText")
|
||||
public static String provideDnsUpdateFailEmailBodyText(RegistryConfigSettings config) {
|
||||
return config.dnsUpdate.dnsUpdateFailEmailBodyText;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("dnsUpdateFailRegistryName")
|
||||
public static String provideDnsUpdateFailRegistryName(RegistryConfigSettings config) {
|
||||
return config.dnsUpdate.dnsUpdateFailRegistryName;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("registrySupportEmail")
|
||||
public static String provideRegistrySupportEmail(RegistryConfigSettings config) {
|
||||
return config.dnsUpdate.registrySupportEmail;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("allowedEcdsaCurves")
|
||||
public static ImmutableSet<String> provideAllowedEcdsaCurves(RegistryConfigSettings config) {
|
||||
|
||||
@@ -42,6 +42,7 @@ public class RegistryConfigSettings {
|
||||
public RegistryTool registryTool;
|
||||
public SslCertificateValidation sslCertificateValidation;
|
||||
public ContactHistory contactHistory;
|
||||
public DnsUpdate dnsUpdate;
|
||||
|
||||
/** Configuration options that apply to the entire App Engine project. */
|
||||
public static class AppEngine {
|
||||
@@ -246,4 +247,12 @@ public class RegistryConfigSettings {
|
||||
public int minMonthsBeforeWipeOut;
|
||||
public int wipeOutQueryBatchSize;
|
||||
}
|
||||
|
||||
/** Configuration for dns update. */
|
||||
public static class DnsUpdate {
|
||||
public String dnsUpdateFailEmailSubjectText;
|
||||
public String dnsUpdateFailEmailBodyText;
|
||||
public String dnsUpdateFailRegistryName;
|
||||
public String registrySupportEmail;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -477,6 +477,28 @@ contactHistory:
|
||||
# The batch size for querying ContactHistory table in the database.
|
||||
wipeOutQueryBatchSize: 500
|
||||
|
||||
# Configuration options relevant to the DNS update functionality.
|
||||
dnsUpdate:
|
||||
dnsUpdateFailRegistryName: Example name
|
||||
registrySupportEmail: email@example.com
|
||||
# Email subject text template to notify partners after repeatedly failing DNS update
|
||||
dnsUpdateFailEmailSubjectText: "[ACTION REQUIRED]: Incomplete DNS Update"
|
||||
# Email body text template for failing DNS update that accepts 5 parameters:
|
||||
# registrar name, domain or host address, 'domain' or 'host' as a string that failed,
|
||||
# registry support email (see dnsUpdateFailRegistrySupportEmail) and registry display name
|
||||
dnsUpdateFailEmailBodyText: >
|
||||
Dear %1$s,
|
||||
|
||||
We are contacting you regarding the changes you recently made to one of your %2$ss.
|
||||
The DNS update for the %3$s %2$s failed to process. Please review your %2$s's DNS records
|
||||
and ensure that it is valid before trying another update.
|
||||
|
||||
If you have any questions or require additional support, please contact us
|
||||
at %4$s.
|
||||
|
||||
Regards,
|
||||
%5$s
|
||||
|
||||
# Configuration options for checking SSL certificates.
|
||||
sslCertificateValidation:
|
||||
# A map specifying the maximum amount of days the certificate can be valid.
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
package google.registry.dns;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static google.registry.dns.DnsConstants.DNS_PUBLISH_PUSH_QUEUE_NAME;
|
||||
import static google.registry.dns.DnsModule.PARAM_DNS_WRITER;
|
||||
import static google.registry.dns.DnsModule.PARAM_DOMAINS;
|
||||
@@ -22,6 +23,7 @@ import static google.registry.dns.DnsModule.PARAM_LOCK_INDEX;
|
||||
import static google.registry.dns.DnsModule.PARAM_NUM_PUBLISH_LOCKS;
|
||||
import static google.registry.dns.DnsModule.PARAM_PUBLISH_TASK_ENQUEUED;
|
||||
import static google.registry.dns.DnsModule.PARAM_REFRESH_REQUEST_CREATED;
|
||||
import static google.registry.model.EppResourceUtils.loadByForeignKey;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static google.registry.request.RequestParameters.PARAM_TLD;
|
||||
import static google.registry.util.CollectionUtils.nullToEmpty;
|
||||
@@ -37,6 +39,10 @@ import google.registry.dns.DnsMetrics.ActionStatus;
|
||||
import google.registry.dns.DnsMetrics.CommitStatus;
|
||||
import google.registry.dns.DnsMetrics.PublishStatus;
|
||||
import google.registry.dns.writer.DnsWriter;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarPoc;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Action.Service;
|
||||
@@ -46,6 +52,7 @@ import google.registry.request.Parameter;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.request.auth.Auth;
|
||||
import google.registry.request.lock.LockHandler;
|
||||
import google.registry.ui.server.SendEmailUtils;
|
||||
import google.registry.util.Clock;
|
||||
import google.registry.util.CloudTasksUtils;
|
||||
import google.registry.util.DomainNameUtils;
|
||||
@@ -102,6 +109,11 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
|
||||
private final Clock clock;
|
||||
private final CloudTasksUtils cloudTasksUtils;
|
||||
private final Response response;
|
||||
private final SendEmailUtils sendEmailUtils;
|
||||
private final String dnsUpdateFailEmailSubjectText;
|
||||
private final String dnsUpdateFailEmailBodyText;
|
||||
private final String dnsUpdateFailRegistryName;
|
||||
private final String registrySupportEmail;
|
||||
|
||||
@Inject
|
||||
public PublishDnsUpdatesAction(
|
||||
@@ -114,6 +126,10 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
|
||||
@Parameter(PARAM_HOSTS) Set<String> hosts,
|
||||
@Parameter(PARAM_TLD) String tld,
|
||||
@Config("publishDnsUpdatesLockDuration") Duration timeout,
|
||||
@Config("dnsUpdateFailEmailSubjectText") String dnsUpdateFailEmailSubjectText,
|
||||
@Config("dnsUpdateFailEmailBodyText") String dnsUpdateFailEmailBodyText,
|
||||
@Config("dnsUpdateFailRegistryName") String dnsUpdateFailRegistryName,
|
||||
@Config("registrySupportEmail") String registrySupportEmail,
|
||||
@Header(APP_ENGINE_RETRY_HEADER) Optional<Integer> appEngineRetryCount,
|
||||
@Header(CLOUD_TASKS_RETRY_HEADER) Optional<Integer> cloudTasksRetryCount,
|
||||
DnsQueue dnsQueue,
|
||||
@@ -122,11 +138,13 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
|
||||
LockHandler lockHandler,
|
||||
Clock clock,
|
||||
CloudTasksUtils cloudTasksUtils,
|
||||
SendEmailUtils sendEmailUtils,
|
||||
Response response) {
|
||||
this.dnsQueue = dnsQueue;
|
||||
this.dnsWriterProxy = dnsWriterProxy;
|
||||
this.dnsMetrics = dnsMetrics;
|
||||
this.timeout = timeout;
|
||||
this.sendEmailUtils = sendEmailUtils;
|
||||
this.retryCount =
|
||||
cloudTasksRetryCount.orElse(
|
||||
appEngineRetryCount.orElseThrow(
|
||||
@@ -143,6 +161,10 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
|
||||
this.clock = clock;
|
||||
this.cloudTasksUtils = cloudTasksUtils;
|
||||
this.response = response;
|
||||
this.dnsUpdateFailEmailBodyText = dnsUpdateFailEmailBodyText;
|
||||
this.dnsUpdateFailEmailSubjectText = dnsUpdateFailEmailSubjectText;
|
||||
this.dnsUpdateFailRegistryName = dnsUpdateFailRegistryName;
|
||||
this.registrySupportEmail = registrySupportEmail;
|
||||
}
|
||||
|
||||
private void recordActionResult(ActionStatus status) {
|
||||
@@ -209,9 +231,35 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
|
||||
} else if (retryCount < RETRIES_BEFORE_PERMANENT_FAILURE) {
|
||||
// If the batch only contains 1 name, allow it more retries
|
||||
throw e;
|
||||
} else {
|
||||
// By the time we get here there's either single domain or a single host
|
||||
domains.stream()
|
||||
.findFirst()
|
||||
.ifPresent(
|
||||
dn -> {
|
||||
Optional<Domain> domain = loadByForeignKey(Domain.class, dn, clock.nowUtc());
|
||||
if (domain.isPresent()) {
|
||||
notifyWithEmailAboutDnsUpdateFailure(
|
||||
domain.get().getCurrentSponsorRegistrarId(), dn, false);
|
||||
} else {
|
||||
logger.atSevere().log(String.format("Domain entity for %s not found", dn));
|
||||
}
|
||||
});
|
||||
|
||||
hosts.stream()
|
||||
.findFirst()
|
||||
.ifPresent(
|
||||
hn -> {
|
||||
Optional<Host> host = loadByForeignKey(Host.class, hn, clock.nowUtc());
|
||||
if (host.isPresent()) {
|
||||
notifyWithEmailAboutDnsUpdateFailure(
|
||||
host.get().getPersistedCurrentSponsorRegistrarId(), hn, true);
|
||||
} else {
|
||||
logger.atSevere().log(String.format("Host entity for %s not found", hn));
|
||||
}
|
||||
});
|
||||
}
|
||||
// If we get here, we should terminate this task as it is likely a perpetually failing task.
|
||||
// TODO(b/237302821): Send an email notifying partner the dns update failed
|
||||
|
||||
recordActionResult(ActionStatus.MAX_RETRIES_EXCEEDED);
|
||||
response.setStatus(SC_ACCEPTED);
|
||||
logger.atSevere().withCause(e).log("Terminated task after too many retries");
|
||||
@@ -219,6 +267,30 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Sends an email to partners regarding a failure during DNS update */
|
||||
private void notifyWithEmailAboutDnsUpdateFailure(
|
||||
String registrarId, String hostOrDomainName, Boolean isHost) {
|
||||
Optional<Registrar> registrar = Registrar.loadByRegistrarIdCached(registrarId);
|
||||
|
||||
if (registrar.isPresent()) {
|
||||
sendEmailUtils.sendEmail(
|
||||
dnsUpdateFailEmailSubjectText,
|
||||
String.format(
|
||||
dnsUpdateFailEmailBodyText,
|
||||
registrar.get().getRegistrarName(),
|
||||
hostOrDomainName,
|
||||
isHost ? "host" : "domain",
|
||||
registrySupportEmail,
|
||||
dnsUpdateFailRegistryName),
|
||||
registrar.get().getContacts().stream()
|
||||
.filter(c -> c.getTypes().contains(RegistrarPoc.Type.ADMIN))
|
||||
.map(RegistrarPoc::getEmailAddress)
|
||||
.collect(toImmutableList()));
|
||||
} else {
|
||||
logger.atSevere().log(String.format("Could not find registrar %s", registrarId));
|
||||
}
|
||||
}
|
||||
|
||||
/** Splits the domains and hosts in a batch into smaller batches and adds them to the queue. */
|
||||
private void splitBatch() {
|
||||
ImmutableList<String> domainList = ImmutableList.copyOf(domains);
|
||||
@@ -294,8 +366,7 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
|
||||
int domainsPublished = 0;
|
||||
int domainsRejected = 0;
|
||||
for (String domain : nullToEmpty(domains)) {
|
||||
if (!DomainNameUtils.isUnder(
|
||||
InternetDomainName.from(domain), InternetDomainName.from(tld))) {
|
||||
if (!DomainNameUtils.isUnder(InternetDomainName.from(domain), InternetDomainName.from(tld))) {
|
||||
logger.atSevere().log("%s: skipping domain %s not under TLD.", tld, domain);
|
||||
domainsRejected += 1;
|
||||
} else {
|
||||
@@ -310,8 +381,7 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
|
||||
int hostsPublished = 0;
|
||||
int hostsRejected = 0;
|
||||
for (String host : nullToEmpty(hosts)) {
|
||||
if (!DomainNameUtils.isUnder(
|
||||
InternetDomainName.from(host), InternetDomainName.from(tld))) {
|
||||
if (!DomainNameUtils.isUnder(InternetDomainName.from(host), InternetDomainName.from(tld))) {
|
||||
logger.atSevere().log("%s: skipping host %s not under TLD.", tld, host);
|
||||
hostsRejected += 1;
|
||||
} else {
|
||||
|
||||
@@ -153,6 +153,7 @@ import org.joda.time.Duration;
|
||||
* @error {@link DomainCreateFlow.AnchorTenantCreatePeriodException}
|
||||
* @error {@link DomainCreateFlow.MustHaveSignedMarksInCurrentPhaseException}
|
||||
* @error {@link DomainCreateFlow.NoGeneralRegistrationsInCurrentPhaseException}
|
||||
* @error {@link DomainCreateFlow.NoTrademarkedRegistrationsBeforeSunriseException}
|
||||
* @error {@link DomainCreateFlow.SignedMarksOnlyDuringSunriseException}
|
||||
* @error {@link DomainFlowTmchUtils.NoMarksFoundMatchingDomainException}
|
||||
* @error {@link DomainFlowTmchUtils.FoundMarkNotYetValidException}
|
||||
@@ -481,7 +482,8 @@ public final class DomainCreateFlow implements TransactionalFlow {
|
||||
boolean isValidReservedCreate,
|
||||
boolean hasSignedMarks)
|
||||
throws NoGeneralRegistrationsInCurrentPhaseException,
|
||||
MustHaveSignedMarksInCurrentPhaseException {
|
||||
MustHaveSignedMarksInCurrentPhaseException,
|
||||
NoTrademarkedRegistrationsBeforeSunriseException {
|
||||
// We allow general registration during GA.
|
||||
TldState currentState = registry.getTldState(now);
|
||||
if (currentState.equals(GENERAL_AVAILABILITY)) {
|
||||
@@ -496,16 +498,23 @@ public final class DomainCreateFlow implements TransactionalFlow {
|
||||
// Bypass most TLD state checks if that behavior is specified by the token
|
||||
if (behavior.equals(RegistrationBehavior.BYPASS_TLD_STATE)
|
||||
|| behavior.equals(RegistrationBehavior.ANCHOR_TENANT)) {
|
||||
// If bypassing TLD state checks, a post-sunrise state is always fine
|
||||
if (!currentState.equals(START_DATE_SUNRISE)
|
||||
&& registry.getTldStateTransitions().headMap(now).containsValue(START_DATE_SUNRISE)) {
|
||||
return;
|
||||
}
|
||||
// Non-trademarked names with the state check bypassed are always available
|
||||
if (!claimsList.getClaimKey(domainLabel).isPresent()) {
|
||||
return;
|
||||
}
|
||||
if (!currentState.equals(START_DATE_SUNRISE)) {
|
||||
// Trademarked domains cannot be registered until after the sunrise period has ended, unless
|
||||
// a valid signed mark is provided. Signed marks can only be provided during sunrise.
|
||||
// Thus, when bypassing TLD state checks, a post-sunrise state is always fine.
|
||||
if (registry.getTldStateTransitions().headMap(now).containsValue(START_DATE_SUNRISE)) {
|
||||
return;
|
||||
} else {
|
||||
// If sunrise hasn't happened yet, trademarked domains are unavailable
|
||||
throw new NoTrademarkedRegistrationsBeforeSunriseException(domainLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, signed marks are necessary and sufficient in the sunrise period
|
||||
if (currentState.equals(START_DATE_SUNRISE)) {
|
||||
if (!hasSignedMarks) {
|
||||
@@ -724,6 +733,17 @@ public final class DomainCreateFlow implements TransactionalFlow {
|
||||
}
|
||||
}
|
||||
|
||||
/** Trademarked domains cannot be registered before the sunrise period. */
|
||||
static class NoTrademarkedRegistrationsBeforeSunriseException
|
||||
extends ParameterValuePolicyErrorException {
|
||||
public NoTrademarkedRegistrationsBeforeSunriseException(String domainLabel) {
|
||||
super(
|
||||
String.format(
|
||||
"The trademarked label %s cannot be registered before the sunrise period.",
|
||||
domainLabel));
|
||||
}
|
||||
}
|
||||
|
||||
/** Anchor tenant domain create is for the wrong number of years. */
|
||||
static class AnchorTenantCreatePeriodException extends ParameterValuePolicyErrorException {
|
||||
public AnchorTenantCreatePeriodException(int invalidYears) {
|
||||
|
||||
@@ -112,6 +112,7 @@ import google.registry.model.domain.secdns.SecDnsUpdateExtension;
|
||||
import google.registry.model.domain.secdns.SecDnsUpdateExtension.Add;
|
||||
import google.registry.model.domain.secdns.SecDnsUpdateExtension.Remove;
|
||||
import google.registry.model.domain.token.AllocationToken;
|
||||
import google.registry.model.domain.token.AllocationToken.RegistrationBehavior;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
|
||||
import google.registry.model.host.Host;
|
||||
@@ -270,7 +271,13 @@ public class DomainFlowUtils {
|
||||
&& token.get().getDomainName().get().equals(domainName.toString())) {
|
||||
return true;
|
||||
}
|
||||
// Otherwise check whether the metadata extension is being used by a superuser to specify that
|
||||
// Otherwise, check to see if we're using the specialized anchor tenant registration behavior on
|
||||
// the allocation token
|
||||
if (token.isPresent()
|
||||
&& token.get().getRegistrationBehavior().equals(RegistrationBehavior.ANCHOR_TENANT)) {
|
||||
return true;
|
||||
}
|
||||
// Otherwise, check whether the metadata extension is being used by a superuser to specify that
|
||||
// it's an anchor tenant creation.
|
||||
return metadataExtension.isPresent() && metadataExtension.get().getIsAnchorTenant();
|
||||
}
|
||||
|
||||
@@ -56,7 +56,6 @@ import google.registry.model.domain.DomainHistory.DomainHistoryId;
|
||||
import google.registry.model.domain.GracePeriod;
|
||||
import google.registry.model.domain.metadata.MetadataExtension;
|
||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||
import google.registry.model.domain.token.AllocationToken;
|
||||
import google.registry.model.domain.token.AllocationTokenExtension;
|
||||
import google.registry.model.eppcommon.AuthInfo;
|
||||
import google.registry.model.eppinput.EppInput;
|
||||
@@ -129,15 +128,12 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
|
||||
extensionManager.validate();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
Domain existingDomain = loadAndVerifyExistence(Domain.class, targetId, now);
|
||||
// Currently we do not do anything with this allocation token, but just want it loaded and
|
||||
// available in this flow in case we use it in the future
|
||||
Optional<AllocationToken> allocationToken =
|
||||
allocationTokenFlowUtils.verifyAllocationTokenIfPresent(
|
||||
existingDomain,
|
||||
Registry.get(existingDomain.getTld()),
|
||||
registrarId,
|
||||
now,
|
||||
eppInput.getSingleExtension(AllocationTokenExtension.class));
|
||||
allocationTokenFlowUtils.verifyAllocationTokenIfPresent(
|
||||
existingDomain,
|
||||
Registry.get(existingDomain.getTld()),
|
||||
registrarId,
|
||||
now,
|
||||
eppInput.getSingleExtension(AllocationTokenExtension.class));
|
||||
verifyOptionalAuthInfo(authInfo, existingDomain);
|
||||
verifyHasPendingTransfer(existingDomain);
|
||||
verifyResourceOwnership(registrarId, existingDomain);
|
||||
@@ -182,9 +178,9 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
|
||||
getOnlyElement(existingDomain.getGracePeriodsOfType(GracePeriodStatus.AUTO_RENEW), null);
|
||||
if (autorenewGrace != null) {
|
||||
// During a normal transfer, if the domain is in the auto-renew grace period, the auto-renew
|
||||
// billing event is cancelled and the gaining registrar is charged for the one year renewal.
|
||||
// billing event is cancelled and the gaining registrar is charged for the one-year renewal.
|
||||
// But, if the superuser extension is used to request a transfer without an additional year
|
||||
// then the gaining registrar is not charged for the one year renewal and the losing registrar
|
||||
// then the gaining registrar is not charged for the one-year renewal and the losing registrar
|
||||
// still needs to be charged for the auto-renew.
|
||||
if (billingEvent.isPresent()) {
|
||||
entitiesToSave.add(
|
||||
|
||||
@@ -62,7 +62,6 @@ import google.registry.model.domain.fee.FeeTransferCommandExtension;
|
||||
import google.registry.model.domain.fee.FeeTransformResponseExtension;
|
||||
import google.registry.model.domain.metadata.MetadataExtension;
|
||||
import google.registry.model.domain.superuser.DomainTransferRequestSuperuserExtension;
|
||||
import google.registry.model.domain.token.AllocationToken;
|
||||
import google.registry.model.domain.token.AllocationTokenExtension;
|
||||
import google.registry.model.eppcommon.AuthInfo;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
@@ -169,15 +168,12 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
|
||||
extensionManager.validate();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
Domain existingDomain = loadAndVerifyExistence(Domain.class, targetId, now);
|
||||
// Currently we do not do anything with this allocation token, but just want it loaded and
|
||||
// available in this flow in case we use it in the future
|
||||
Optional<AllocationToken> allocationToken =
|
||||
allocationTokenFlowUtils.verifyAllocationTokenIfPresent(
|
||||
existingDomain,
|
||||
Registry.get(existingDomain.getTld()),
|
||||
gainingClientId,
|
||||
now,
|
||||
eppInput.getSingleExtension(AllocationTokenExtension.class));
|
||||
allocationTokenFlowUtils.verifyAllocationTokenIfPresent(
|
||||
existingDomain,
|
||||
Registry.get(existingDomain.getTld()),
|
||||
gainingClientId,
|
||||
now,
|
||||
eppInput.getSingleExtension(AllocationTokenExtension.class));
|
||||
Optional<DomainTransferRequestSuperuserExtension> superuserExtension =
|
||||
eppInput.getSingleExtension(DomainTransferRequestSuperuserExtension.class);
|
||||
Period period =
|
||||
@@ -210,9 +206,12 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
|
||||
.setId(domainHistoryKey.getId())
|
||||
.setOtherRegistrarId(existingDomain.getCurrentSponsorRegistrarId());
|
||||
DateTime automaticTransferTime =
|
||||
superuserExtension.isPresent()
|
||||
? now.plusDays(superuserExtension.get().getAutomaticTransferLength())
|
||||
: now.plus(registry.getAutomaticTransferLength());
|
||||
superuserExtension
|
||||
.map(
|
||||
domainTransferRequestSuperuserExtension ->
|
||||
now.plusDays(
|
||||
domainTransferRequestSuperuserExtension.getAutomaticTransferLength()))
|
||||
.orElseGet(() -> now.plus(registry.getAutomaticTransferLength()));
|
||||
// If the domain will be in the auto-renew grace period at the moment of transfer, the transfer
|
||||
// will subsume the autorenew, so we don't add the normal extra year from the transfer.
|
||||
// The gaining registrar is still billed for the extra year; the losing registrar will get a
|
||||
@@ -325,7 +324,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
|
||||
*
|
||||
* <p>Even if not required, this policy is desirable because it dramatically simplifies the logic
|
||||
* in transfer flows. Registrars appear to never request 2+ year transfers in practice, and they
|
||||
* can always decompose an multi-year transfer into a 1-year transfer followed by a manual renewal
|
||||
* can always decompose a multi-year transfer into a 1-year transfer followed by a manual renewal
|
||||
* afterwards. The <a href="https://tools.ietf.org/html/rfc5731#section-3.2.4">EPP Domain RFC,
|
||||
* section 3.2.4</a> says about EPP transfer periods that "the number of units available MAY be
|
||||
* subject to limits imposed by the server" so we're just limiting the units to one.
|
||||
@@ -370,7 +369,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
|
||||
private DomainTransferResponse createResponse(
|
||||
Period period, Domain existingDomain, Domain newDomain, DateTime now) {
|
||||
// If the registration were approved this instant, this is what the new expiration would be,
|
||||
// because we cap at 10 years from the moment of approval. This is different than the server
|
||||
// because we cap at 10 years from the moment of approval. This is different from the server
|
||||
// approval new expiration time, which is capped at 10 years from the server approve time.
|
||||
DateTime approveNowExtendedRegistrationTime =
|
||||
computeExDateForApprovalTime(existingDomain, now, period);
|
||||
|
||||
@@ -63,5 +63,7 @@ public enum ConsolePermission {
|
||||
/** View announcements in the UI. */
|
||||
VIEW_ANNOUNCEMENTS,
|
||||
/** Viewing a record of actions performed in the UI for a particular registrar. */
|
||||
VIEW_ACTIVITY_LOG
|
||||
VIEW_ACTIVITY_LOG,
|
||||
/** View and perform registry locks. */
|
||||
REGISTRY_LOCK
|
||||
}
|
||||
|
||||
@@ -44,7 +44,8 @@ public class ConsoleRoleDefinitions {
|
||||
ConsolePermission.VIEW_OPERATIONAL_DATA,
|
||||
ConsolePermission.SEND_ANNOUNCEMENTS,
|
||||
ConsolePermission.VIEW_ANNOUNCEMENTS,
|
||||
ConsolePermission.VIEW_ACTIVITY_LOG);
|
||||
ConsolePermission.VIEW_ACTIVITY_LOG,
|
||||
ConsolePermission.REGISTRY_LOCK);
|
||||
|
||||
/** Permissions for a registry support lead. */
|
||||
static final ImmutableSet<ConsolePermission> SUPPORT_LEAD_PERMISSIONS =
|
||||
@@ -76,10 +77,17 @@ public class ConsoleRoleDefinitions {
|
||||
ConsolePermission.VIEW_OPERATIONAL_DATA,
|
||||
ConsolePermission.VIEW_ANNOUNCEMENTS);
|
||||
|
||||
/** Permissions for a registrar partner account manager that can perform registry locks. */
|
||||
static final ImmutableSet<ConsolePermission> ACCOUNT_MANAGER_WITH_REGISTRY_LOCK_PERMISSIONS =
|
||||
new ImmutableSet.Builder<ConsolePermission>()
|
||||
.addAll(ACCOUNT_MANAGER_PERMISSIONS)
|
||||
.add(ConsolePermission.REGISTRY_LOCK)
|
||||
.build();
|
||||
|
||||
/** Permissions for the tech contact of a registrar. */
|
||||
static final ImmutableSet<ConsolePermission> TECH_CONTACT_PERMISSIONS =
|
||||
new ImmutableSet.Builder<ConsolePermission>()
|
||||
.addAll(ACCOUNT_MANAGER_PERMISSIONS)
|
||||
.addAll(ACCOUNT_MANAGER_WITH_REGISTRY_LOCK_PERMISSIONS)
|
||||
.add(
|
||||
ConsolePermission.MANAGE_ACCREDITATION,
|
||||
ConsolePermission.CONFIGURE_EPP_CONNECTION,
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
package google.registry.model.console;
|
||||
|
||||
import static google.registry.model.console.ConsoleRoleDefinitions.ACCOUNT_MANAGER_PERMISSIONS;
|
||||
import static google.registry.model.console.ConsoleRoleDefinitions.ACCOUNT_MANAGER_WITH_REGISTRY_LOCK_PERMISSIONS;
|
||||
import static google.registry.model.console.ConsoleRoleDefinitions.PRIMARY_CONTACT_PERMISSIONS;
|
||||
import static google.registry.model.console.ConsoleRoleDefinitions.TECH_CONTACT_PERMISSIONS;
|
||||
|
||||
@@ -25,6 +26,8 @@ public enum RegistrarRole {
|
||||
|
||||
/** The user is a standard account manager at a registrar. */
|
||||
ACCOUNT_MANAGER(ACCOUNT_MANAGER_PERMISSIONS),
|
||||
/** The user is an account manager that can perform registry locks. */
|
||||
ACCOUNT_MANAGER_WITH_REGISTRY_LOCK(ACCOUNT_MANAGER_WITH_REGISTRY_LOCK_PERMISSIONS),
|
||||
/** The user is a technical contact of a registrar. */
|
||||
TECH_CONTACT(TECH_CONTACT_PERMISSIONS),
|
||||
/** The user is the primary contact at a registrar. */
|
||||
|
||||
@@ -40,12 +40,6 @@ public class User extends ImmutableObject implements Buildable {
|
||||
/** Roles (which grant permissions) associated with this user. */
|
||||
private UserRoles userRoles;
|
||||
|
||||
/**
|
||||
* Whether the contact is allowed to set their registry lock password through the registrar
|
||||
* console. This will be set to false on contact creation and when the user sets a password.
|
||||
*/
|
||||
boolean allowedToSetRegistryLockPassword = false;
|
||||
|
||||
/**
|
||||
* A hashed password that exists iff this contact is registry-lock-enabled. The hash is a base64
|
||||
* encoded SHA256 string.
|
||||
@@ -55,6 +49,10 @@ public class User extends ImmutableObject implements Buildable {
|
||||
/** Randomly generated hash salt. */
|
||||
String registryLockPasswordSalt;
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getGaiaId() {
|
||||
return gaiaId;
|
||||
}
|
||||
@@ -67,11 +65,7 @@ public class User extends ImmutableObject implements Buildable {
|
||||
return userRoles;
|
||||
}
|
||||
|
||||
public boolean isAllowedToSetRegistryLockPassword() {
|
||||
return allowedToSetRegistryLockPassword;
|
||||
}
|
||||
|
||||
public boolean isRegistryLockAllowed() {
|
||||
public boolean hasRegistryLockPassword() {
|
||||
return !isNullOrEmpty(registryLockPasswordHash) && !isNullOrEmpty(registryLockPasswordSalt);
|
||||
}
|
||||
|
||||
@@ -85,6 +79,22 @@ public class User extends ImmutableObject implements Buildable {
|
||||
.equals(registryLockPasswordHash);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the user has the registry lock permission on any registrar or globally.
|
||||
*
|
||||
* <p>If so, they should be allowed to (re)set their registry lock password.
|
||||
*/
|
||||
public boolean hasAnyRegistryLockPermission() {
|
||||
if (userRoles == null) {
|
||||
return false;
|
||||
}
|
||||
if (userRoles.isAdmin() || userRoles.hasGlobalPermission(ConsolePermission.REGISTRY_LOCK)) {
|
||||
return true;
|
||||
}
|
||||
return userRoles.getRegistrarRoles().values().stream()
|
||||
.anyMatch(role -> role.hasPermission(ConsolePermission.REGISTRY_LOCK));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder asBuilder() {
|
||||
return new Builder(clone(this));
|
||||
@@ -99,6 +109,7 @@ public class User extends ImmutableObject implements Buildable {
|
||||
super(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public User build() {
|
||||
checkArgumentNotNull(getInstance().gaiaId, "Gaia ID cannot be null");
|
||||
checkArgumentNotNull(getInstance().emailAddress, "Email address cannot be null");
|
||||
@@ -123,25 +134,22 @@ public class User extends ImmutableObject implements Buildable {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setAllowedToSetRegistryLockPassword(boolean allowedToSetRegistryLockPassword) {
|
||||
if (allowedToSetRegistryLockPassword) {
|
||||
getInstance().registryLockPasswordSalt = null;
|
||||
getInstance().registryLockPasswordHash = null;
|
||||
}
|
||||
getInstance().allowedToSetRegistryLockPassword = allowedToSetRegistryLockPassword;
|
||||
public Builder removeRegistryLockPassword() {
|
||||
getInstance().registryLockPasswordHash = null;
|
||||
getInstance().registryLockPasswordSalt = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setRegistryLockPassword(String registryLockPassword) {
|
||||
checkArgument(
|
||||
getInstance().allowedToSetRegistryLockPassword,
|
||||
"Not allowed to set registry lock password for this user");
|
||||
getInstance().hasAnyRegistryLockPermission(), "User has no registry lock permission");
|
||||
checkArgument(
|
||||
!getInstance().hasRegistryLockPassword(), "User already has a password, remove it first");
|
||||
checkArgument(
|
||||
!isNullOrEmpty(registryLockPassword), "Registry lock password was null or empty");
|
||||
getInstance().registryLockPasswordSalt = base64().encode(SALT_SUPPLIER.get());
|
||||
getInstance().registryLockPasswordHash =
|
||||
hashPassword(registryLockPassword, getInstance().registryLockPasswordSalt);
|
||||
getInstance().allowedToSetRegistryLockPassword = false;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ import google.registry.testing.CloudTasksHelper;
|
||||
import google.registry.testing.CloudTasksHelper.TaskMatcher;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.FakeSleeper;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import google.registry.util.CapturingLogHandler;
|
||||
import google.registry.util.CloudTasksUtils;
|
||||
import google.registry.util.JdkLoggerConfig;
|
||||
@@ -57,12 +56,10 @@ public class AsyncTaskEnqueuerTest {
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withCloudSql().withTaskQueue().build();
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
|
||||
private AsyncTaskEnqueuer asyncTaskEnqueuer;
|
||||
private final CapturingLogHandler logHandler = new CapturingLogHandler();
|
||||
private final FakeClock clock = new FakeClock(DateTime.parse("2015-05-18T12:34:56Z"));
|
||||
private CloudTasksHelper cloudTasksHelper = new CloudTasksHelper(clock);
|
||||
private final CloudTasksHelper cloudTasksHelper = new CloudTasksHelper(clock);
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
|
||||
@@ -34,7 +34,6 @@ import google.registry.model.billing.BillingEvent.Flag;
|
||||
import google.registry.model.billing.BillingEvent.Reason;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.persistence.transaction.QueryComposer.Comparator;
|
||||
@@ -43,7 +42,6 @@ import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.FakeLockHandler;
|
||||
import google.registry.testing.FakeResponse;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import java.util.Optional;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@@ -59,14 +57,11 @@ class DeleteExpiredDomainsActionTest {
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withCloudSql().withClock(clock).withTaskQueue().build();
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
|
||||
private final FakeResponse response = new FakeResponse();
|
||||
private DeleteExpiredDomainsAction action;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
inject.setStaticField(Ofy.class, "clock", clock);
|
||||
createTld("tld");
|
||||
EppController eppController =
|
||||
DaggerEppTestComponent.builder()
|
||||
@@ -103,7 +98,7 @@ class DeleteExpiredDomainsActionTest {
|
||||
|
||||
// A non-autorenewing domain that is past its expiration time and should be deleted.
|
||||
// (This is the only one that needs a full set of subsidiary resources, for the delete flow to
|
||||
// to operate on.)
|
||||
// operate on.)
|
||||
Domain pendingExpirationDomain = persistNonAutorenewingDomain("fizz.tld");
|
||||
|
||||
assertThat(loadByEntity(pendingExpirationDomain).getStatusValues())
|
||||
|
||||
@@ -20,7 +20,6 @@ import static google.registry.batch.AsyncTaskEnqueuer.PARAM_RESOURCE_KEY;
|
||||
import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_ACTIONS;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.loadByEntity;
|
||||
import static google.registry.testing.DatabaseHelper.newDomain;
|
||||
import static google.registry.testing.DatabaseHelper.persistActiveContact;
|
||||
import static google.registry.testing.DatabaseHelper.persistDomainWithDependentResources;
|
||||
import static google.registry.testing.DatabaseHelper.persistDomainWithPendingTransfer;
|
||||
@@ -35,14 +34,12 @@ import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.GracePeriod;
|
||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.CloudTasksHelper;
|
||||
import google.registry.testing.CloudTasksHelper.TaskMatcher;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@@ -62,16 +59,13 @@ public class ResaveEntityActionTest {
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withCloudSql().withTaskQueue().build();
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
|
||||
@Mock private Response response;
|
||||
private final FakeClock clock = new FakeClock(DateTime.parse("2016-02-11T10:00:00Z"));
|
||||
private AsyncTaskEnqueuer asyncTaskEnqueuer;
|
||||
private CloudTasksHelper cloudTasksHelper = new CloudTasksHelper(clock);
|
||||
private final CloudTasksHelper cloudTasksHelper = new CloudTasksHelper(clock);
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
inject.setStaticField(Ofy.class, "clock", clock);
|
||||
asyncTaskEnqueuer =
|
||||
AsyncTaskEnqueuerTest.createForTesting(
|
||||
cloudTasksHelper.getTestCloudTasksUtils(), clock, Duration.ZERO);
|
||||
|
||||
+4
-7
@@ -15,7 +15,6 @@
|
||||
package google.registry.batch;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.Truth8.assertThat;
|
||||
import static google.registry.testing.AppEngineExtension.makeRegistrar1;
|
||||
import static google.registry.testing.DatabaseHelper.loadByEntity;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
@@ -40,7 +39,6 @@ import google.registry.model.registrar.RegistrarPoc.Type;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.FakeResponse;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import google.registry.util.SelfSignedCaCertificate;
|
||||
import google.registry.util.SendEmailService;
|
||||
import java.security.cert.X509Certificate;
|
||||
@@ -57,11 +55,11 @@ class SendExpiringCertificateNotificationEmailActionTest {
|
||||
|
||||
private static final String EXPIRATION_WARNING_EMAIL_BODY_TEXT =
|
||||
" Dear %1$s,\n"
|
||||
+ "\n"
|
||||
+ '\n'
|
||||
+ "We would like to inform you that your %2$s certificate will expire at %3$s."
|
||||
+ "\n"
|
||||
+ '\n'
|
||||
+ " Kind update your account using the following steps: "
|
||||
+ "\n"
|
||||
+ '\n'
|
||||
+ " 1. Navigate to support and login using your %4$s@registry.example credentials.\n"
|
||||
+ " 2. Click Settings -> Privacy on the top left corner.\n"
|
||||
+ " 3. Click Edit and enter certificate string."
|
||||
@@ -75,7 +73,6 @@ class SendExpiringCertificateNotificationEmailActionTest {
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withCloudSql().withTaskQueue().build();
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
private final FakeClock clock = new FakeClock(DateTime.parse("2021-05-24T20:21:22Z"));
|
||||
private final SendEmailService sendEmailService = mock(SendEmailService.class);
|
||||
private CertificateChecker certificateChecker;
|
||||
@@ -708,7 +705,7 @@ class SendExpiringCertificateNotificationEmailActionTest {
|
||||
}
|
||||
|
||||
/** Returns persisted sample contacts with a customized contact email type. */
|
||||
private ImmutableList<RegistrarPoc> persistSampleContacts(
|
||||
private static ImmutableList<RegistrarPoc> persistSampleContacts(
|
||||
Registrar registrar, RegistrarPoc.Type emailType) {
|
||||
return persistSimpleResources(
|
||||
ImmutableList.of(
|
||||
|
||||
@@ -38,7 +38,6 @@ import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.FakeResponse;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -102,7 +101,6 @@ class WipeOutContactHistoryPiiActionTest {
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withCloudSql().withTaskQueue().build();
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
private final FakeClock clock = new FakeClock(DateTime.parse("2021-08-26T20:21:22Z"));
|
||||
|
||||
private FakeResponse response;
|
||||
|
||||
@@ -24,13 +24,11 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.request.HttpException.NotFoundException;
|
||||
import google.registry.request.RequestModule;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.CloudTasksHelper.CloudTasksHelperModule;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@@ -47,8 +45,6 @@ public final class DnsInjectionTest {
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withCloudSql().withTaskQueue().build();
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
|
||||
private final HttpServletRequest req = mock(HttpServletRequest.class);
|
||||
private final HttpServletResponse rsp = mock(HttpServletResponse.class);
|
||||
private final StringWriter httpOutput = new StringWriter();
|
||||
@@ -58,7 +54,6 @@ public final class DnsInjectionTest {
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() throws Exception {
|
||||
inject.setStaticField(Ofy.class, "clock", clock);
|
||||
when(rsp.getWriter()).thenReturn(new PrintWriter(httpOutput));
|
||||
component =
|
||||
DaggerDnsTestComponent.builder()
|
||||
|
||||
@@ -38,6 +38,7 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.dns.DnsMetrics.ActionStatus;
|
||||
@@ -45,7 +46,6 @@ import google.registry.dns.DnsMetrics.CommitStatus;
|
||||
import google.registry.dns.DnsMetrics.PublishStatus;
|
||||
import google.registry.dns.writer.DnsWriter;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.request.HttpException.ServiceUnavailableException;
|
||||
import google.registry.request.lock.LockHandler;
|
||||
@@ -55,14 +55,18 @@ import google.registry.testing.CloudTasksHelper.TaskMatcher;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.FakeLockHandler;
|
||||
import google.registry.testing.FakeResponse;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import google.registry.ui.server.SendEmailUtils;
|
||||
import google.registry.util.EmailMessage;
|
||||
import google.registry.util.SendEmailService;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
/** Unit tests for {@link PublishDnsUpdatesAction}. */
|
||||
public class PublishDnsUpdatesActionTest {
|
||||
@@ -71,7 +75,6 @@ public class PublishDnsUpdatesActionTest {
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withCloudSql().withTaskQueue().build();
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
private final FakeClock clock = new FakeClock(DateTime.parse("1971-01-01TZ"));
|
||||
private final FakeResponse response = new FakeResponse();
|
||||
private final FakeLockHandler lockHandler = new FakeLockHandler(true);
|
||||
@@ -80,10 +83,18 @@ public class PublishDnsUpdatesActionTest {
|
||||
private final DnsQueue dnsQueue = mock(DnsQueue.class);
|
||||
private final CloudTasksHelper cloudTasksHelper = new CloudTasksHelper();
|
||||
private PublishDnsUpdatesAction action;
|
||||
private final SendEmailService emailService = mock(SendEmailService.class);
|
||||
private SendEmailUtils sendEmailUtils;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
inject.setStaticField(Ofy.class, "clock", clock);
|
||||
void beforeEach() throws Exception {
|
||||
sendEmailUtils =
|
||||
new SendEmailUtils(
|
||||
new InternetAddress("outgoing@registry.example"),
|
||||
"UnitTest Registry",
|
||||
ImmutableList.of("notification@test.example", "notification2@test.example"),
|
||||
emailService);
|
||||
|
||||
createTld("xn--q9jyb4c");
|
||||
persistResource(
|
||||
Registry.get("xn--q9jyb4c")
|
||||
@@ -142,6 +153,10 @@ public class PublishDnsUpdatesActionTest {
|
||||
hosts,
|
||||
tld,
|
||||
Duration.standardSeconds(10),
|
||||
"Subj",
|
||||
"Body %1$s %2$s %3$s %4$s %5$s",
|
||||
"registry@test.com",
|
||||
"awesomeRegistry",
|
||||
Optional.ofNullable(retryCount),
|
||||
Optional.empty(),
|
||||
dnsQueue,
|
||||
@@ -150,6 +165,7 @@ public class PublishDnsUpdatesActionTest {
|
||||
lockHandler,
|
||||
clock,
|
||||
cloudTasksHelper.getTestCloudTasksUtils(),
|
||||
sendEmailUtils,
|
||||
response);
|
||||
}
|
||||
|
||||
@@ -385,6 +401,37 @@ public class PublishDnsUpdatesActionTest {
|
||||
assertThat(response.getStatus()).isEqualTo(SC_ACCEPTED);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDomainDnsUpdateRetriesExhausted_emailIsSent() {
|
||||
action =
|
||||
createAction("xn--q9jyb4c", ImmutableSet.of("example.xn--q9jyb4c"), ImmutableSet.of(), 10);
|
||||
doThrow(new RuntimeException()).when(dnsWriter).commit();
|
||||
action.run();
|
||||
ArgumentCaptor<EmailMessage> contentCaptor = ArgumentCaptor.forClass(EmailMessage.class);
|
||||
verify(emailService).sendEmail(contentCaptor.capture());
|
||||
EmailMessage emailMessage = contentCaptor.getValue();
|
||||
assertThat(emailMessage.subject()).isEqualTo("Subj");
|
||||
assertThat(emailMessage.body())
|
||||
.isEqualTo(
|
||||
"Body The Registrar example.xn--q9jyb4c domain awesomeRegistry registry@test.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHostDnsUpdateRetriesExhausted_emailIsSent() {
|
||||
action =
|
||||
createAction(
|
||||
"xn--q9jyb4c", ImmutableSet.of(), ImmutableSet.of("ns1.example.xn--q9jyb4c"), 10);
|
||||
doThrow(new RuntimeException()).when(dnsWriter).commit();
|
||||
action.run();
|
||||
ArgumentCaptor<EmailMessage> contentCaptor = ArgumentCaptor.forClass(EmailMessage.class);
|
||||
verify(emailService).sendEmail(contentCaptor.capture());
|
||||
EmailMessage emailMessage = contentCaptor.getValue();
|
||||
assertThat(emailMessage.subject()).isEqualTo("Subj");
|
||||
assertThat(emailMessage.body())
|
||||
.isEqualTo(
|
||||
"Body The Registrar ns1.example.xn--q9jyb4c host awesomeRegistry registry@test.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTaskMissingRetryHeaders_throwsException() {
|
||||
IllegalStateException thrown =
|
||||
|
||||
@@ -39,13 +39,12 @@ import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.secdns.DelegationSignerData;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@@ -76,8 +75,6 @@ public class DnsUpdateWriterTest {
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withCloudSql().withTaskQueue().build();
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
|
||||
@Mock private DnsMessageTransport mockResolver;
|
||||
@Captor private ArgumentCaptor<Update> updateCaptor;
|
||||
|
||||
@@ -87,8 +84,6 @@ public class DnsUpdateWriterTest {
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() throws Exception {
|
||||
inject.setStaticField(Ofy.class, "clock", clock);
|
||||
|
||||
createTld("tld");
|
||||
when(mockResolver.send(any(Update.class))).thenReturn(messageWithResponseCode(Rcode.NOERROR));
|
||||
|
||||
@@ -418,23 +413,23 @@ public class DnsUpdateWriterTest {
|
||||
assertThat(thrown).hasMessageThat().contains("SERVFAIL");
|
||||
}
|
||||
|
||||
private void assertThatUpdatedZoneIs(Update update, String zoneName) {
|
||||
Record[] zoneRecords = update.getSectionArray(Section.ZONE);
|
||||
assertThat(zoneRecords[0].getName().toString()).isEqualTo(zoneName);
|
||||
private static void assertThatUpdatedZoneIs(Update update, String zoneName) {
|
||||
List<Record> zoneRecords = update.getSection(Section.ZONE);
|
||||
assertThat(zoneRecords.get(0).getName().toString()).isEqualTo(zoneName);
|
||||
}
|
||||
|
||||
private void assertThatTotalUpdateSetsIs(Update update, int count) {
|
||||
private static void assertThatTotalUpdateSetsIs(Update update, int count) {
|
||||
assertThat(update.getSectionRRsets(Section.UPDATE)).hasSize(count);
|
||||
}
|
||||
|
||||
private void assertThatUpdateDeletes(Update update, String resourceName, int recordType) {
|
||||
private static void assertThatUpdateDeletes(Update update, String resourceName, int recordType) {
|
||||
ImmutableList<Record> deleted = findUpdateRecords(update, resourceName, recordType);
|
||||
// There's only an empty (i.e. "delete") record.
|
||||
assertThat(deleted.get(0).rdataToString()).hasLength(0);
|
||||
assertThat(deleted).hasSize(1);
|
||||
}
|
||||
|
||||
private void assertThatUpdateAdds(
|
||||
private static void assertThatUpdateAdds(
|
||||
Update update, String resourceName, int recordType, String... resourceData) {
|
||||
ArrayList<String> expectedData = new ArrayList<>();
|
||||
Collections.addAll(expectedData, resourceData);
|
||||
@@ -446,7 +441,7 @@ public class DnsUpdateWriterTest {
|
||||
assertThat(actualData).containsExactlyElementsIn(expectedData);
|
||||
}
|
||||
|
||||
private ImmutableList<Record> findUpdateRecords(
|
||||
private static ImmutableList<Record> findUpdateRecords(
|
||||
Update update, String resourceName, int recordType) {
|
||||
for (RRset set : update.getSectionRRsets(Section.UPDATE)) {
|
||||
if (set.getName().toString().equals(resourceName) && set.getType() == recordType) {
|
||||
@@ -460,7 +455,7 @@ public class DnsUpdateWriterTest {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
private Message messageWithResponseCode(int responseCode) {
|
||||
private static Message messageWithResponseCode(int responseCode) {
|
||||
Message message = new Message();
|
||||
message.getHeader().setOpcode(Opcode.UPDATE);
|
||||
message.getHeader().setFlag(Flags.QR);
|
||||
|
||||
@@ -33,16 +33,13 @@ import com.google.cloud.storage.contrib.nio.testing.LocalStorageHelper;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.net.MediaType;
|
||||
import google.registry.gcs.GcsUtils;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.model.tld.Registry.TldType;
|
||||
import google.registry.storage.drive.DriveConnection;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
@@ -51,8 +48,8 @@ import org.mockito.ArgumentCaptor;
|
||||
class ExportDomainListsActionTest {
|
||||
|
||||
private final GcsUtils gcsUtils = new GcsUtils(LocalStorageHelper.getOptions());
|
||||
private DriveConnection driveConnection = mock(DriveConnection.class);
|
||||
private ArgumentCaptor<byte[]> bytesExportedToDrive = ArgumentCaptor.forClass(byte[].class);
|
||||
private final DriveConnection driveConnection = mock(DriveConnection.class);
|
||||
private final ArgumentCaptor<byte[]> bytesExportedToDrive = ArgumentCaptor.forClass(byte[].class);
|
||||
private ExportDomainListsAction action;
|
||||
private final FakeClock clock = new FakeClock(DateTime.parse("2020-02-02T02:02:02Z"));
|
||||
|
||||
@@ -60,11 +57,6 @@ class ExportDomainListsActionTest {
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withCloudSql().withLocalModules().withTaskQueue().build();
|
||||
|
||||
@Order(Order.DEFAULT - 1)
|
||||
@RegisterExtension
|
||||
public final InjectExtension inject =
|
||||
new InjectExtension().withStaticFieldOverride(Ofy.class, "clock", clock);
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
createTld("tld");
|
||||
|
||||
@@ -42,7 +42,6 @@ import google.registry.request.Response;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.FakeSleeper;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import google.registry.util.Retrier;
|
||||
import java.io.IOException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -59,8 +58,6 @@ public class SyncGroupMembersActionTest {
|
||||
@RegisterExtension
|
||||
public final AppEngineExtension appEngine = AppEngineExtension.builder().withCloudSql().build();
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
|
||||
private final DirectoryGroupsConnection connection = mock(DirectoryGroupsConnection.class);
|
||||
private final Response response = mock(Response.class);
|
||||
|
||||
@@ -76,8 +73,7 @@ public class SyncGroupMembersActionTest {
|
||||
@Test
|
||||
void test_getGroupEmailAddressForContactType_convertsToLowercase() {
|
||||
assertThat(
|
||||
getGroupEmailAddressForContactType(
|
||||
"SomeRegistrar", RegistrarPoc.Type.ADMIN, "domain-registry.example"))
|
||||
getGroupEmailAddressForContactType("SomeRegistrar", ADMIN, "domain-registry.example"))
|
||||
.isEqualTo("someregistrar-primary-contacts@domain-registry.example");
|
||||
}
|
||||
|
||||
|
||||
@@ -35,14 +35,12 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.model.common.Cursor;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarAddress;
|
||||
import google.registry.model.registrar.RegistrarPoc;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -60,8 +58,6 @@ public class SyncRegistrarsSheetTest {
|
||||
@RegisterExtension
|
||||
public final AppEngineExtension appEngine = AppEngineExtension.builder().withCloudSql().build();
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
|
||||
@Captor private ArgumentCaptor<ImmutableList<ImmutableMap<String, String>>> rowsCaptor;
|
||||
@Mock private SheetSynchronizer sheetSynchronizer;
|
||||
|
||||
@@ -76,7 +72,6 @@ public class SyncRegistrarsSheetTest {
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
inject.setStaticField(Ofy.class, "clock", clock);
|
||||
createTld("example");
|
||||
// Remove Registrar entities created by AppEngineExtension (and RegistrarContact's, for jpa).
|
||||
// We don't do this for ofy because ofy's loadAllOf() can't be called in a transaction but
|
||||
@@ -215,7 +210,7 @@ public class SyncRegistrarsSheetTest {
|
||||
+ "Phone number and email visible in domain WHOIS query as "
|
||||
+ "Registrar Abuse contact info: No\n"
|
||||
+ "Registrar-Console access: No\n"
|
||||
+ "\n"
|
||||
+ '\n'
|
||||
+ "John Doe\n"
|
||||
+ "john.doe@example.tld\n"
|
||||
+ "Tel: +1.1234567890\n"
|
||||
|
||||
@@ -31,13 +31,11 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import google.registry.flows.EppTestComponent.FakesAndMocksModule;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.monitoring.whitebox.EppMetric;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.EppLoader;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.FakeHttpSession;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -52,14 +50,11 @@ class EppPointInTimeTest {
|
||||
final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withCloudSql().withClock(clock).withTaskQueue().build();
|
||||
|
||||
@RegisterExtension final InjectExtension inject = new InjectExtension();
|
||||
|
||||
private EppLoader eppLoader;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
createTld("tld");
|
||||
inject.setStaticField(Ofy.class, "clock", clock);
|
||||
}
|
||||
|
||||
private void runFlow() throws Exception {
|
||||
|
||||
@@ -36,7 +36,6 @@ import google.registry.model.billing.BillingEvent.Reason;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.eppcommon.EppXmlTransformer;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.reporting.HistoryEntry.Type;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.monitoring.whitebox.EppMetric;
|
||||
@@ -44,7 +43,6 @@ import google.registry.persistence.VKey;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.FakeHttpSession;
|
||||
import google.registry.testing.FakeResponse;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import google.registry.util.ProxyHttpHeaders;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@@ -52,16 +50,12 @@ import java.util.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
import org.joda.money.Money;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
public class EppTestCase {
|
||||
|
||||
private static final MediaType APPLICATION_EPP_XML_UTF8 =
|
||||
MediaType.create("application", "epp+xml").withCharset(UTF_8);
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
|
||||
protected final FakeClock clock = new FakeClock();
|
||||
|
||||
private SessionMetadata sessionMetadata;
|
||||
@@ -69,12 +63,6 @@ public class EppTestCase {
|
||||
private EppMetric.Builder eppMetricBuilder;
|
||||
private boolean isSuperuser;
|
||||
|
||||
@BeforeEach
|
||||
public void beforeEachEppTestCase() {
|
||||
// For transactional flows
|
||||
inject.setStaticField(Ofy.class, "clock", clock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the transport credentials.
|
||||
*
|
||||
@@ -92,14 +80,14 @@ public class EppTestCase {
|
||||
|
||||
public class CommandAsserter {
|
||||
private final String inputFilename;
|
||||
private @Nullable final Map<String, String> inputSubstitutions;
|
||||
@Nullable private final Map<String, String> inputSubstitutions;
|
||||
private DateTime now;
|
||||
|
||||
private CommandAsserter(
|
||||
String inputFilename, @Nullable Map<String, String> inputSubstitutions) {
|
||||
this.inputFilename = inputFilename;
|
||||
this.inputSubstitutions = inputSubstitutions;
|
||||
this.now = clock.nowUtc();
|
||||
now = clock.nowUtc();
|
||||
}
|
||||
|
||||
public CommandAsserter atTime(DateTime now) {
|
||||
@@ -121,9 +109,88 @@ public class EppTestCase {
|
||||
inputFilename, inputSubstitutions, outputFilename, outputSubstitutions, now);
|
||||
}
|
||||
|
||||
public String hasSuccessfulLogin() throws Exception {
|
||||
return assertLoginCommandAndResponse(inputFilename, inputSubstitutions, null, clock.nowUtc());
|
||||
public void hasSuccessfulLogin() throws Exception {
|
||||
assertLoginCommandAndResponse(inputFilename, inputSubstitutions, null, clock.nowUtc());
|
||||
}
|
||||
|
||||
private void assertLoginCommandAndResponse(
|
||||
String inputFilename,
|
||||
@Nullable Map<String, String> inputSubstitutions,
|
||||
@Nullable Map<String, String> outputSubstitutions,
|
||||
DateTime now)
|
||||
throws Exception {
|
||||
String outputFilename = "generic_success_response.xml";
|
||||
clock.setTo(now);
|
||||
String input = loadFile(EppTestCase.class, inputFilename, inputSubstitutions);
|
||||
String expectedOutput = loadFile(EppTestCase.class, outputFilename, outputSubstitutions);
|
||||
setUpSession();
|
||||
FakeResponse response = executeXmlCommand(input);
|
||||
|
||||
// Check that the logged-in header was added to the response
|
||||
assertThat(response.getHeaders())
|
||||
.isEqualTo(ImmutableMap.of(ProxyHttpHeaders.LOGGED_IN, "true"));
|
||||
|
||||
verifyAndReturnOutput(response.getPayload(), expectedOutput, inputFilename, outputFilename);
|
||||
}
|
||||
|
||||
private String assertCommandAndResponse(
|
||||
String inputFilename,
|
||||
@Nullable Map<String, String> inputSubstitutions,
|
||||
String outputFilename,
|
||||
@Nullable Map<String, String> outputSubstitutions,
|
||||
DateTime now)
|
||||
throws Exception {
|
||||
clock.setTo(now);
|
||||
String input = loadFile(EppTestCase.class, inputFilename, inputSubstitutions);
|
||||
String expectedOutput = loadFile(EppTestCase.class, outputFilename, outputSubstitutions);
|
||||
setUpSession();
|
||||
FakeResponse response = executeXmlCommand(input);
|
||||
|
||||
// Checks that the Logged-In header is not in the response. If testing the login command, use
|
||||
// assertLoginCommandAndResponse instead of this method.
|
||||
assertThat(response.getHeaders()).doesNotContainEntry(ProxyHttpHeaders.LOGGED_IN, "true");
|
||||
|
||||
return verifyAndReturnOutput(
|
||||
response.getPayload(), expectedOutput, inputFilename, outputFilename);
|
||||
}
|
||||
}
|
||||
|
||||
private void setUpSession() {
|
||||
if (sessionMetadata == null) {
|
||||
sessionMetadata =
|
||||
new HttpSessionMetadata(new FakeHttpSession()) {
|
||||
@Override
|
||||
public void invalidate() {
|
||||
// When a session is invalidated, reset the sessionMetadata field.
|
||||
super.invalidate();
|
||||
sessionMetadata = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private FakeResponse executeXmlCommand(String inputXml) {
|
||||
EppRequestHandler handler = new EppRequestHandler();
|
||||
FakeResponse response = new FakeResponse();
|
||||
handler.response = response;
|
||||
FakesAndMocksModule fakesAndMocksModule = FakesAndMocksModule.create(clock);
|
||||
eppMetricBuilder = fakesAndMocksModule.getMetricBuilder();
|
||||
handler.eppController =
|
||||
DaggerEppTestComponent.builder()
|
||||
.fakesAndMocksModule(fakesAndMocksModule)
|
||||
.build()
|
||||
.startRequest()
|
||||
.eppController();
|
||||
handler.executeEpp(
|
||||
sessionMetadata,
|
||||
credentials,
|
||||
EppRequestSource.UNIT_TEST,
|
||||
false, // Not dryRun.
|
||||
isSuperuser,
|
||||
inputXml.getBytes(UTF_8));
|
||||
assertThat(response.getStatus()).isEqualTo(SC_OK);
|
||||
assertThat(response.getContentType()).isEqualTo(APPLICATION_EPP_XML_UTF8);
|
||||
return response;
|
||||
}
|
||||
|
||||
protected CommandAsserter assertThatCommand(String inputFilename) {
|
||||
@@ -148,63 +215,7 @@ public class EppTestCase {
|
||||
assertThatCommand("logout.xml").hasResponse("logout_response.xml");
|
||||
}
|
||||
|
||||
private String assertLoginCommandAndResponse(
|
||||
String inputFilename,
|
||||
@Nullable Map<String, String> inputSubstitutions,
|
||||
@Nullable Map<String, String> outputSubstitutions,
|
||||
DateTime now)
|
||||
throws Exception {
|
||||
String outputFilename = "generic_success_response.xml";
|
||||
clock.setTo(now);
|
||||
String input = loadFile(EppTestCase.class, inputFilename, inputSubstitutions);
|
||||
String expectedOutput = loadFile(EppTestCase.class, outputFilename, outputSubstitutions);
|
||||
setUpSession();
|
||||
FakeResponse response = executeXmlCommand(input);
|
||||
|
||||
// Check that the logged-in header was added to the response
|
||||
assertThat(response.getHeaders())
|
||||
.isEqualTo(ImmutableMap.of(ProxyHttpHeaders.LOGGED_IN, "true"));
|
||||
|
||||
return verifyAndReturnOutput(
|
||||
response.getPayload(), expectedOutput, inputFilename, outputFilename);
|
||||
}
|
||||
|
||||
private String assertCommandAndResponse(
|
||||
String inputFilename,
|
||||
@Nullable Map<String, String> inputSubstitutions,
|
||||
String outputFilename,
|
||||
@Nullable Map<String, String> outputSubstitutions,
|
||||
DateTime now)
|
||||
throws Exception {
|
||||
clock.setTo(now);
|
||||
String input = loadFile(EppTestCase.class, inputFilename, inputSubstitutions);
|
||||
String expectedOutput = loadFile(EppTestCase.class, outputFilename, outputSubstitutions);
|
||||
setUpSession();
|
||||
FakeResponse response = executeXmlCommand(input);
|
||||
|
||||
// Checks that the Logged-In header is not in the response. If testing the login command, use
|
||||
// assertLoginCommandAndResponse instead of this method.
|
||||
assertThat(response.getHeaders()).doesNotContainEntry(ProxyHttpHeaders.LOGGED_IN, "true");
|
||||
|
||||
return verifyAndReturnOutput(
|
||||
response.getPayload(), expectedOutput, inputFilename, outputFilename);
|
||||
}
|
||||
|
||||
private void setUpSession() {
|
||||
if (sessionMetadata == null) {
|
||||
sessionMetadata =
|
||||
new HttpSessionMetadata(new FakeHttpSession()) {
|
||||
@Override
|
||||
public void invalidate() {
|
||||
// When a session is invalidated, reset the sessionMetadata field.
|
||||
super.invalidate();
|
||||
EppTestCase.this.sessionMetadata = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private String verifyAndReturnOutput(
|
||||
private static String verifyAndReturnOutput(
|
||||
String actualOutput, String expectedOutput, String inputFilename, String outputFilename)
|
||||
throws Exception {
|
||||
// Run the resulting xml through the unmarshaller to verify that it was valid.
|
||||
@@ -219,30 +230,6 @@ public class EppTestCase {
|
||||
return actualOutput;
|
||||
}
|
||||
|
||||
private FakeResponse executeXmlCommand(String inputXml) {
|
||||
EppRequestHandler handler = new EppRequestHandler();
|
||||
FakeResponse response = new FakeResponse();
|
||||
handler.response = response;
|
||||
FakesAndMocksModule fakesAndMocksModule = FakesAndMocksModule.create(clock);
|
||||
eppMetricBuilder = fakesAndMocksModule.getMetricBuilder();
|
||||
handler.eppController =
|
||||
DaggerEppTestComponent.builder()
|
||||
.fakesAndMocksModule(fakesAndMocksModule)
|
||||
.build()
|
||||
.startRequest()
|
||||
.eppController();
|
||||
handler.executeEpp(
|
||||
sessionMetadata,
|
||||
credentials,
|
||||
EppRequestSource.UNIT_TEST,
|
||||
false, // Not dryRun.
|
||||
isSuperuser,
|
||||
inputXml.getBytes(UTF_8));
|
||||
assertThat(response.getStatus()).isEqualTo(SC_OK);
|
||||
assertThat(response.getContentType()).isEqualTo(APPLICATION_EPP_XML_UTF8);
|
||||
return response;
|
||||
}
|
||||
|
||||
EppMetric getRecordedEppMetric() {
|
||||
return eppMetricBuilder.build();
|
||||
}
|
||||
|
||||
@@ -39,7 +39,6 @@ import google.registry.model.domain.GracePeriod;
|
||||
import google.registry.model.eppcommon.ProtocolDefinition;
|
||||
import google.registry.model.eppinput.EppInput;
|
||||
import google.registry.model.eppoutput.EppOutput;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.reporting.HistoryEntryDao;
|
||||
import google.registry.monitoring.whitebox.EppMetric;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
@@ -48,7 +47,6 @@ import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.EppLoader;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.FakeHttpSession;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import google.registry.testing.TestDataHelper;
|
||||
import google.registry.util.TypeUtils.TypeInstantiator;
|
||||
import google.registry.xml.ValidationMode;
|
||||
@@ -58,7 +56,6 @@ import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/**
|
||||
@@ -89,13 +86,6 @@ public abstract class FlowTestCase<F extends Flow> {
|
||||
|
||||
private EppMetric.Builder eppMetricBuilder;
|
||||
|
||||
// Set the clock for transactional flows. We have to order this before the AppEngineExtension
|
||||
// which populates data.
|
||||
@Order(value = Order.DEFAULT - 1)
|
||||
@RegisterExtension
|
||||
final InjectExtension inject =
|
||||
new InjectExtension().withStaticFieldOverride(Ofy.class, "clock", clock);
|
||||
|
||||
@RegisterExtension
|
||||
final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withClock(clock).withCloudSql().withTaskQueue().build();
|
||||
@@ -171,13 +161,13 @@ public abstract class FlowTestCase<F extends Flow> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to facilitate comparison of maps of GracePeriods to BillingEvents. This takes a map of
|
||||
* GracePeriods to BillingEvents and returns a map of the same entries that ignores the keys
|
||||
* on the grace periods and the IDs on the billing events (by setting them all to the same dummy
|
||||
* Helper to facilitate comparison of maps of GracePeriods to BillingEvents. This takes a map of
|
||||
* GracePeriods to BillingEvents and returns a map of the same entries that ignores the keys on
|
||||
* the grace periods and the IDs on the billing events (by setting them all to the same dummy
|
||||
* values), since they will vary between instantiations even when the other data is the same.
|
||||
*/
|
||||
private ImmutableMap<GracePeriod, BillingEvent>
|
||||
canonicalizeGracePeriods(ImmutableMap<GracePeriod, ? extends BillingEvent> gracePeriods) {
|
||||
private static ImmutableMap<GracePeriod, BillingEvent> canonicalizeGracePeriods(
|
||||
ImmutableMap<GracePeriod, ? extends BillingEvent> gracePeriods) {
|
||||
ImmutableMap.Builder<GracePeriod, BillingEvent> builder = new ImmutableMap.Builder<>();
|
||||
for (Map.Entry<GracePeriod, ? extends BillingEvent> entry : gracePeriods.entrySet()) {
|
||||
builder.put(
|
||||
@@ -210,7 +200,7 @@ public abstract class FlowTestCase<F extends Flow> {
|
||||
* keys match the expected map of grace periods to billing events. For the expected map, the keys
|
||||
* on the grace periods and IDs on the billing events are ignored.
|
||||
*/
|
||||
protected void assertGracePeriods(
|
||||
protected static void assertGracePeriods(
|
||||
Iterable<GracePeriod> actual, ImmutableMap<GracePeriod, ? extends BillingEvent> expected) {
|
||||
assertThat(canonicalizeGracePeriods(Maps.toMap(actual, FlowTestCase::expandGracePeriod)))
|
||||
.isEqualTo(canonicalizeGracePeriods(expected));
|
||||
@@ -258,7 +248,7 @@ public abstract class FlowTestCase<F extends Flow> {
|
||||
return runFlow(CommitMode.LIVE, UserPrivileges.NORMAL);
|
||||
}
|
||||
|
||||
/** Shortcut to call {@link #runFlow(CommitMode, UserPrivileges)} as super user and live run. */
|
||||
/** Shortcut to call {@link #runFlow(CommitMode, UserPrivileges)} as superuser and live run. */
|
||||
protected EppOutput runFlowAsSuperuser() throws Exception {
|
||||
return runFlow(CommitMode.LIVE, UserPrivileges.SUPERUSER);
|
||||
}
|
||||
|
||||
@@ -82,6 +82,7 @@ import google.registry.flows.ResourceFlowTestCase;
|
||||
import google.registry.flows.domain.DomainCreateFlow.AnchorTenantCreatePeriodException;
|
||||
import google.registry.flows.domain.DomainCreateFlow.MustHaveSignedMarksInCurrentPhaseException;
|
||||
import google.registry.flows.domain.DomainCreateFlow.NoGeneralRegistrationsInCurrentPhaseException;
|
||||
import google.registry.flows.domain.DomainCreateFlow.NoTrademarkedRegistrationsBeforeSunriseException;
|
||||
import google.registry.flows.domain.DomainCreateFlow.RenewalPriceInfo;
|
||||
import google.registry.flows.domain.DomainCreateFlow.SignedMarksOnlyDuringSunriseException;
|
||||
import google.registry.flows.domain.DomainFlowTmchUtils.FoundMarkExpiredException;
|
||||
@@ -2734,7 +2735,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_quietPeriod_skipTldCheckWithToken() throws Exception {
|
||||
void testSuccess_quietPeriod_skipTldStateCheckWithToken() throws Exception {
|
||||
AllocationToken token =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
@@ -2813,7 +2814,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
.build());
|
||||
persistContactsAndHosts();
|
||||
setEppInput("domain_create_allocationtoken_claims.xml");
|
||||
assertThrows(NoGeneralRegistrationsInCurrentPhaseException.class, this::runFlow);
|
||||
assertThrows(NoTrademarkedRegistrationsBeforeSunriseException.class, this::runFlow);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -2844,4 +2845,285 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
runFlow();
|
||||
assertSuccessfulCreate("tld", ImmutableSet.of(), allocationToken);
|
||||
}
|
||||
|
||||
// ________________________________
|
||||
// Anchor tenant in quiet period before sunrise:
|
||||
// Only non-trademarked domains are allowed.
|
||||
// ________________________________
|
||||
@Test
|
||||
void testSuccess_anchorTenant_quietPeriodBeforeSunrise_nonTrademarked_viaToken()
|
||||
throws Exception {
|
||||
createTld("tld", QUIET_PERIOD);
|
||||
AllocationToken token =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(SINGLE_USE)
|
||||
.setDomainName("example.tld")
|
||||
.setRegistrationBehavior(RegistrationBehavior.ANCHOR_TENANT)
|
||||
.build());
|
||||
setEppInput(
|
||||
"domain_create_allocationtoken.xml",
|
||||
ImmutableMap.of("DOMAIN", "example.tld", "YEARS", "2"));
|
||||
persistContactsAndHosts();
|
||||
runFlow();
|
||||
assertSuccessfulCreate("tld", ImmutableSet.of(ANCHOR_TENANT), token);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_anchorTenant_quietPeriodBeforeSunrise_trademarked_withoutClaims_viaToken() {
|
||||
createTld("tld", QUIET_PERIOD);
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(SINGLE_USE)
|
||||
.setDomainName("test-validate.tld")
|
||||
.setRegistrationBehavior(RegistrationBehavior.ANCHOR_TENANT)
|
||||
.build());
|
||||
setEppInput(
|
||||
"domain_create_allocationtoken.xml",
|
||||
ImmutableMap.of("DOMAIN", "test-validate.tld", "YEARS", "2"));
|
||||
persistContactsAndHosts();
|
||||
assertThrows(NoTrademarkedRegistrationsBeforeSunriseException.class, this::runFlow);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_anchorTenant_quietPeriodBeforeSunrise_trademarked_withClaims_viaToken() {
|
||||
createTld("tld", QUIET_PERIOD);
|
||||
persistResource(
|
||||
allocationToken
|
||||
.asBuilder()
|
||||
.setDomainName("example-one.tld")
|
||||
.setRegistrationBehavior(RegistrationBehavior.ANCHOR_TENANT)
|
||||
.build());
|
||||
setEppInput("domain_create_allocationtoken_claims.xml");
|
||||
persistContactsAndHosts();
|
||||
assertThrows(NoTrademarkedRegistrationsBeforeSunriseException.class, this::runFlow);
|
||||
}
|
||||
|
||||
// ________________________________
|
||||
// Anchor tenant in sunrise:
|
||||
// Non-trademarked domains and trademarked domains with signed marks are allowed
|
||||
// ________________________________
|
||||
@Test
|
||||
void testSuccess_anchorTenant_inSunrise_nonTrademarked_viaToken() throws Exception {
|
||||
createTld("tld", START_DATE_SUNRISE);
|
||||
AllocationToken token =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(SINGLE_USE)
|
||||
.setDomainName("example.tld")
|
||||
.setRegistrationBehavior(RegistrationBehavior.ANCHOR_TENANT)
|
||||
.build());
|
||||
persistContactsAndHosts();
|
||||
setEppInput(
|
||||
"domain_create_allocationtoken.xml",
|
||||
ImmutableMap.of("DOMAIN", "example.tld", "YEARS", "2"));
|
||||
runFlow();
|
||||
assertSuccessfulCreate("tld", ImmutableSet.of(ANCHOR_TENANT), token);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_anchorTenant_inSunrise_trademarked_withSignedMark_viaToken() throws Exception {
|
||||
createTld("tld", START_DATE_SUNRISE);
|
||||
clock.setTo(DateTime.parse("2014-09-09T09:09:09Z"));
|
||||
setEppInput(
|
||||
"domain_create_registration_encoded_signed_mark_allocationtoken.xml",
|
||||
ImmutableMap.of("DOMAIN", "test-validate.tld"));
|
||||
persistResource(
|
||||
allocationToken
|
||||
.asBuilder()
|
||||
.setRegistrationBehavior(RegistrationBehavior.ANCHOR_TENANT)
|
||||
.setDomainName("test-validate.tld")
|
||||
.build());
|
||||
persistContactsAndHosts();
|
||||
runFlow();
|
||||
assertSuccessfulCreate("tld", ImmutableSet.of(SUNRISE, ANCHOR_TENANT), allocationToken);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_anchorTenant_inSunrise_trademarked_withoutSignedMark_viaToken() {
|
||||
createTld("tld", START_DATE_SUNRISE);
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setTokenType(SINGLE_USE)
|
||||
.setToken("abc123")
|
||||
.setDomainName("example-one.tld")
|
||||
.setRegistrationBehavior(RegistrationBehavior.ANCHOR_TENANT)
|
||||
.build());
|
||||
persistContactsAndHosts();
|
||||
assertThrows(MustHaveSignedMarksInCurrentPhaseException.class, this::runFlow);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_anchorTenant_inSunrise_trademarked_withoutSignedMark_withClaims_viaToken() {
|
||||
createTld("tld", START_DATE_SUNRISE);
|
||||
persistResource(
|
||||
allocationToken
|
||||
.asBuilder()
|
||||
.setDomainName("example-one.tld")
|
||||
.setRegistrationBehavior(RegistrationBehavior.ANCHOR_TENANT)
|
||||
.build());
|
||||
setEppInput("domain_create_allocationtoken_claims.xml");
|
||||
persistContactsAndHosts();
|
||||
assertThrows(MustHaveSignedMarksInCurrentPhaseException.class, this::runFlow);
|
||||
}
|
||||
|
||||
// ________________________________
|
||||
// Anchor tenant in a post-sunrise quiet period:
|
||||
// Non-trademarked domains and trademarked domains with claims are allowed.
|
||||
// ________________________________
|
||||
@Test
|
||||
void testSuccess_anchorTenant_quietPeriodAfterSunrise_nonTrademarked_viaToken() throws Exception {
|
||||
persistResource(
|
||||
Registry.get("tld")
|
||||
.asBuilder()
|
||||
.setTldStateTransitions(
|
||||
ImmutableSortedMap.of(
|
||||
START_OF_TIME,
|
||||
QUIET_PERIOD,
|
||||
clock.nowUtc().minusYears(1),
|
||||
START_DATE_SUNRISE,
|
||||
clock.nowUtc().minusMonths(1),
|
||||
QUIET_PERIOD))
|
||||
.build());
|
||||
AllocationToken token =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(SINGLE_USE)
|
||||
.setRegistrationBehavior(RegistrationBehavior.ANCHOR_TENANT)
|
||||
.setDomainName("example.tld")
|
||||
.build());
|
||||
persistContactsAndHosts();
|
||||
setEppInput(
|
||||
"domain_create_allocationtoken.xml",
|
||||
ImmutableMap.of("DOMAIN", "example.tld", "YEARS", "2"));
|
||||
runFlow();
|
||||
assertSuccessfulCreate("tld", ImmutableSet.of(ANCHOR_TENANT), token);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_anchorTenant_quietPeriodAfterSunrise_trademarked_withClaims_viaToken()
|
||||
throws Exception {
|
||||
persistResource(
|
||||
Registry.get("tld")
|
||||
.asBuilder()
|
||||
.setTldStateTransitions(
|
||||
ImmutableSortedMap.of(
|
||||
START_OF_TIME,
|
||||
QUIET_PERIOD,
|
||||
clock.nowUtc().minusYears(1),
|
||||
START_DATE_SUNRISE,
|
||||
clock.nowUtc().minusMonths(1),
|
||||
QUIET_PERIOD))
|
||||
.build());
|
||||
persistResource(
|
||||
allocationToken
|
||||
.asBuilder()
|
||||
.setDomainName("example-one.tld")
|
||||
.setRegistrationBehavior(RegistrationBehavior.ANCHOR_TENANT)
|
||||
.build());
|
||||
setEppInput("domain_create_allocationtoken_claims.xml");
|
||||
persistContactsAndHosts();
|
||||
runFlow();
|
||||
assertSuccessfulCreate("tld", ImmutableSet.of(ANCHOR_TENANT), allocationToken);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_anchorTenant_quietPeriodAfterSunrise_trademarked_withoutClaims_viaToken() {
|
||||
persistResource(
|
||||
Registry.get("tld")
|
||||
.asBuilder()
|
||||
.setTldStateTransitions(
|
||||
ImmutableSortedMap.of(
|
||||
START_OF_TIME,
|
||||
QUIET_PERIOD,
|
||||
clock.nowUtc().minusYears(1),
|
||||
START_DATE_SUNRISE,
|
||||
clock.nowUtc().minusMonths(1),
|
||||
QUIET_PERIOD))
|
||||
.build());
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(SINGLE_USE)
|
||||
.setDomainName("example-one.tld")
|
||||
.setRegistrationBehavior(RegistrationBehavior.ANCHOR_TENANT)
|
||||
.build());
|
||||
persistContactsAndHosts();
|
||||
setEppInput(
|
||||
"domain_create_allocationtoken.xml",
|
||||
ImmutableMap.of("DOMAIN", "example-one.tld", "YEARS", "2"));
|
||||
assertThrows(MissingClaimsNoticeException.class, this::runFlow);
|
||||
}
|
||||
|
||||
// ________________________________
|
||||
// Anchor tenant in GA:
|
||||
// Non-trademarked domains and trademarked domains with claims are allowed.
|
||||
// ________________________________
|
||||
@Test
|
||||
void testSuccess_anchorTenant_ga_nonTrademarked_viaToken() throws Exception {
|
||||
AllocationToken token =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(SINGLE_USE)
|
||||
.setRegistrationBehavior(RegistrationBehavior.ANCHOR_TENANT)
|
||||
.setDomainName("example.tld")
|
||||
.build());
|
||||
persistContactsAndHosts();
|
||||
setEppInput(
|
||||
"domain_create_allocationtoken.xml",
|
||||
ImmutableMap.of("DOMAIN", "example.tld", "YEARS", "2"));
|
||||
runFlow();
|
||||
assertSuccessfulCreate("tld", ImmutableSet.of(ANCHOR_TENANT), token);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_anchorTenant_ga_trademarked_withClaims_viaToken() throws Exception {
|
||||
persistResource(
|
||||
allocationToken
|
||||
.asBuilder()
|
||||
.setDomainName("example-one.tld")
|
||||
.setRegistrationBehavior(RegistrationBehavior.ANCHOR_TENANT)
|
||||
.build());
|
||||
setEppInput("domain_create_allocationtoken_claims.xml");
|
||||
persistContactsAndHosts();
|
||||
runFlow();
|
||||
assertSuccessfulCreate("tld", ImmutableSet.of(ANCHOR_TENANT), allocationToken);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_anchorTenant_ga_trademarked_withoutClaims_viaToken() {
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(SINGLE_USE)
|
||||
.setDomainName("example-one.tld")
|
||||
.setRegistrationBehavior(RegistrationBehavior.ANCHOR_TENANT)
|
||||
.build());
|
||||
persistContactsAndHosts();
|
||||
setEppInput(
|
||||
"domain_create_allocationtoken.xml",
|
||||
ImmutableMap.of("DOMAIN", "example-one.tld", "YEARS", "2"));
|
||||
assertThrows(MissingClaimsNoticeException.class, this::runFlow);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_anchorTenant_mismatchedName_viaToken() throws Exception {
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(SINGLE_USE)
|
||||
.setRegistrationBehavior(RegistrationBehavior.ANCHOR_TENANT)
|
||||
.setDomainName("example.tld")
|
||||
.build());
|
||||
persistContactsAndHosts();
|
||||
setEppInput(
|
||||
"domain_create_allocationtoken.xml",
|
||||
ImmutableMap.of("DOMAIN", "example-one.tld", "YEARS", "2"));
|
||||
assertThrows(AllocationTokenNotValidForDomainException.class, this::runFlow);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,12 +16,9 @@ package google.registry.model;
|
||||
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Base class of all unit tests for entities which are persisted to Datastore via Objectify. */
|
||||
@@ -41,8 +38,6 @@ public abstract class EntityTestCase {
|
||||
|
||||
@RegisterExtension public final AppEngineExtension appEngine;
|
||||
|
||||
@RegisterExtension public InjectExtension inject = new InjectExtension();
|
||||
|
||||
protected EntityTestCase() {
|
||||
this(JpaEntityCoverageCheck.DISABLED);
|
||||
}
|
||||
@@ -55,9 +50,4 @@ public abstract class EntityTestCase {
|
||||
.withClock(fakeClock)
|
||||
.build();
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void injectClock() {
|
||||
inject.setStaticField(Ofy.class, "clock", fakeClock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,10 +23,8 @@ import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@@ -42,12 +40,9 @@ class EppResourceUtilsTest {
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withCloudSql().withClock(clock).withTaskQueue().build();
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
createTld("tld");
|
||||
inject.setStaticField(Ofy.class, "clock", clock);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -49,21 +49,30 @@ public class ConsoleRoleDefinitionsTest {
|
||||
// Note: we can't use Truth's IterableSubject to check all the subset/superset restrictions
|
||||
// because it is generic to iterables and doesn't know about sets.
|
||||
assertThat(
|
||||
ConsoleRoleDefinitions.SUPPORT_LEAD_PERMISSIONS.containsAll(
|
||||
ConsoleRoleDefinitions.SUPPORT_AGENT_PERMISSIONS))
|
||||
ConsoleRoleDefinitions.ACCOUNT_MANAGER_WITH_REGISTRY_LOCK_PERMISSIONS.containsAll(
|
||||
ConsoleRoleDefinitions.ACCOUNT_MANAGER_PERMISSIONS))
|
||||
.isTrue();
|
||||
assertThat(
|
||||
ConsoleRoleDefinitions.SUPPORT_AGENT_PERMISSIONS.containsAll(
|
||||
ConsoleRoleDefinitions.SUPPORT_LEAD_PERMISSIONS))
|
||||
ConsoleRoleDefinitions.ACCOUNT_MANAGER_PERMISSIONS.containsAll(
|
||||
ConsoleRoleDefinitions.ACCOUNT_MANAGER_WITH_REGISTRY_LOCK_PERMISSIONS))
|
||||
.isFalse();
|
||||
|
||||
assertThat(
|
||||
ConsoleRoleDefinitions.SUPPORT_LEAD_PERMISSIONS.containsAll(
|
||||
ConsoleRoleDefinitions.SUPPORT_AGENT_PERMISSIONS))
|
||||
ConsoleRoleDefinitions.TECH_CONTACT_PERMISSIONS.containsAll(
|
||||
ConsoleRoleDefinitions.ACCOUNT_MANAGER_WITH_REGISTRY_LOCK_PERMISSIONS))
|
||||
.isTrue();
|
||||
assertThat(
|
||||
ConsoleRoleDefinitions.SUPPORT_AGENT_PERMISSIONS.containsAll(
|
||||
ConsoleRoleDefinitions.SUPPORT_LEAD_PERMISSIONS))
|
||||
ConsoleRoleDefinitions.ACCOUNT_MANAGER_WITH_REGISTRY_LOCK_PERMISSIONS.containsAll(
|
||||
ConsoleRoleDefinitions.TECH_CONTACT_PERMISSIONS))
|
||||
.isFalse();
|
||||
|
||||
assertThat(
|
||||
ConsoleRoleDefinitions.PRIMARY_CONTACT_PERMISSIONS.containsAll(
|
||||
ConsoleRoleDefinitions.TECH_CONTACT_PERMISSIONS))
|
||||
.isTrue();
|
||||
assertThat(
|
||||
ConsoleRoleDefinitions.TECH_CONTACT_PERMISSIONS.containsAll(
|
||||
ConsoleRoleDefinitions.PRIMARY_CONTACT_PERMISSIONS))
|
||||
.isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,4 +58,33 @@ public class UserTest {
|
||||
builder.setUserRoles(new UserRoles.Builder().build());
|
||||
builder.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRegistryLockPassword() {
|
||||
assertThat(
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() ->
|
||||
new User.Builder()
|
||||
.setUserRoles(new UserRoles.Builder().build())
|
||||
.setRegistryLockPassword("foobar")))
|
||||
.hasMessageThat()
|
||||
.isEqualTo("User has no registry lock permission");
|
||||
|
||||
User user =
|
||||
new User.Builder()
|
||||
.setGaiaId("gaiaId")
|
||||
.setEmailAddress("email@email.com")
|
||||
.setUserRoles(new UserRoles.Builder().setGlobalRole(GlobalRole.FTE).build())
|
||||
.build();
|
||||
assertThat(user.hasRegistryLockPassword()).isFalse();
|
||||
|
||||
user = user.asBuilder().setRegistryLockPassword("foobar").build();
|
||||
assertThat(user.hasRegistryLockPassword()).isTrue();
|
||||
assertThat(user.verifyRegistryLockPassword("foobar")).isTrue();
|
||||
|
||||
user = user.asBuilder().removeRegistryLockPassword().build();
|
||||
assertThat(user.hasRegistryLockPassword()).isFalse();
|
||||
assertThat(user.verifyRegistryLockPassword("foobar")).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,14 +28,12 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.domain.Period;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.poll.PollMessageExternalKeyConverter.PollMessageExternalKeyParseException;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -47,14 +45,11 @@ public class PollMessageExternalKeyConverterTest {
|
||||
@RegisterExtension
|
||||
public final AppEngineExtension appEngine = AppEngineExtension.builder().withCloudSql().build();
|
||||
|
||||
@RegisterExtension public InjectExtension inject = new InjectExtension();
|
||||
|
||||
private HistoryEntry historyEntry;
|
||||
private FakeClock clock = new FakeClock(DateTime.parse("2007-07-07T01:01:01Z"));
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
inject.setStaticField(Ofy.class, "clock", clock);
|
||||
createTld("foobar");
|
||||
historyEntry =
|
||||
persistResource(
|
||||
|
||||
@@ -43,7 +43,6 @@ import google.registry.model.tld.Registry.TldState;
|
||||
import google.registry.model.tld.label.PremiumList;
|
||||
import google.registry.model.tld.label.PremiumListDao;
|
||||
import google.registry.model.tld.label.ReservedList;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.util.SerializeUtils;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Optional;
|
||||
@@ -61,8 +60,6 @@ public final class RegistryTest extends EntityTestCase {
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
// Auto-increment fakeClock in DatabaseHelper.
|
||||
inject.setStaticField(DatabaseHelper.class, "clock", fakeClock);
|
||||
createTld("tld");
|
||||
}
|
||||
|
||||
|
||||
@@ -27,11 +27,9 @@ import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
@@ -54,8 +52,6 @@ public class TransactionManagerTest {
|
||||
new TestEntity("entity2", "bar"),
|
||||
new TestEntity("entity3", "qux"));
|
||||
|
||||
@RegisterExtension public InjectExtension inject = new InjectExtension();
|
||||
|
||||
@RegisterExtension
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder()
|
||||
@@ -69,7 +65,6 @@ public class TransactionManagerTest {
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
inject.setStaticField(Ofy.class, "clock", fakeClock);
|
||||
fakeClock.setAutoIncrementByOneMilli();
|
||||
}
|
||||
|
||||
|
||||
@@ -24,8 +24,6 @@ import static org.mockito.Mockito.mock;
|
||||
|
||||
import com.google.appengine.api.users.User;
|
||||
import com.google.gson.JsonObject;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Actions;
|
||||
import google.registry.request.auth.AuthLevel;
|
||||
import google.registry.request.auth.AuthResult;
|
||||
@@ -33,7 +31,6 @@ import google.registry.request.auth.UserAuthInfo;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.FakeResponse;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import google.registry.util.Idn;
|
||||
import google.registry.util.TypeUtils;
|
||||
import java.util.HashMap;
|
||||
@@ -48,8 +45,6 @@ abstract class RdapActionBaseTestCase<A extends RdapActionBase> {
|
||||
@RegisterExtension
|
||||
public final AppEngineExtension appEngine = AppEngineExtension.builder().withCloudSql().build();
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
|
||||
protected static final AuthResult AUTH_RESULT =
|
||||
AuthResult.create(
|
||||
AuthLevel.USER,
|
||||
@@ -72,19 +67,18 @@ abstract class RdapActionBaseTestCase<A extends RdapActionBase> {
|
||||
|
||||
RdapActionBaseTestCase(Class<A> rdapActionClass) {
|
||||
this.rdapActionClass = rdapActionClass;
|
||||
this.actionPath = Actions.getPathForAction(rdapActionClass);
|
||||
actionPath = Actions.getPathForAction(rdapActionClass);
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void beforeEachRdapActionBaseTestCase() {
|
||||
inject.setStaticField(Ofy.class, "clock", clock);
|
||||
action = TypeUtils.instantiate(rdapActionClass);
|
||||
action.includeDeletedParam = Optional.empty();
|
||||
action.formatOutputParam = Optional.empty();
|
||||
action.response = response;
|
||||
action.rdapJsonFormatter = RdapTestHelper.getTestRdapJsonFormatter(clock);
|
||||
action.rdapMetrics = rdapMetrics;
|
||||
action.requestMethod = Action.Method.GET;
|
||||
action.requestMethod = GET;
|
||||
logout();
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,6 @@ import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarPoc;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
@@ -51,7 +50,6 @@ import google.registry.rdap.RdapObjectClasses.ReplyPayloadBase;
|
||||
import google.registry.rdap.RdapObjectClasses.TopLevelReplyObject;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -63,8 +61,6 @@ class RdapJsonFormatterTest {
|
||||
@RegisterExtension
|
||||
public final AppEngineExtension appEngine = AppEngineExtension.builder().withCloudSql().build();
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
|
||||
private final FakeClock clock = new FakeClock(DateTime.parse("1999-01-01T00:00:00Z"));
|
||||
|
||||
private RdapJsonFormatter rdapJsonFormatter;
|
||||
@@ -85,8 +81,6 @@ class RdapJsonFormatterTest {
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
inject.setStaticField(Ofy.class, "clock", clock);
|
||||
|
||||
rdapJsonFormatter = RdapTestHelper.getTestRdapJsonFormatter(clock);
|
||||
rdapJsonFormatter.rdapAuthorization =
|
||||
RdapAuthorization.create(RdapAuthorization.Role.REGISTRAR, "unicoderegistrar");
|
||||
@@ -299,7 +293,7 @@ class RdapJsonFormatterTest {
|
||||
}
|
||||
|
||||
private JsonObject loadJson(String expectedFileName) {
|
||||
return new Gson().fromJson(loadFile(this.getClass(), expectedFileName), JsonObject.class);
|
||||
return new Gson().fromJson(loadFile(getClass(), expectedFileName), JsonObject.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -512,7 +506,7 @@ class RdapJsonFormatterTest {
|
||||
assertThat(
|
||||
TopLevelReplyObject.create(
|
||||
new ReplyPayloadBase(BoilerplateType.OTHER) {
|
||||
@JsonableElement public String key = "value";
|
||||
@JsonableElement public static final String key = "value";
|
||||
},
|
||||
rdapJsonFormatter.createTosNotice())
|
||||
.toJson())
|
||||
@@ -524,7 +518,7 @@ class RdapJsonFormatterTest {
|
||||
assertThat(
|
||||
TopLevelReplyObject.create(
|
||||
new ReplyPayloadBase(BoilerplateType.DOMAIN) {
|
||||
@JsonableElement public String key = "value";
|
||||
@JsonableElement public static final String key = "value";
|
||||
},
|
||||
rdapJsonFormatter.createTosNotice())
|
||||
.toJson())
|
||||
|
||||
@@ -31,11 +31,9 @@ import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.common.truth.Truth8;
|
||||
import google.registry.model.common.Cursor;
|
||||
import google.registry.model.common.Cursor.CursorType;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -44,8 +42,6 @@ import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
/** Unit tests for {@link PendingDepositChecker}. */
|
||||
public class PendingDepositCheckerTest {
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
|
||||
@RegisterExtension
|
||||
public final AppEngineExtension appEngine = AppEngineExtension.builder().withCloudSql().build();
|
||||
|
||||
@@ -54,7 +50,6 @@ public class PendingDepositCheckerTest {
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
inject.setStaticField(Ofy.class, "clock", clock);
|
||||
checker.brdaDayOfWeek = TUESDAY;
|
||||
checker.brdaInterval = standardDays(7);
|
||||
checker.clock = clock;
|
||||
|
||||
+1
-4
@@ -37,7 +37,6 @@ import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.Registrar.State;
|
||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor.RegistrarAccessDeniedException;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import google.registry.util.JdkLoggerConfig;
|
||||
import java.util.Optional;
|
||||
import java.util.logging.Level;
|
||||
@@ -61,8 +60,6 @@ class AuthenticatedRegistrarAccessorTest {
|
||||
@RegisterExtension
|
||||
final AppEngineExtension appEngine = AppEngineExtension.builder().withCloudSql().build();
|
||||
|
||||
@RegisterExtension final InjectExtension inject = new InjectExtension();
|
||||
|
||||
@Mock private HttpServletRequest req;
|
||||
@Mock private HttpServletResponse rsp;
|
||||
@Mock private GroupsConnection groupsConnection;
|
||||
@@ -142,7 +139,7 @@ class AuthenticatedRegistrarAccessorTest {
|
||||
verify(lazyGroupsConnection).get();
|
||||
}
|
||||
|
||||
/** Logged out users don't have access to anything. */
|
||||
/** Logged-out users don't have access to anything. */
|
||||
@Test
|
||||
void getAllClientIdWithAccess_loggedOutUser() {
|
||||
AuthenticatedRegistrarAccessor registrarAccessor =
|
||||
|
||||
@@ -22,7 +22,6 @@ import com.google.common.base.Splitter;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.FakeUserService;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import org.joda.time.Duration;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -34,8 +33,6 @@ class XsrfTokenManagerTest {
|
||||
@RegisterExtension
|
||||
final AppEngineExtension appEngine = AppEngineExtension.builder().withCloudSql().build();
|
||||
|
||||
@RegisterExtension InjectExtension inject = new InjectExtension();
|
||||
|
||||
private final User testUser = new User("test@example.com", "test@example.com");
|
||||
private final FakeClock clock = new FakeClock(START_OF_TIME);
|
||||
private final FakeUserService userService = new FakeUserService();
|
||||
@@ -81,7 +78,7 @@ class XsrfTokenManagerTest {
|
||||
void testValidate_tokenTimestampTamperedWith() {
|
||||
String encodedPart = Splitter.on(':').splitToList(token).get(2);
|
||||
long fakeTimestamp = clock.nowUtc().plusMillis(1).getMillis();
|
||||
assertThat(xsrfTokenManager.validateToken("1:" + fakeTimestamp + ":" + encodedPart)).isFalse();
|
||||
assertThat(xsrfTokenManager.validateToken("1:" + fakeTimestamp + ':' + encodedPart)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -32,12 +32,8 @@ import google.registry.model.contact.ContactAddress;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.PostalInfo;
|
||||
import google.registry.model.domain.DesignatedContact;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import java.io.IOException;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/**
|
||||
* Datastore fixtures for the development webserver.
|
||||
@@ -47,14 +43,6 @@ import org.joda.time.DateTime;
|
||||
*/
|
||||
public enum Fixture {
|
||||
|
||||
INJECTED_FAKE_CLOCK {
|
||||
@Override
|
||||
public void load() {
|
||||
new InjectExtension()
|
||||
.setStaticField(Ofy.class, "clock", new FakeClock(DateTime.parse("2000-01-01TZ")));
|
||||
}
|
||||
},
|
||||
|
||||
/** Fixture of two TLDs, three contacts, two domains, and six hosts. */
|
||||
BASIC {
|
||||
@Override
|
||||
|
||||
@@ -1,211 +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.testing;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
import org.junit.jupiter.api.extension.AfterEachCallback;
|
||||
import org.junit.jupiter.api.extension.BeforeEachCallback;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
|
||||
/**
|
||||
* JUnit extension for overriding {@code private static} fields during a test.
|
||||
*
|
||||
* <p>This extension uses reflection to change the value of a field while your test is running and
|
||||
* then restore it to its original value after it's done (even if the test fails). The injection
|
||||
* will work even if the field is marked {@code private} (but not if it's {@code final}). The
|
||||
* downside is that if you rename the field in the future, IDE refactoring won't be smart enough to
|
||||
* update the injection site.
|
||||
*
|
||||
* <p>We encourage you to consider using {@link google.registry.util.NonFinalForTesting
|
||||
* @NonFinalForTesting} to document your injected fields.
|
||||
*
|
||||
* <p>This class is a horrible evil hack, but it alleviates you of the toil of having to break
|
||||
* encapsulation by making your fields non-{@code private}, using the {@link
|
||||
* com.google.common.annotations.VisibleForTesting @VisibleForTesting} annotation to document
|
||||
* why you've reduced visibility, creating a temporary field to store the old value, and then
|
||||
* writing an {@link org.junit.After @After} method to restore it. So sometimes it feels good
|
||||
* to be evil; but hopefully one day we'll be able to delete this class and do things
|
||||
* <i>properly</i> with <a href="http://square.github.io/dagger/">Dagger</a> dependency injection.
|
||||
*
|
||||
* <p>You use this class in by declaring it as an {@link
|
||||
* org.junit.jupiter.api.extension.RegisterExtension @RegisterExtension} field and then call
|
||||
* {@link #setStaticField} from either your {@link org.junit.jupiter.api.Test @Test} or {@link
|
||||
* org.junit.jupiter.api.BeforeEach @BeforeEach} methods. For example:
|
||||
*
|
||||
* <pre>
|
||||
* // Doomsday.java
|
||||
* public class Doomsday {
|
||||
*
|
||||
* private static Clock clock = new SystemClock();
|
||||
*
|
||||
* public long getTime() {
|
||||
* return clock.currentTimeMillis();
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* // DoomsdayTest.java
|
||||
* public class DoomsdayTest {
|
||||
*
|
||||
* @RegisterExtension
|
||||
* public InjectExtension inject = new InjectExtension();
|
||||
*
|
||||
* private final FakeClock clock = new FakeClock();
|
||||
*
|
||||
* @BeforeEach
|
||||
* public void beforeEach() {
|
||||
* inject.setStaticField(Doomsday.class, "clock", clock);
|
||||
* }
|
||||
*
|
||||
* @Test
|
||||
* public void test() {
|
||||
* clock.advanceBy(666L);
|
||||
* Doomsday doom = new Doomsday();
|
||||
* assertEquals(666L, doom.getTime());
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @see google.registry.util.NonFinalForTesting
|
||||
*/
|
||||
public class InjectExtension implements AfterEachCallback, BeforeEachCallback {
|
||||
|
||||
private static class Change {
|
||||
private final Field field;
|
||||
@Nullable private Object oldValue;
|
||||
@Nullable private final Object newValue;
|
||||
private boolean active;
|
||||
|
||||
Change(Field field, @Nullable Object oldValue, @Nullable Object newValue, boolean active) {
|
||||
this.field = field;
|
||||
this.oldValue = oldValue;
|
||||
this.newValue = newValue;
|
||||
this.active = active;
|
||||
}
|
||||
}
|
||||
|
||||
private final List<Change> changes = new ArrayList<>();
|
||||
private final Set<Field> injected = new HashSet<>();
|
||||
|
||||
/** Adds the specified field override to those set by the extension. */
|
||||
public InjectExtension withStaticFieldOverride(
|
||||
Class<?> clazz, String fieldName, @Nullable Object newValue) {
|
||||
changes.add(new Change(getField(clazz, fieldName), null, newValue, false));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a static field and be restores its current value after the test completes.
|
||||
*
|
||||
* <p>Prefer to use withStaticFieldOverride(), which is more consistent with the extension
|
||||
* pattern.
|
||||
*
|
||||
* <p>The field is allowed to be {@code private}, but it most not be {@code final}.
|
||||
*
|
||||
* <p>This method may be called either from either your {@link
|
||||
* org.junit.jupiter.api.BeforeEach @BeforeEach} method or from the {@link
|
||||
* org.junit.jupiter.api.Test @Test} method itself. However you may not inject the same field
|
||||
* multiple times during the same test.
|
||||
*
|
||||
* @throws IllegalArgumentException if the static field could not be found or modified.
|
||||
* @throws IllegalStateException if the field has already been injected during this test.
|
||||
*/
|
||||
public void setStaticField(Class<?> clazz, String fieldName, @Nullable Object newValue) {
|
||||
Field field = getField(clazz, fieldName);
|
||||
Change change = new Change(field, null, newValue, true);
|
||||
activateChange(change);
|
||||
changes.add(change);
|
||||
injected.add(field);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeEach(ExtensionContext context) {
|
||||
for (Change change : changes) {
|
||||
if (!change.active) {
|
||||
activateChange(change);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterEach(ExtensionContext context) {
|
||||
RuntimeException thrown = null;
|
||||
for (Change change : changes) {
|
||||
if (change.active) {
|
||||
try {
|
||||
checkState(
|
||||
change.field.get(null).equals(change.newValue),
|
||||
"Static field value was changed post-injection: %s.%s",
|
||||
change.field.getDeclaringClass().getSimpleName(),
|
||||
change.field.getName());
|
||||
change.field.set(null, change.oldValue);
|
||||
} catch (IllegalArgumentException | IllegalStateException | IllegalAccessException e) {
|
||||
if (thrown == null) {
|
||||
thrown = new RuntimeException(e);
|
||||
} else {
|
||||
thrown.addSuppressed(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
changes.clear();
|
||||
injected.clear();
|
||||
if (thrown != null) {
|
||||
throw thrown;
|
||||
}
|
||||
}
|
||||
|
||||
private Field getField(Class<?> clazz, String fieldName) {
|
||||
try {
|
||||
return clazz.getDeclaredField(fieldName);
|
||||
} catch (SecurityException | NoSuchFieldException e) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Static field not found: %s.%s", clazz.getSimpleName(), fieldName), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void activateChange(Change change) {
|
||||
Class<?> clazz = change.field.getDeclaringClass();
|
||||
try {
|
||||
change.field.setAccessible(true);
|
||||
change.oldValue = change.field.get(null);
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
"Static field not gettable: %s.%s", clazz.getSimpleName(), change.field.getName()),
|
||||
e);
|
||||
}
|
||||
checkState(
|
||||
!injected.contains(change.field),
|
||||
"Static field already injected: %s.%s",
|
||||
clazz.getSimpleName(),
|
||||
change.field.getName());
|
||||
try {
|
||||
change.field.set(null, change.newValue);
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
"Static field not settable: %s.%s", clazz.getSimpleName(), change.field.getName()),
|
||||
e);
|
||||
}
|
||||
change.active = true;
|
||||
}
|
||||
}
|
||||
@@ -24,11 +24,9 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.launch.LaunchNotice;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.registrar.Registrar.Type;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import google.registry.testing.TaskQueueHelper.TaskMatcher;
|
||||
import google.registry.util.Clock;
|
||||
import org.joda.time.DateTime;
|
||||
@@ -45,15 +43,12 @@ public class LordnTaskUtilsTest {
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withCloudSql().withClock(clock).withTaskQueue().build();
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
createTld("example");
|
||||
inject.setStaticField(Ofy.class, "clock", clock);
|
||||
}
|
||||
|
||||
private Domain.Builder newDomainBuilder() {
|
||||
private static Domain.Builder newDomainBuilder() {
|
||||
return new Domain.Builder()
|
||||
.setDomainName("fleece.example")
|
||||
.setPersistedCurrentSponsorRegistrarId("TheRegistrar")
|
||||
|
||||
@@ -48,14 +48,12 @@ import com.google.common.base.VerifyException;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.launch.LaunchNotice;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.FakeSleeper;
|
||||
import google.registry.testing.FakeUrlConnectionService;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import google.registry.testing.TaskQueueHelper.TaskMatcher;
|
||||
import google.registry.util.Retrier;
|
||||
import google.registry.util.TaskQueueUtils;
|
||||
@@ -95,8 +93,6 @@ class NordnUploadActionTest {
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withCloudSql().withClock(clock).withTaskQueue().build();
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
|
||||
private final LordnRequestInitializer lordnRequestInitializer =
|
||||
new LordnRequestInitializer(Optional.of("attack"));
|
||||
private final NordnUploadAction action = new NordnUploadAction();
|
||||
@@ -108,7 +104,6 @@ class NordnUploadActionTest {
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() throws Exception {
|
||||
inject.setStaticField(Ofy.class, "clock", clock);
|
||||
when(httpUrlConnection.getInputStream())
|
||||
.thenReturn(new ByteArrayInputStream("Success".getBytes(UTF_8)));
|
||||
when(httpUrlConnection.getResponseCode()).thenReturn(SC_ACCEPTED);
|
||||
@@ -164,7 +159,6 @@ class NordnUploadActionTest {
|
||||
() -> NordnUploadAction.convertTasksToCsv(null, clock.nowUtc(), "header"));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
void test_loadAllTasks_retryLogic_thirdTrysTheCharm() {
|
||||
Queue queue = mock(Queue.class);
|
||||
@@ -230,7 +224,7 @@ class NordnUploadActionTest {
|
||||
void testRun_claimsMode_payloadMatchesClaimsCsv() {
|
||||
persistClaimsModeDomain();
|
||||
action.run();
|
||||
assertThat(new String(connectionOutputStream.toByteArray(), UTF_8)).contains(CLAIMS_CSV);
|
||||
assertThat(connectionOutputStream.toString(UTF_8)).contains(CLAIMS_CSV);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -249,7 +243,7 @@ class NordnUploadActionTest {
|
||||
void testRun_sunriseMode_payloadMatchesSunriseCsv() {
|
||||
persistSunriseModeDomain();
|
||||
action.run();
|
||||
assertThat(new String(connectionOutputStream.toByteArray(), UTF_8)).contains(SUNRISE_CSV);
|
||||
assertThat(connectionOutputStream.toString(UTF_8)).contains(SUNRISE_CSV);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -258,7 +252,7 @@ class NordnUploadActionTest {
|
||||
when(httpUrlConnection.getInputStream()).thenReturn(new ByteArrayInputStream(new byte[] {}));
|
||||
persistSunriseModeDomain();
|
||||
action.run();
|
||||
assertThat(new String(connectionOutputStream.toByteArray(), UTF_8)).contains(SUNRISE_CSV);
|
||||
assertThat(connectionOutputStream.toString(UTF_8)).contains(SUNRISE_CSV);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -288,7 +282,7 @@ class NordnUploadActionTest {
|
||||
assertThrows(UrlConnectionException.class, action::run);
|
||||
}
|
||||
|
||||
private void persistClaimsModeDomain() {
|
||||
private static void persistClaimsModeDomain() {
|
||||
Domain domain = DatabaseHelper.newDomain("claims-landrush1.tld");
|
||||
persistDomainAndEnqueueLordn(
|
||||
domain
|
||||
|
||||
@@ -21,7 +21,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import google.registry.config.RegistryConfig.ConfigModule.TmchCaMode;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import google.registry.tmch.TmchXmlSignature.CertificateSignatureException;
|
||||
import java.security.cert.CertificateExpiredException;
|
||||
import java.security.cert.CertificateNotYetValidException;
|
||||
@@ -42,8 +41,6 @@ class TmchXmlSignatureTest {
|
||||
@RegisterExtension
|
||||
public final AppEngineExtension appEngine = AppEngineExtension.builder().withCloudSql().build();
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
|
||||
// This should be a date which falls within the validity range of the test files contained in the
|
||||
// testdata/active directory. Note that test files claiming to be valid for a particular date
|
||||
// range in the file header may not actually be valid the whole time, because they contain an
|
||||
|
||||
@@ -25,7 +25,6 @@ import com.google.common.collect.ImmutableList;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.domain.DomainHistory.DomainHistoryId;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.poll.PollMessage.Autorenew;
|
||||
import google.registry.model.poll.PollMessage.OneTime;
|
||||
@@ -33,24 +32,19 @@ import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link AckPollMessagesCommand}. */
|
||||
public class AckPollMessagesCommandTest extends CommandTestCase<AckPollMessagesCommand> {
|
||||
|
||||
private FakeClock clock = new FakeClock(DateTime.parse("2015-02-04T08:16:32.064Z"));
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
private final FakeClock clock = new FakeClock(DateTime.parse("2015-02-04T08:16:32.064Z"));
|
||||
|
||||
private DomainHistory domainHistory;
|
||||
|
||||
@BeforeEach
|
||||
final void beforeEach() {
|
||||
inject.setStaticField(Ofy.class, "clock", clock);
|
||||
command.clock = clock;
|
||||
createTld("tld");
|
||||
Domain domain =
|
||||
|
||||
@@ -18,20 +18,14 @@ import static google.registry.testing.DatabaseHelper.createTlds;
|
||||
import static google.registry.testing.DatabaseHelper.persistActiveDomain;
|
||||
import static google.registry.testing.DatabaseHelper.persistDeletedDomain;
|
||||
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link CountDomainsCommand}. */
|
||||
public class CountDomainsCommandTest extends CommandTestCase<CountDomainsCommand> {
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
|
||||
@BeforeEach
|
||||
final void beforeEach() {
|
||||
inject.setStaticField(Ofy.class, "clock", fakeClock);
|
||||
command.clock = fakeClock;
|
||||
createTlds("foo", "bar", "baz", "qux");
|
||||
}
|
||||
|
||||
@@ -40,9 +40,7 @@ import com.google.common.collect.Range;
|
||||
import com.google.common.net.MediaType;
|
||||
import google.registry.flows.certs.CertificateChecker;
|
||||
import google.registry.flows.certs.CertificateChecker.InsecureCertificateException;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Optional;
|
||||
@@ -51,7 +49,6 @@ import org.joda.money.Money;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.mockito.Mock;
|
||||
|
||||
@@ -60,11 +57,9 @@ class CreateRegistrarCommandTest extends CommandTestCase<CreateRegistrarCommand>
|
||||
|
||||
@Mock private AppEngineConnection connection;
|
||||
|
||||
@RegisterExtension final InjectExtension inject = new InjectExtension();
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
inject.setStaticField(Ofy.class, "clock", fakeClock);
|
||||
command.setConnection(connection);
|
||||
command.certificateChecker =
|
||||
new CertificateChecker(
|
||||
|
||||
@@ -26,25 +26,19 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.beust.jcommander.ParameterException;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link EnqueuePollMessageCommand}. */
|
||||
class EnqueuePollMessageCommandTest extends CommandTestCase<EnqueuePollMessageCommand> {
|
||||
|
||||
@RegisterExtension final InjectExtension inject = new InjectExtension();
|
||||
|
||||
private Domain domain;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
createTld("tld");
|
||||
inject.setStaticField(Ofy.class, "clock", fakeClock);
|
||||
domain = persistActiveDomain("example.tld");
|
||||
persistNewRegistrar("AdminRegistrar");
|
||||
command.registryAdminClientId = "AdminRegistrar";
|
||||
|
||||
@@ -21,10 +21,8 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import com.beust.jcommander.ParameterException;
|
||||
import google.registry.testing.CloudTasksHelper;
|
||||
import google.registry.testing.CloudTasksHelper.TaskMatcher;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.mockito.junit.jupiter.MockitoSettings;
|
||||
import org.mockito.quality.Strictness;
|
||||
|
||||
@@ -33,8 +31,6 @@ import org.mockito.quality.Strictness;
|
||||
public class GenerateEscrowDepositCommandTest
|
||||
extends CommandTestCase<GenerateEscrowDepositCommand> {
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
|
||||
CloudTasksHelper cloudTasksHelper = new CloudTasksHelper();
|
||||
|
||||
@BeforeEach
|
||||
|
||||
@@ -22,7 +22,6 @@ import google.registry.keyring.api.Keyring;
|
||||
import google.registry.rde.Ghostryde;
|
||||
import google.registry.testing.BouncyCastleProviderExtension;
|
||||
import google.registry.testing.FakeKeyringModule;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@@ -51,8 +50,6 @@ class GhostrydeCommandTest extends CommandTestCase<GhostrydeCommand> {
|
||||
+ "Haply I may remember, \n"
|
||||
+ " And haply may forget. \n").getBytes(UTF_8);
|
||||
|
||||
@RegisterExtension final InjectExtension inject = new InjectExtension();
|
||||
|
||||
@RegisterExtension
|
||||
final BouncyCastleProviderExtension bouncy = new BouncyCastleProviderExtension();
|
||||
|
||||
@@ -78,7 +75,7 @@ class GhostrydeCommandTest extends CommandTestCase<GhostrydeCommand> {
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> runCommand("--input=" + inputFile.toString(), "--output=bar.dat"));
|
||||
() -> runCommand("--input=" + inputFile, "--output=bar.dat"));
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("Please specify either --encrypt or --decrypt");
|
||||
}
|
||||
|
||||
@@ -87,8 +84,7 @@ class GhostrydeCommandTest extends CommandTestCase<GhostrydeCommand> {
|
||||
Path inputFile = Files.createFile(tmpDir.resolve("foo.dat"));
|
||||
IllegalArgumentException thrown =
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> runCommand("--encrypt", "--input=" + inputFile.toString()));
|
||||
IllegalArgumentException.class, () -> runCommand("--encrypt", "--input=" + inputFile));
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("--output path is required in --encrypt mode");
|
||||
}
|
||||
|
||||
|
||||
@@ -22,13 +22,10 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import com.beust.jcommander.ParameterException;
|
||||
import google.registry.model.common.Cursor;
|
||||
import google.registry.model.common.Cursor.CursorType;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link ListCursorsCommand}. */
|
||||
public class ListCursorsCommandTest extends CommandTestCase<ListCursorsCommand> {
|
||||
@@ -39,12 +36,9 @@ public class ListCursorsCommandTest extends CommandTestCase<ListCursorsCommand>
|
||||
private static final String HEADER_TWO =
|
||||
"--------------------------------------------------------------------------";
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
fakeClock.setTo(DateTime.parse("1984-12-21T06:07:08.789Z"));
|
||||
inject.setStaticField(Ofy.class, "clock", fakeClock);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -22,11 +22,9 @@ import static org.mockito.Mockito.verify;
|
||||
import com.beust.jcommander.ParameterException;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import google.registry.testing.AppEngineAdminApiHelper;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import google.registry.util.AppEngineServiceUtils;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoSettings;
|
||||
import org.mockito.quality.Strictness;
|
||||
@@ -34,11 +32,9 @@ import org.mockito.quality.Strictness;
|
||||
/** Unit tests for {@link SetNumInstancesCommand}. */
|
||||
public class SetNumInstancesCommandTest extends CommandTestCase<SetNumInstancesCommand> {
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
|
||||
@Mock AppEngineServiceUtils appEngineServiceUtils;
|
||||
|
||||
private final String projectId = "domain-registry-test";
|
||||
private static final String projectId = "domain-registry-test";
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
|
||||
@@ -41,25 +41,19 @@ import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link UnrenewDomainCommand}. */
|
||||
public class UnrenewDomainCommandTest extends CommandTestCase<UnrenewDomainCommand> {
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
createTld("tld");
|
||||
fakeClock.setTo(DateTime.parse("2016-12-06T13:55:01Z"));
|
||||
inject.setStaticField(Ofy.class, "clock", fakeClock);
|
||||
command.clock = fakeClock;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,17 +42,14 @@ import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.domain.GracePeriod;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import google.registry.util.CapturingLogHandler;
|
||||
import google.registry.util.JdkLoggerConfig;
|
||||
import java.util.logging.Level;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
/** Unit tests for {@link UpdateDomainCommand}. */
|
||||
class UpdateDomainCommandTest extends EppToolCommandTestCase<UpdateDomainCommand> {
|
||||
@@ -61,11 +58,8 @@ class UpdateDomainCommandTest extends EppToolCommandTestCase<UpdateDomainCommand
|
||||
|
||||
private Domain domain;
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
inject.setStaticField(Ofy.class, "clock", fakeClock);
|
||||
command.clock = fakeClock;
|
||||
domain = persistActiveDomain("example.tld");
|
||||
JdkLoggerConfig.getConfig(UpdateDomainCommand.class).addHandler(logHandler);
|
||||
|
||||
@@ -28,7 +28,6 @@ import google.registry.request.HttpException.BadRequestException;
|
||||
import google.registry.request.HttpException.InternalServerErrorException;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import java.util.Optional;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
@@ -39,8 +38,6 @@ class CreateGroupsActionTest {
|
||||
@RegisterExtension
|
||||
final AppEngineExtension appEngine = AppEngineExtension.builder().withCloudSql().build();
|
||||
|
||||
@RegisterExtension final InjectExtension inject = new InjectExtension();
|
||||
|
||||
private final DirectoryGroupsConnection connection = mock(DirectoryGroupsConnection.class);
|
||||
private final Response response = mock(Response.class);
|
||||
|
||||
|
||||
+1
-10
@@ -31,17 +31,14 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.dns.DnsQueue;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.FakeResponse;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import java.util.Random;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
@@ -53,24 +50,18 @@ public class RefreshDnsForAllDomainsActionTest {
|
||||
private final FakeClock clock = new FakeClock(DateTime.parse("2020-02-02T02:02:02Z"));
|
||||
private final DnsQueue dnsQueue = mock(DnsQueue.class);
|
||||
private RefreshDnsForAllDomainsAction action;
|
||||
private FakeResponse response = new FakeResponse();
|
||||
private final FakeResponse response = new FakeResponse();
|
||||
|
||||
@RegisterExtension
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withCloudSql().withLocalModules().withTaskQueue().build();
|
||||
|
||||
@Order(Order.DEFAULT - 1)
|
||||
@RegisterExtension
|
||||
public final InjectExtension inject =
|
||||
new InjectExtension().withStaticFieldOverride(Ofy.class, "clock", clock);
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
action = new RefreshDnsForAllDomainsAction();
|
||||
action.smearMinutes = 1;
|
||||
action.random = new Random();
|
||||
action.random.setSeed(123L);
|
||||
action.response = new FakeResponse();
|
||||
action.clock = clock;
|
||||
action.dnsQueue = dnsQueue;
|
||||
action.response = response;
|
||||
|
||||
-5
@@ -36,7 +36,6 @@ import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.common.truth.Truth;
|
||||
import google.registry.flows.certs.CertificateChecker;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.registrar.RegistrarPoc;
|
||||
import google.registry.request.JsonActionRunner;
|
||||
import google.registry.request.JsonResponse;
|
||||
@@ -48,7 +47,6 @@ import google.registry.request.auth.UserAuthInfo;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.CloudTasksHelper;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import google.registry.ui.server.SendEmailUtils;
|
||||
import google.registry.util.EmailMessage;
|
||||
import google.registry.util.SendEmailService;
|
||||
@@ -81,8 +79,6 @@ public abstract class RegistrarSettingsActionTestCase {
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withCloudSql().withClock(clock).withTaskQueue().build();
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
|
||||
@Mock HttpServletRequest req;
|
||||
@Mock HttpServletResponse rsp;
|
||||
@Mock SendEmailService emailService;
|
||||
@@ -129,7 +125,6 @@ public abstract class RegistrarSettingsActionTestCase {
|
||||
clock);
|
||||
action.cloudTasksUtils = cloudTasksHelper.getTestCloudTasksUtils();
|
||||
|
||||
inject.setStaticField(Ofy.class, "clock", clock);
|
||||
when(req.getMethod()).thenReturn("POST");
|
||||
when(rsp.getWriter()).thenReturn(new PrintWriter(writer));
|
||||
when(req.getContentType()).thenReturn("application/json");
|
||||
|
||||
@@ -47,7 +47,6 @@ import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.model.transfer.DomainTransferData;
|
||||
@@ -57,7 +56,6 @@ import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.FakeResponse;
|
||||
import google.registry.testing.FakeSleeper;
|
||||
import google.registry.testing.FullFieldsTestEntityHelper;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import google.registry.testing.TestCacheExtension;
|
||||
import google.registry.util.Retrier;
|
||||
import google.registry.whois.WhoisMetrics.WhoisMetric;
|
||||
@@ -80,8 +78,6 @@ public class WhoisActionTest {
|
||||
public final AppEngineExtension appEngine =
|
||||
AppEngineExtension.builder().withCloudSql().withClock(clock).build();
|
||||
|
||||
@RegisterExtension public final InjectExtension inject = new InjectExtension();
|
||||
|
||||
@RegisterExtension
|
||||
public final TestCacheExtension testCacheExtension =
|
||||
new TestCacheExtension.Builder()
|
||||
@@ -109,7 +105,6 @@ public class WhoisActionTest {
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
createTlds("lol", "xn--q9jyb4c", "1.test");
|
||||
inject.setStaticField(Ofy.class, "clock", clock);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -119,7 +114,7 @@ public class WhoisActionTest {
|
||||
assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_no_command.txt"));
|
||||
}
|
||||
|
||||
private Domain makeDomainWithRegistrar(Registrar registrar) {
|
||||
private static Domain makeDomainWithRegistrar(Registrar registrar) {
|
||||
return makeDomain(
|
||||
"cat.lol",
|
||||
persistResource(makeContactResource("5372808-ERL", "Goblin Market", "lol@cat.lol")),
|
||||
@@ -287,8 +282,7 @@ public class WhoisActionTest {
|
||||
persistResource(FullFieldsTestEntityHelper.makeHost("ns1.cat.lol", "1.2.3.4")),
|
||||
persistResource(
|
||||
FullFieldsTestEntityHelper.makeHost("ns2.cat.lol", "bad:f00d:cafe::15:beef")),
|
||||
persistResource(
|
||||
(registrar = makeRegistrar("example", "Example Registrar", ACTIVE))))
|
||||
persistResource(registrar = makeRegistrar("example", "Example Registrar", ACTIVE)))
|
||||
.asBuilder()
|
||||
.setDeletionTime(clock.nowUtc().minusDays(1))
|
||||
.build());
|
||||
@@ -339,7 +333,7 @@ public class WhoisActionTest {
|
||||
persistResource(
|
||||
FullFieldsTestEntityHelper.makeHost("ns2.google.lol", "4311::f143")),
|
||||
persistResource(
|
||||
(registrar = makeRegistrar("example", "Example Registrar", ACTIVE))))
|
||||
registrar = makeRegistrar("example", "Example Registrar", ACTIVE)))
|
||||
.asBuilder()
|
||||
.setCreationTimeForTest(clock.nowUtc())
|
||||
.build());
|
||||
|
||||
@@ -36,14 +36,12 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.ofy.Ofy;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.FakeResponse;
|
||||
import google.registry.testing.FullFieldsTestEntityHelper;
|
||||
import google.registry.testing.InjectExtension;
|
||||
import google.registry.whois.WhoisMetrics.WhoisMetric;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
@@ -65,8 +63,6 @@ class WhoisHttpActionTest {
|
||||
@RegisterExtension
|
||||
final AppEngineExtension appEngine = AppEngineExtension.builder().withCloudSql().build();
|
||||
|
||||
@RegisterExtension final InjectExtension inject = new InjectExtension();
|
||||
|
||||
private final FakeResponse response = new FakeResponse();
|
||||
private final FakeClock clock = new FakeClock(DateTime.parse("2009-06-29T20:13:00Z"));
|
||||
|
||||
@@ -88,7 +84,6 @@ class WhoisHttpActionTest {
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
createTlds("lol", "xn--q9jyb4c", "1.test");
|
||||
inject.setStaticField(Ofy.class, "clock", clock);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+36
File diff suppressed because one or more lines are too long
@@ -374,6 +374,7 @@ An EPP flow that creates a new domain resource.
|
||||
* The allocation token was already redeemed.
|
||||
* 2306
|
||||
* Anchor tenant domain create is for the wrong number of years.
|
||||
* Trademarked domains cannot be registered before the sunrise period.
|
||||
* The provided mark is not yet valid.
|
||||
* The provided mark has expired.
|
||||
* Domain names can only contain a-z, 0-9, '.' and '-'.
|
||||
|
||||
Reference in New Issue
Block a user