1
0
mirror of https://github.com/google/nomulus synced 2026-06-09 16:33:02 +00:00

Compare commits

...

8 Commits

Author SHA1 Message Date
Lai Jiang 74baae397a Find the most recent prefix for RdeReportAction (#2043)
When RdeReportAction is invoked without a prefix parameter (as in the
case when it is kicked off by cron jobs for potential catch ups), we
need to used the same heuristics that's employed in RdeUploadAction to
find the most recent prefix for the given watermark, otherwise the job
will not find any deposits to upload.

Also renamed RdeUtil to RdeUtils, to be consistent with our naming
conventions.
2023-05-25 14:57:03 -04:00
sarahcaseybot fddecea18e Rename Registries to Tlds (#2042)
* Rename Registries to Tlds

* Change Tlds to TLDs in comments
2023-05-24 17:08:09 -04:00
Pavlo Tkach 36a60bdf8b Add swagger API documentation (#2035) 2023-05-24 16:10:50 -04:00
dependabot[bot] 58ed53314c Bump socket.io-parser from 4.2.1 to 4.2.3 in /console-webapp (#2040)
Bumps [socket.io-parser](https://github.com/socketio/socket.io-parser) from 4.2.1 to 4.2.3.
- [Release notes](https://github.com/socketio/socket.io-parser/releases)
- [Changelog](https://github.com/socketio/socket.io-parser/blob/main/CHANGELOG.md)
- [Commits](https://github.com/socketio/socket.io-parser/compare/4.2.1...4.2.3)

---
updated-dependencies:
- dependency-name: socket.io-parser
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-24 07:23:15 -04:00
Lai Jiang 5eaf99e02a Show HTTP response code when PUT fails (#2038) 2023-05-23 17:01:56 -04:00
Pavlo Tkach 9a5f094d1d Remove unused queue.xml file left after Cloud Tasks Queue migration (#2039) 2023-05-23 13:59:21 -04:00
Lai Jiang 6cbc2fa5ef Wrap tm().loadByKey() in a transaction when caching is not enabled. (#2030)
We have caching enabled so we never exercised this line.
2023-05-19 14:21:48 -04:00
Lai Jiang 6883093735 Drop DatabaseMigrationStateSchedule table (#2002) 2023-05-18 13:44:24 -04:00
73 changed files with 2739 additions and 1711 deletions
+1 -1
View File
@@ -103,7 +103,7 @@ nomulus.iws
.gradle/
**/build
cloudbuild-caches/
node_modules/**
**/node_modules/**
/repos/
# Compiled JS/CSS code
+1 -1
View File
@@ -25,7 +25,7 @@ import textwrap
import re
# We should never analyze any generated files
UNIVERSALLY_SKIPPED_PATTERNS = {"/build/", "cloudbuild-caches", "/out/", ".git/", ".gradle/", "/dist/", "karma.conf.js", "polyfills.ts", "test.ts"}
UNIVERSALLY_SKIPPED_PATTERNS = {"/build/", "cloudbuild-caches", "/out/", ".git/", ".gradle/", "/dist/", "karma.conf.js", "polyfills.ts", "test.ts", "/docs/console-endpoints/"}
# We can't rely on CI to have the Enum package installed so we do this instead.
FORBIDDEN = 1
REQUIRED = 2
+6 -6
View File
@@ -10909,9 +10909,9 @@
}
},
"node_modules/socket.io-parser": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.1.tgz",
"integrity": "sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.3.tgz",
"integrity": "sha512-JMafRntWVO2DCJimKsRTh/wnqVvO4hrfwOqtO7f+uzwsQMuxO6VwImtYxaQ+ieoyshWOTJyV0fA21lccEXRPpQ==",
"dev": true,
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
@@ -20541,9 +20541,9 @@
}
},
"socket.io-parser": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.1.tgz",
"integrity": "sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.3.tgz",
"integrity": "sha512-JMafRntWVO2DCJimKsRTh/wnqVvO4hrfwOqtO7f+uzwsQMuxO6VwImtYxaQ+ieoyshWOTJyV0fA21lccEXRPpQ==",
"dev": true,
"requires": {
"@socket.io/component-emitter": "~3.1.0",
@@ -21,7 +21,7 @@ import static google.registry.batch.BatchModule.PARAM_DRY_RUN;
import static google.registry.config.RegistryEnvironment.PRODUCTION;
import static google.registry.dns.DnsUtils.requestDomainDnsRefresh;
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_DELETE;
import static google.registry.model.tld.Registries.getTldsOfType;
import static google.registry.model.tld.Tlds.getTldsOfType;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.request.Action.Method.POST;
import static google.registry.request.RequestParameters.PARAM_TLDS;
@@ -43,7 +43,7 @@ import google.registry.rde.RdeMarshaller;
import google.registry.rde.RdeModule;
import google.registry.rde.RdeResourceType;
import google.registry.rde.RdeUploadAction;
import google.registry.rde.RdeUtil;
import google.registry.rde.RdeUtils;
import google.registry.request.Action.Service;
import google.registry.request.RequestParameters;
import google.registry.tldconfig.idn.IdnTableEnum;
@@ -166,7 +166,7 @@ public class RdeIO {
final int revision =
Optional.ofNullable(key.revision())
.orElseGet(() -> RdeRevision.getNextRevision(tld, watermark, mode));
String id = RdeUtil.timestampToId(watermark);
String id = RdeUtils.timestampToId(watermark);
String prefix =
options.getJobName()
+ '/'
@@ -27,9 +27,9 @@ import static google.registry.cron.CronModule.FOR_EACH_TEST_TLD_PARAM;
import static google.registry.cron.CronModule.JITTER_SECONDS_PARAM;
import static google.registry.cron.CronModule.QUEUE_PARAM;
import static google.registry.cron.CronModule.RUN_IN_EMPTY_PARAM;
import static google.registry.model.tld.Registries.getTldsOfType;
import static google.registry.model.tld.Tld.TldType.REAL;
import static google.registry.model.tld.Tld.TldType.TEST;
import static google.registry.model.tld.Tlds.getTldsOfType;
import com.google.cloud.tasks.v2.Task;
import com.google.common.collect.ArrayListMultimap;
@@ -20,8 +20,8 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
import com.google.common.collect.ImmutableList;
import com.google.common.net.InternetDomainName;
import google.registry.model.common.DnsRefreshRequest;
import google.registry.model.tld.Registries;
import google.registry.model.tld.Tld;
import google.registry.model.tld.Tlds;
import java.util.Collection;
import java.util.Optional;
import org.joda.time.DateTime;
@@ -38,7 +38,7 @@ public final class DnsUtils {
private static void requestDnsRefresh(String name, TargetType type, Duration delay) {
// Throws an IllegalArgumentException if the name is not under a managed TLD -- we only update
// DNS for names that are under our management.
String tld = Registries.findTldForNameOrThrow(InternetDomainName.from(name)).toString();
String tld = Tlds.findTldForNameOrThrow(InternetDomainName.from(name)).toString();
tm().transact(
() ->
tm().insert(
@@ -114,7 +114,7 @@ public final class DnsUtils {
}
public static long getDnsAPlusAAAATtlForHost(String host, Duration dnsDefaultATtl) {
Optional<InternetDomainName> tldName = Registries.findTldForName(InternetDomainName.from(host));
Optional<InternetDomainName> tldName = Tlds.findTldForName(InternetDomainName.from(host));
Duration dnsAPlusAaaaTtl = dnsDefaultATtl;
if (tldName.isPresent()) {
Tld tld = Tld.get(tldName.get().toString());
@@ -40,8 +40,8 @@ import google.registry.dns.writer.DnsWriterZone;
import google.registry.model.domain.Domain;
import google.registry.model.domain.secdns.DomainDsData;
import google.registry.model.host.Host;
import google.registry.model.tld.Registries;
import google.registry.model.tld.Tld;
import google.registry.model.tld.Tlds;
import google.registry.util.Clock;
import google.registry.util.Concurrent;
import google.registry.util.Retrier;
@@ -248,7 +248,7 @@ public class CloudDnsWriter extends BaseDnsWriter {
public void publishHost(String hostName) {
// Get the superordinate domain name of the host.
InternetDomainName host = InternetDomainName.from(hostName);
Optional<InternetDomainName> tld = Registries.findTldForName(host);
Optional<InternetDomainName> tld = Tlds.findTldForName(host);
// Host not managed by our registry, no need to update DNS.
if (!tld.isPresent()) {
@@ -31,8 +31,8 @@ import google.registry.dns.writer.DnsWriterZone;
import google.registry.model.domain.Domain;
import google.registry.model.domain.secdns.DomainDsData;
import google.registry.model.host.Host;
import google.registry.model.tld.Registries;
import google.registry.model.tld.Tld;
import google.registry.model.tld.Tlds;
import google.registry.util.Clock;
import java.io.IOException;
import java.net.Inet4Address;
@@ -154,7 +154,7 @@ public class DnsUpdateWriter extends BaseDnsWriter {
// Get the superordinate domain name of the host.
InternetDomainName host = InternetDomainName.from(hostName);
ImmutableList<String> hostParts = host.parts();
Optional<InternetDomainName> tld = Registries.findTldForName(host);
Optional<InternetDomainName> tld = Tlds.findTldForName(host);
// host not managed by our registry, no need to update DNS.
if (!tld.isPresent()) {
@@ -1,119 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- TODO: @ptkach - Delete once Cloud Api deployer is up and running -->
<queue-entries>
<!-- Queue for reading DNS update requests and batching them off to the dns-publish queue. -->
<queue>
<name>dns-refresh</name>
<rate>100/s</rate>
</queue>
<!-- Queue for publishing DNS updates in batches. -->
<queue>
<name>dns-publish</name>
<rate>100/s</rate>
<bucket-size>100</bucket-size>
<!-- 30 sec backoff increasing linearly up to 30 minutes. -->
<retry-parameters>
<min-backoff-seconds>30</min-backoff-seconds>
<max-backoff-seconds>1800</max-backoff-seconds>
<max-doublings>0</max-doublings>
</retry-parameters>
</queue>
<!-- Queue for uploading RDE deposits to the escrow provider. -->
<queue>
<name>rde-upload</name>
<rate>10/m</rate>
<bucket-size>50</bucket-size>
<max-concurrent-requests>5</max-concurrent-requests>
<retry-parameters>
<task-age-limit>4h</task-age-limit>
</retry-parameters>
</queue>
<!-- Queue for uploading RDE reports to ICANN. -->
<queue>
<name>rde-report</name>
<rate>1/s</rate>
<max-concurrent-requests>1</max-concurrent-requests>
<retry-parameters>
<task-age-limit>4h</task-age-limit>
</retry-parameters>
</queue>
<!-- Queue for copying BRDA deposits to GCS. -->
<queue>
<name>brda</name>
<rate>1/m</rate>
<max-concurrent-requests>10</max-concurrent-requests>
<retry-parameters>
<task-age-limit>23h</task-age-limit>
</retry-parameters>
</queue>
<!-- Queue for tasks that trigger domain DNS update upon host rename. -->
<queue>
<name>async-host-rename</name>
<rate>1/s</rate>
</queue>
<!-- Queue for tasks that wait for a Beam pipeline to complete (i.e. Spec11 and invoicing). -->
<queue>
<name>beam-reporting</name>
<rate>1/m</rate>
<max-concurrent-requests>1</max-concurrent-requests>
<retry-parameters>
<task-retry-limit>5</task-retry-limit>
<min-backoff-seconds>180</min-backoff-seconds>
<max-backoff-seconds>180</max-backoff-seconds>
</retry-parameters>
</queue>
<!-- Queue for tasks that communicate with TMCH MarksDB webserver. -->
<queue>
<name>marksdb</name>
<rate>1/m</rate>
<max-concurrent-requests>1</max-concurrent-requests>
<retry-parameters>
<task-age-limit>11h</task-age-limit> <!-- cron interval minus hour -->
</retry-parameters>
</queue>
<!-- Queue for tasks to produce LORDN CSV reports, populated by a Cloud Scheduler fanout job. -->
<queue>
<name>nordn</name>
<rate>1/s</rate>
<max-concurrent-requests>10</max-concurrent-requests>
<retry-parameters>
<task-age-limit>11h</task-age-limit> <!-- cron interval minus hour -->
</retry-parameters>
</queue>
<!-- Queue for tasks that sync data to Google Spreadsheets. -->
<queue>
<name>sheet</name>
<rate>1/s</rate>
<!-- max-concurrent-requests is intentionally omitted. -->
<retry-parameters>
<task-age-limit>1h</task-age-limit>
</retry-parameters>
</queue>
<!-- Queue for infrequent cron tasks (i.e. hourly or less often) that should retry three times on failure. -->
<queue>
<name>retryable-cron-tasks</name>
<rate>1/s</rate>
<retry-parameters>
<task-retry-limit>3</task-retry-limit>
</retry-parameters>
</queue>
<!-- Queue for async actions that should be run at some point in the future. -->
<queue>
<name>async-actions</name>
<rate>1/s</rate>
<max-concurrent-requests>5</max-concurrent-requests>
</queue>
</queue-entries>
@@ -15,7 +15,7 @@
package google.registry.export;
import static com.google.common.base.Verify.verifyNotNull;
import static google.registry.model.tld.Registries.getTldsOfType;
import static google.registry.model.tld.Tlds.getTldsOfType;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.request.Action.Method.POST;
import static java.nio.charset.StandardCharsets.UTF_8;
@@ -26,12 +26,12 @@ import static com.google.common.collect.Sets.difference;
import static com.google.common.collect.Sets.intersection;
import static com.google.common.collect.Sets.union;
import static google.registry.model.domain.Domain.MAX_REGISTRATION_YEARS;
import static google.registry.model.tld.Registries.findTldForName;
import static google.registry.model.tld.Registries.getTlds;
import static google.registry.model.tld.Tld.TldState.GENERAL_AVAILABILITY;
import static google.registry.model.tld.Tld.TldState.PREDELEGATION;
import static google.registry.model.tld.Tld.TldState.QUIET_PERIOD;
import static google.registry.model.tld.Tld.TldState.START_DATE_SUNRISE;
import static google.registry.model.tld.Tlds.findTldForName;
import static google.registry.model.tld.Tlds.getTlds;
import static google.registry.model.tld.label.ReservationType.ALLOWED_IN_SUNRISE;
import static google.registry.model.tld.label.ReservationType.FULLY_BLOCKED;
import static google.registry.model.tld.label.ReservationType.NAME_COLLISION;
@@ -16,7 +16,7 @@ package google.registry.flows.host;
import static google.registry.model.EppResourceUtils.isActive;
import static google.registry.model.EppResourceUtils.loadByForeignKey;
import static google.registry.model.tld.Registries.findTldForName;
import static google.registry.model.tld.Tlds.findTldForName;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import static java.util.stream.Collectors.joining;
@@ -403,7 +403,7 @@ public abstract class EppResource extends UpdateAutoTimestampEntity implements B
public static ImmutableMap<VKey<? extends EppResource>, EppResource> loadCached(
Iterable<VKey<? extends EppResource>> keys) {
if (!RegistryConfig.isEppResourceCachingEnabled()) {
return tm().loadByKeys(keys);
return tm().transact(() -> tm().loadByKeys(keys));
}
return ImmutableMap.copyOf(cacheEppResources.getAll(keys));
}
@@ -416,7 +416,7 @@ public abstract class EppResource extends UpdateAutoTimestampEntity implements B
*/
public static <T extends EppResource> T loadCached(VKey<T> key) {
if (!RegistryConfig.isEppResourceCachingEnabled()) {
return tm().loadByKey(key);
return tm().transact(() -> tm().loadByKey(key));
}
// Safe to cast because loading a Key<T> returns an entity of type T.
@SuppressWarnings("unchecked")
@@ -26,7 +26,7 @@ import static com.google.common.collect.Sets.immutableEnumSet;
import static com.google.common.io.BaseEncoding.base64;
import static google.registry.config.RegistryConfig.getDefaultRegistrarWhoisServer;
import static google.registry.model.CacheUtils.memoizeWithShortExpiration;
import static google.registry.model.tld.Registries.assertTldsExist;
import static google.registry.model.tld.Tlds.assertTldsExist;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
import static google.registry.util.CollectionUtils.nullToEmptyImmutableSortedCopy;
@@ -40,15 +40,15 @@ import java.util.stream.Stream;
import javax.persistence.EntityManager;
/** Utilities for finding and listing {@link Tld} entities. */
public final class Registries {
public final class Tlds {
private Registries() {}
private Tlds() {}
/** Supplier of a cached registries map. */
/** Supplier of a cached TLDs map. */
private static Supplier<ImmutableMap<String, TldType>> cache = createFreshCache();
/**
* Returns a newly-created Supplier of a registries to types map.
* Returns a newly-created Supplier of a TLDs to types map.
*
* <p>The supplier's get() method enters a transactionless context briefly to avoid enrolling the
* query inside an unrelated client-affecting transaction.
@@ -84,7 +84,7 @@ public final class Registries {
return ImmutableSet.copyOf(filterValues(cache.get(), equalTo(type)).keySet());
}
/** Returns the Registry entities themselves of the given type loaded fresh from the database. */
/** Returns the TLD entities themselves of the given type loaded fresh from the database. */
public static ImmutableSet<Tld> getTldEntitiesOfType(TldType type) {
return Tld.get(filterValues(cache.get(), equalTo(type)).keySet());
}
@@ -18,7 +18,7 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Strings.isNullOrEmpty;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static google.registry.model.tld.Registries.getTlds;
import static google.registry.model.tld.Tlds.getTlds;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableList;
@@ -20,7 +20,7 @@ import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import google.registry.model.eppoutput.Result.Code;
import google.registry.model.tld.Registries;
import google.registry.model.tld.Tlds;
import google.registry.util.Clock;
import java.util.Optional;
import org.joda.time.DateTime;
@@ -104,7 +104,7 @@ public abstract class EppMetric {
String tld = Iterables.getOnlyElement(tlds);
// Only record TLDs that actually exist, otherwise we can blow up cardinality by recording
// an arbitrarily large number of strings.
setTld(Optional.ofNullable(Registries.getTlds().contains(tld) ? tld : "_invalid"));
setTld(Optional.ofNullable(Tlds.getTlds().contains(tld) ? tld : "_invalid"));
break;
default:
setTld("_various");
@@ -112,8 +112,8 @@ final class ContactToXjcConverter {
private static XjcRdeContactTransferDataType convertTransferData(TransferData model) {
XjcRdeContactTransferDataType bean = new XjcRdeContactTransferDataType();
bean.setTrStatus(XjcEppcomTrStatusType.fromValue(model.getTransferStatus().getXmlName()));
bean.setReRr(RdeUtil.makeXjcRdeRrType(model.getGainingRegistrarId()));
bean.setAcRr(RdeUtil.makeXjcRdeRrType(model.getLosingRegistrarId()));
bean.setReRr(RdeUtils.makeXjcRdeRrType(model.getGainingRegistrarId()));
bean.setAcRr(RdeUtils.makeXjcRdeRrType(model.getLosingRegistrarId()));
bean.setReDate(model.getTransferRequestTime());
bean.setAcDate(model.getPendingTransferExpirationTime());
return bean;
@@ -262,8 +262,8 @@ final class DomainToXjcConverter {
XjcRdeDomainTransferDataType bean = new XjcRdeDomainTransferDataType();
bean.setTrStatus(
XjcEppcomTrStatusType.fromValue(model.getTransferStatus().getXmlName()));
bean.setReRr(RdeUtil.makeXjcRdeRrType(model.getGainingRegistrarId()));
bean.setAcRr(RdeUtil.makeXjcRdeRrType(model.getLosingRegistrarId()));
bean.setReRr(RdeUtils.makeXjcRdeRrType(model.getGainingRegistrarId()));
bean.setAcRr(RdeUtils.makeXjcRdeRrType(model.getLosingRegistrarId()));
bean.setReDate(model.getTransferRequestTime());
bean.setAcDate(model.getPendingTransferExpirationTime());
bean.setExDate(model.getTransferredRegistrationExpirationTime());
@@ -23,9 +23,9 @@ import google.registry.config.RegistryConfig.Config;
import google.registry.model.common.Cursor;
import google.registry.model.common.Cursor.CursorType;
import google.registry.model.rde.RdeMode;
import google.registry.model.tld.Registries;
import google.registry.model.tld.Tld;
import google.registry.model.tld.Tld.TldType;
import google.registry.model.tld.Tlds;
import google.registry.util.Clock;
import java.util.Optional;
import javax.inject.Inject;
@@ -83,7 +83,7 @@ public final class PendingDepositChecker {
ImmutableSetMultimap.Builder<String, PendingDeposit> builder =
new ImmutableSetMultimap.Builder<>();
DateTime now = clock.nowUtc();
for (String tldStr : Registries.getTldsOfType(TldType.REAL)) {
for (String tldStr : Tlds.getTldsOfType(TldType.REAL)) {
Tld tld = Tld.get(tldStr);
if (!tld.getEscrowEnabled()) {
continue;
@@ -19,6 +19,7 @@ import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8;
import static google.registry.model.common.Cursor.getCursorTimeOrStartOfTime;
import static google.registry.model.rde.RdeMode.FULL;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.rde.RdeUtils.findMostRecentPrefixForWatermark;
import static google.registry.request.Action.Method.POST;
import static google.registry.util.DateTimeUtils.isBeforeOrAt;
@@ -98,8 +99,10 @@ public final class RdeReportAction implements Runnable, EscrowTask {
RdeRevision.getCurrentRevision(tld, watermark, FULL)
.orElseThrow(
() -> new IllegalStateException("RdeRevision was not set on generated deposit"));
String name =
prefix.orElse("") + RdeNamingUtils.makeRydeFilename(tld, watermark, FULL, 1, revision);
if (!prefix.isPresent()) {
prefix = Optional.of(findMostRecentPrefixForWatermark(watermark, bucket, tld, gcsUtils));
}
String name = prefix.get() + RdeNamingUtils.makeRydeFilename(tld, watermark, FULL, 1, revision);
BlobId reportFilename = BlobId.of(bucket, name + "-report.xml.ghostryde");
verify(gcsUtils.existsAndNotEmpty(reportFilename), "Missing file: %s", reportFilename);
reporter.send(readReportFromGcs(reportFilename));
@@ -43,6 +43,7 @@ import java.io.ByteArrayInputStream;
import java.net.MalformedURLException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.util.Arrays;
import javax.inject.Inject;
/**
@@ -86,22 +87,23 @@ public class RdeReporter {
retrier.callWithRetry(
() -> {
HTTPResponse rsp1 = urlFetchService.fetch(req);
switch (rsp1.getResponseCode()) {
case SC_OK:
case SC_BAD_REQUEST:
break;
default:
throw new RuntimeException("PUT failed");
int responseCode = rsp1.getResponseCode();
if (responseCode != SC_OK && responseCode != SC_BAD_REQUEST) {
logger.atSevere().log(
"Failure when trying to PUT RDE report to ICANN server: %d\n%s",
responseCode, Arrays.toString(rsp1.getContent()));
throw new RuntimeException("Error uploading deposits to ICANN");
}
return rsp1;
},
SocketTimeoutException.class);
// Ensure the XML response is valid.
// Ensure the XML response is valid. The EPP result code would not be 1000 if we get an
// SC_BAD_REQUEST as the HTTP response code.
XjcIirdeaResult result = parseResult(rsp.getContent());
if (result.getCode().getValue() != 1000) {
logger.atWarning().log(
"PUT rejected: %d %s\n%s",
"Rejected when trying to PUT RDE report to ICANN server: %d %s\n%s",
result.getCode().getValue(), result.getMsg(), result.getDescription());
throw new InternalServerErrorException(result.getMsg());
}
@@ -23,6 +23,7 @@ import static google.registry.model.common.Cursor.getCursorTimeOrStartOfTime;
import static google.registry.model.rde.RdeMode.FULL;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.rde.RdeModule.RDE_REPORT_QUEUE;
import static google.registry.rde.RdeUtils.findMostRecentPrefixForWatermark;
import static google.registry.request.Action.Method.POST;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import static google.registry.util.DateTimeUtils.isBeforeOrAt;
@@ -31,7 +32,6 @@ import static java.util.Arrays.asList;
import com.google.cloud.storage.BlobId;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Ordering;
import com.google.common.flogger.FluentLogger;
import com.google.common.io.ByteStreams;
import com.jcraft.jsch.JSch;
@@ -136,26 +136,10 @@ public final class RdeUploadAction implements Runnable, EscrowTask {
@Override
public void runWithLock(final DateTime watermark) throws Exception {
// If a prefix is not provided, but we are in SQL mode, try to determine the prefix. This should
// only happen when the RDE upload cron job runs to catch up any un-retried (i. e. expected)
// RDE failures.
// If a prefix is not provided,try to determine the prefix. This should only happen when the RDE
// upload cron job runs to catch up any un-retried (i. e. expected) RDE failures.
if (!prefix.isPresent()) {
// The prefix is always in the format of: rde-2022-02-21t00-00-00z-2022-02-21t00-07-33z, where
// the first datetime is the watermark and the second one is the time when the RDE beam job
// launched. We search for the latest folder that starts with "rde-[watermark]".
String partialPrefix =
String.format("rde-%s", watermark.toString("yyyy-MM-dd't'HH-mm-ss'z'"));
String latestFilenameSuffix =
gcsUtils.listFolderObjects(bucket, partialPrefix).stream()
.max(Ordering.natural())
.orElse(null);
if (latestFilenameSuffix == null) {
throw new NoContentException(
String.format("RDE deposit for TLD %s on %s does not exist", tld, watermark));
}
int firstSlashPosition = latestFilenameSuffix.indexOf('/');
prefix =
Optional.of(partialPrefix + latestFilenameSuffix.substring(0, firstSlashPosition + 1));
prefix = Optional.of(findMostRecentPrefixForWatermark(watermark, bucket, tld, gcsUtils));
}
logger.atInfo().log("Verifying readiness to upload the RDE deposit.");
Optional<Cursor> cursor =
@@ -193,7 +177,7 @@ public final class RdeUploadAction implements Runnable, EscrowTask {
() -> new IllegalStateException("RdeRevision was not set on generated deposit"));
final String nameWithoutPrefix =
RdeNamingUtils.makeRydeFilename(tld, watermark, FULL, 1, revision);
final String name = prefix.orElse("") + nameWithoutPrefix;
final String name = prefix.get() + nameWithoutPrefix;
final BlobId xmlFilename = BlobId.of(bucket, name + ".xml.ghostryde");
final BlobId xmlLengthFilename = BlobId.of(bucket, name + ".xml.length");
BlobId reportFilename = BlobId.of(bucket, name + "-report.xml.ghostryde");
@@ -17,9 +17,12 @@ package google.registry.rde;
import static google.registry.util.HexDumper.dumpHex;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.collect.Ordering;
import com.google.common.io.BaseEncoding;
import com.google.re2j.Matcher;
import com.google.re2j.Pattern;
import google.registry.gcs.GcsUtils;
import google.registry.request.HttpException.NoContentException;
import google.registry.xjc.rde.XjcRdeRrType;
import google.registry.xml.XmlException;
import java.io.BufferedInputStream;
@@ -31,7 +34,7 @@ import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
/** Helper methods for RDE. */
public final class RdeUtil {
public final class RdeUtils {
/** Number of bytes in head of XML deposit that will contain the information we want. */
private static final int PEEK_SIZE = 2048;
@@ -70,6 +73,32 @@ public final class RdeUtil {
return DATETIME_FORMATTER.parseDateTime(watermarkMatcher.group(1));
}
/** Find the most recent folder in the given GCS bucket for the given watermark. */
public static String findMostRecentPrefixForWatermark(
DateTime watermark, String bucket, String tld, GcsUtils gcsUtils) throws NoContentException {
// The prefix is always in the format of: rde-2022-02-21t00-00-00z-2022-02-21t00-07-33z, where
// the first datetime is the watermark and the second one is the time when the RDE beam job
// launched. We search for the latest folder that starts with "rde-[watermark]".
String partialPrefix = String.format("rde-%s", watermark.toString("yyyy-MM-dd't'HH-mm-ss'z'"));
String latestFilenameSuffix = null;
try {
latestFilenameSuffix =
gcsUtils.listFolderObjects(bucket, partialPrefix).stream()
.max(Ordering.natural())
.orElse(null);
} catch (IOException e) {
throw new NoContentException(
String.format(
"Error reading folders starting with %s in bucket %s", partialPrefix, bucket));
}
if (latestFilenameSuffix == null) {
throw new NoContentException(
String.format("RDE deposit for TLD %s on %s does not exist", tld, watermark));
}
int firstSlashPosition = latestFilenameSuffix.indexOf('/');
return partialPrefix + latestFilenameSuffix.substring(0, firstSlashPosition + 1);
}
/**
* Generates an ID matching the regex {@code \w&lbrace;1,13&rbrace; } from a millisecond
* timestamp.
@@ -89,5 +118,5 @@ public final class RdeUtil {
return bean;
}
private RdeUtil() {}
private RdeUtils() {}
}
@@ -16,7 +16,7 @@ package google.registry.reporting.icann;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.net.MediaType.CSV_UTF_8;
import static google.registry.model.tld.Registries.assertTldExists;
import static google.registry.model.tld.Tlds.assertTldExists;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.api.client.http.ByteArrayContent;
@@ -29,9 +29,9 @@ import google.registry.config.RegistryConfig.Config;
import google.registry.gcs.GcsUtils;
import google.registry.model.common.Cursor;
import google.registry.model.common.Cursor.CursorType;
import google.registry.model.tld.Registries;
import google.registry.model.tld.Tld;
import google.registry.model.tld.Tld.TldType;
import google.registry.model.tld.Tlds;
import google.registry.persistence.VKey;
import google.registry.request.Action;
import google.registry.request.HttpException.ServiceUnavailableException;
@@ -203,7 +203,7 @@ public final class IcannReportingUploadAction implements Runnable {
/** Returns a map of each cursor to the tld. */
private ImmutableMap<Cursor, String> loadCursors() {
ImmutableSet<Tld> registries = Registries.getTldEntitiesOfType(TldType.REAL);
ImmutableSet<Tld> registries = Tlds.getTldEntitiesOfType(TldType.REAL);
ImmutableMap<VKey<? extends Cursor>, Tld> activityKeyMap =
loadKeyMap(registries, CursorType.ICANN_UPLOAD_ACTIVITY);
@@ -17,8 +17,8 @@ package google.registry.request;
import static com.google.common.net.MediaType.JSON_UTF_8;
import static google.registry.dns.PublishDnsUpdatesAction.APP_ENGINE_RETRY_HEADER;
import static google.registry.dns.PublishDnsUpdatesAction.CLOUD_TASKS_RETRY_HEADER;
import static google.registry.model.tld.Registries.assertTldExists;
import static google.registry.model.tld.Registries.assertTldsExist;
import static google.registry.model.tld.Tlds.assertTldExists;
import static google.registry.model.tld.Tlds.assertTldsExist;
import static google.registry.request.RequestParameters.extractOptionalHeader;
import static google.registry.request.RequestParameters.extractRequiredParameter;
import static google.registry.request.RequestParameters.extractSetOfParameters;
@@ -14,7 +14,7 @@
package google.registry.tools;
import static google.registry.model.tld.Registries.assertTldsExist;
import static google.registry.model.tld.Tlds.assertTldsExist;
import static google.registry.persistence.transaction.QueryComposer.Comparator;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
@@ -16,7 +16,7 @@ package google.registry.tools;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Strings.isNullOrEmpty;
import static google.registry.model.tld.Registries.findTldForNameOrThrow;
import static google.registry.model.tld.Tlds.findTldForNameOrThrow;
import static google.registry.pricing.PricingEngineProxy.getDomainCreateCost;
import static google.registry.util.StringGenerator.DEFAULT_PASSWORD_LENGTH;
import static org.joda.time.DateTimeZone.UTC;
@@ -28,10 +28,10 @@ import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Sets;
import google.registry.model.pricing.StaticPremiumListPricingEngine;
import google.registry.model.tld.Registries;
import google.registry.model.tld.Tld;
import google.registry.model.tld.Tld.TldState;
import google.registry.model.tld.Tld.TldType;
import google.registry.model.tld.Tlds;
import google.registry.model.tld.label.PremiumList;
import google.registry.model.tld.label.PremiumListDao;
import google.registry.tldconfig.idn.IdnTableEnum;
@@ -459,8 +459,8 @@ abstract class CreateOrUpdateTldCommand extends MutatingCommand {
} finally {
// Manually reset the cache here so that subsequent commands (e.g. in SetupOteCommand) see
// the latest version of the data.
// TODO(b/24903801): change all those places to use uncached code paths to get Registries.
Registries.resetCache();
// TODO(b/24903801): change all those places to use uncached code paths to get TLDs.
Tlds.resetCache();
}
}
@@ -15,7 +15,7 @@
package google.registry.tools;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.model.tld.Registries.assertTldExists;
import static google.registry.model.tld.Tlds.assertTldExists;
import static google.registry.util.ListNamingUtils.convertFilePathToName;
import static java.nio.charset.StandardCharsets.UTF_8;
@@ -15,7 +15,7 @@
package google.registry.tools;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.model.tld.Registries.assertTldExists;
import static google.registry.model.tld.Tlds.assertTldExists;
import static google.registry.util.ListNamingUtils.convertFilePathToName;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.joda.time.DateTimeZone.UTC;
@@ -16,7 +16,7 @@ package google.registry.tools;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static google.registry.model.tld.Registries.getTlds;
import static google.registry.model.tld.Tlds.getTlds;
import static google.registry.util.CollectionUtils.nullToEmpty;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
@@ -18,7 +18,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Strings.nullToEmpty;
import static com.google.common.collect.Maps.filterValues;
import static com.google.common.io.Resources.getResource;
import static google.registry.model.tld.Registries.findTldForNameOrThrow;
import static google.registry.model.tld.Tlds.findTldForNameOrThrow;
import static google.registry.tools.CommandUtilities.addHeader;
import static google.registry.util.DomainNameUtils.canonicalizeHostname;
import static google.registry.util.PreconditionsUtils.checkArgumentPresent;
@@ -20,7 +20,7 @@ import com.google.common.io.ByteStreams;
import google.registry.keyring.api.KeyModule.Key;
import google.registry.model.rde.RdeMode;
import google.registry.model.rde.RdeNamingUtils;
import google.registry.rde.RdeUtil;
import google.registry.rde.RdeUtils;
import google.registry.rde.RydeEncoder;
import google.registry.xml.XmlException;
import java.io.BufferedInputStream;
@@ -59,7 +59,7 @@ final class EscrowDepositEncryptor {
throws IOException, XmlException {
try (InputStream xmlFileInput = Files.newInputStream(xmlFile);
BufferedInputStream xmlInput = new BufferedInputStream(xmlFileInput, PEEK_BUFFER_SIZE)) {
DateTime watermark = RdeUtil.peekWatermark(xmlInput);
DateTime watermark = RdeUtils.peekWatermark(xmlInput);
String name = RdeNamingUtils.makeRydeFilename(tld, watermark, mode, 1, revision);
Path rydePath = outdir.resolve(name + ".ryde");
Path sigPath = outdir.resolve(name + ".sig");
@@ -16,7 +16,7 @@ package google.registry.tools;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.io.BaseEncoding.base16;
import static google.registry.model.tld.Registries.assertTldExists;
import static google.registry.model.tld.Tlds.assertTldExists;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.isBeforeOrAt;
import static java.nio.charset.StandardCharsets.US_ASCII;
@@ -14,7 +14,7 @@
package google.registry.tools;
import static google.registry.model.tld.Registries.assertTldsExist;
import static google.registry.model.tld.Tlds.assertTldsExist;
import static google.registry.rde.RdeModule.PARAM_DIRECTORY;
import static google.registry.rde.RdeModule.PARAM_LENIENT;
import static google.registry.rde.RdeModule.PARAM_MANUAL;
@@ -14,7 +14,7 @@
package google.registry.tools;
import static google.registry.model.tld.Registries.assertTldsExist;
import static google.registry.model.tld.Tlds.assertTldsExist;
import static org.joda.time.DateTimeZone.UTC;
import static org.joda.time.Duration.standardMinutes;
@@ -14,7 +14,7 @@
package google.registry.tools;
import static google.registry.model.tld.Registries.assertTldsExist;
import static google.registry.model.tld.Tlds.assertTldsExist;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
@@ -23,9 +23,9 @@ import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import google.registry.model.common.Cursor;
import google.registry.model.common.Cursor.CursorType;
import google.registry.model.tld.Registries;
import google.registry.model.tld.Tld;
import google.registry.model.tld.Tld.TldType;
import google.registry.model.tld.Tlds;
import google.registry.persistence.VKey;
import java.util.Map;
import java.util.Optional;
@@ -53,7 +53,7 @@ final class ListCursorsCommand implements Command {
public void run() {
Map<String, VKey<Cursor>> cursorKeys =
cursorType.isScoped()
? Registries.getTlds().stream()
? Tlds.getTlds().stream()
.map(Tld::get)
.filter(r -> r.getTldType() == filterTldType)
.filter(r -> !filterEscrowEnabled || r.getEscrowEnabled())
@@ -15,7 +15,7 @@
package google.registry.tools;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.model.tld.Registries.getTldsOfType;
import static google.registry.model.tld.Tlds.getTldsOfType;
import static google.registry.util.CollectionUtils.isNullOrEmpty;
import com.beust.jcommander.Parameter;
@@ -20,7 +20,7 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.net.MediaType;
import google.registry.loadtest.LoadTestAction;
import google.registry.model.registrar.Registrar;
import google.registry.model.tld.Registries;
import google.registry.model.tld.Tlds;
/** Command to initiate a load-test. */
@Parameters(separators = " =", commandDescription = "Run a load test.")
@@ -91,7 +91,7 @@ class LoadTestCommand extends ConfirmingCommand implements CommandWithConnection
}
// Check validity of TLD and Client Id.
if (!Registries.getTlds().contains(tld)) {
if (!Tlds.getTlds().contains(tld)) {
System.err.printf("No such TLD: %s\n", tld);
return false;
}
@@ -18,7 +18,7 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.Sets.difference;
import static com.google.common.collect.Sets.intersection;
import static com.google.common.collect.Sets.union;
import static google.registry.model.tld.Registries.assertTldExists;
import static google.registry.model.tld.Tlds.assertTldExists;
import static google.registry.util.CollectionUtils.nullToEmpty;
import com.beust.jcommander.Parameter;
@@ -16,7 +16,7 @@ package google.registry.tools.server;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static google.registry.model.tld.Registries.assertTldsExist;
import static google.registry.model.tld.Tlds.assertTldsExist;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.request.Action.Method.GET;
import static google.registry.request.Action.Method.POST;
@@ -15,7 +15,7 @@
package google.registry.tools.server;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static google.registry.model.tld.Registries.getTlds;
import static google.registry.model.tld.Tlds.getTlds;
import static google.registry.request.Action.Method.GET;
import static google.registry.request.Action.Method.POST;
@@ -16,7 +16,7 @@ package google.registry.tools.server;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.dns.DnsUtils.requestDomainDnsRefresh;
import static google.registry.model.tld.Registries.assertTldsExist;
import static google.registry.model.tld.Tlds.assertTldsExist;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.request.RequestParameters.PARAM_TLDS;
@@ -15,8 +15,8 @@
package google.registry.whois;
import static com.google.common.base.Preconditions.checkNotNull;
import static google.registry.model.tld.Registries.findTldForName;
import static google.registry.model.tld.Registries.getTlds;
import static google.registry.model.tld.Tlds.findTldForName;
import static google.registry.model.tld.Tlds.getTlds;
import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
import com.google.common.annotations.VisibleForTesting;
@@ -25,7 +25,7 @@ import com.google.common.collect.Streams;
import com.google.common.net.InetAddresses;
import com.google.common.net.InternetDomainName;
import google.registry.model.host.Host;
import google.registry.model.tld.Registries;
import google.registry.model.tld.Tlds;
import java.net.InetAddress;
import org.joda.time.DateTime;
@@ -72,8 +72,7 @@ final class NameserverLookupByIpCommand implements WhoisCommand {
Streams.stream(hostsFromDb)
.filter(
host ->
Registries.findTldForName(InternetDomainName.from(host.getHostName()))
.isPresent())
Tlds.findTldForName(InternetDomainName.from(host.getHostName())).isPresent())
.collect(toImmutableList());
if (hosts.isEmpty()) {
throw new WhoisException(now, SC_NOT_FOUND, "No nameservers found.");
@@ -16,7 +16,7 @@ package google.registry.whois;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Strings.isNullOrEmpty;
import static google.registry.model.tld.Registries.findTldForName;
import static google.registry.model.tld.Tlds.findTldForName;
import static google.registry.util.DomainNameUtils.canonicalizeHostname;
import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
@@ -42,9 +42,9 @@ import google.registry.config.RegistryConfig;
import google.registry.model.EntityTestCase;
import google.registry.model.registrar.Registrar.State;
import google.registry.model.registrar.Registrar.Type;
import google.registry.model.tld.Registries;
import google.registry.model.tld.Tld;
import google.registry.model.tld.Tld.TldType;
import google.registry.model.tld.Tlds;
import google.registry.util.CidrAddressBlock;
import google.registry.util.SerializeUtils;
import java.math.BigDecimal;
@@ -603,14 +603,14 @@ class RegistrarTest extends EntityTestCase {
// Cache duration in tests is 0. To make sure the data isn't in the cache we have to set it
// to a higher value and reset the cache.
RegistryConfig.CONFIG_SETTINGS.get().caching.singletonCacheRefreshSeconds = 600;
Registries.resetCache();
Tlds.resetCache();
// Make sure the TLD we want to create doesn't exist yet.
// This is also important because getTlds fills out the cache when used.
assertThat(Registries.getTlds()).doesNotContain("newtld");
assertThat(Tlds.getTlds()).doesNotContain("newtld");
// We can't use createTld here because it fails when the cache is used.
persistResource(newTld("newtld", "NEWTLD"));
// Make sure we set up the cache correctly, so the newly created TLD isn't in the cache
assertThat(Registries.getTlds()).doesNotContain("newtld");
assertThat(Tlds.getTlds()).doesNotContain("newtld");
// Test that the uncached version works
assertThat(
@@ -633,11 +633,11 @@ class RegistrarTest extends EntityTestCase {
// Make sure the cache hasn't expired during the test and "newtld" is still not in the cached
// TLDs
assertThat(Registries.getTlds()).doesNotContain("newtld");
assertThat(Tlds.getTlds()).doesNotContain("newtld");
} finally {
RegistryConfig.CONFIG_SETTINGS.get().caching.singletonCacheRefreshSeconds =
origSingletonCacheRefreshSeconds;
Registries.resetCache();
Tlds.resetCache();
}
}
@@ -28,8 +28,8 @@ import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationT
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link Registries}. */
class RegistriesTest {
/** Unit tests for {@link Tlds}. */
class TldsTest {
@RegisterExtension
final JpaIntegrationTestExtension jpa =
@@ -42,51 +42,51 @@ class RegistriesTest {
@Test
void testGetTlds() {
initTestTlds();
assertThat(Registries.getTlds()).containsExactly("foo", "a.b.c");
assertThat(Tlds.getTlds()).containsExactly("foo", "a.b.c");
}
@Test
void test_getTldEntities() {
initTestTlds();
persistResource(newTld("testtld", "TESTTLD").asBuilder().setTldType(TldType.TEST).build());
assertThat(Registries.getTldEntitiesOfType(TldType.REAL))
assertThat(Tlds.getTldEntitiesOfType(TldType.REAL))
.containsExactly(Tld.get("foo"), Tld.get("a.b.c"));
assertThat(Registries.getTldEntitiesOfType(TldType.TEST)).containsExactly(Tld.get("testtld"));
assertThat(Tlds.getTldEntitiesOfType(TldType.TEST)).containsExactly(Tld.get("testtld"));
}
@Test
void testGetTlds_withNoRegistriesPersisted_returnsEmptySet() {
assertThat(Registries.getTlds()).isEmpty();
assertThat(Tlds.getTlds()).isEmpty();
}
@Test
void testAssertTldExists_doesExist() {
initTestTlds();
Registries.assertTldExists("foo");
Registries.assertTldExists("a.b.c");
Tlds.assertTldExists("foo");
Tlds.assertTldExists("a.b.c");
}
@Test
void testAssertTldExists_doesntExist() {
initTestTlds();
assertThrows(IllegalArgumentException.class, () -> Registries.assertTldExists("baz"));
assertThrows(IllegalArgumentException.class, () -> Tlds.assertTldExists("baz"));
}
@Test
void testFindTldForName() {
initTestTlds();
assertThat(Registries.findTldForName(InternetDomainName.from("example.foo")).get().toString())
assertThat(Tlds.findTldForName(InternetDomainName.from("example.foo")).get().toString())
.isEqualTo("foo");
assertThat(Registries.findTldForName(InternetDomainName.from("x.y.a.b.c")).get().toString())
assertThat(Tlds.findTldForName(InternetDomainName.from("x.y.a.b.c")).get().toString())
.isEqualTo("a.b.c");
// We don't have an "example" tld.
assertThat(Registries.findTldForName(InternetDomainName.from("foo.example"))).isEmpty();
assertThat(Tlds.findTldForName(InternetDomainName.from("foo.example"))).isEmpty();
// A tld is not a match for itself.
assertThat(Registries.findTldForName(InternetDomainName.from("foo"))).isEmpty();
assertThat(Tlds.findTldForName(InternetDomainName.from("foo"))).isEmpty();
// The name must match the entire tld.
assertThat(Registries.findTldForName(InternetDomainName.from("x.y.a.b"))).isEmpty();
assertThat(Registries.findTldForName(InternetDomainName.from("x.y.b.c"))).isEmpty();
assertThat(Tlds.findTldForName(InternetDomainName.from("x.y.a.b"))).isEmpty();
assertThat(Tlds.findTldForName(InternetDomainName.from("x.y.b.c"))).isEmpty();
// Substring tld matches aren't considered.
assertThat(Registries.findTldForName(InternetDomainName.from("example.barfoo"))).isEmpty();
assertThat(Tlds.findTldForName(InternetDomainName.from("example.barfoo"))).isEmpty();
}
}
@@ -63,6 +63,7 @@ import google.registry.xjc.rdereport.XjcRdeReportReport;
import google.registry.xml.XmlException;
import java.io.ByteArrayInputStream;
import java.net.SocketTimeoutException;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Optional;
import org.bouncycastle.openpgp.PGPPublicKey;
@@ -95,7 +96,7 @@ public class RdeReportActionTest {
new FakeKeyringModule().get().getRdeStagingEncryptionKey();
private final GcsUtils gcsUtils = new GcsUtils(LocalStorageHelper.getOptions());
private final BlobId reportFile =
BlobId.of("tub", "test_2006-06-06_full_S1_R0-report.xml.ghostryde");
BlobId.of("tub", "job-name/test_2006-06-06_full_S1_R0-report.xml.ghostryde");
private Tld registry;
private RdeReportAction createAction() {
@@ -114,7 +115,7 @@ public class RdeReportActionTest {
action.timeout = standardSeconds(30);
action.stagingDecryptionKey = new FakeKeyringModule().get().getRdeStagingDecryptionKey();
action.runner = runner;
action.prefix = Optional.empty();
action.prefix = Optional.of("job-name/");
return action;
}
@@ -170,11 +171,54 @@ public class RdeReportActionTest {
when(httpResponse.getContent()).thenReturn(IIRDEA_GOOD_XML.read());
when(urlFetchService.fetch(request.capture())).thenReturn(httpResponse);
RdeReportAction action = createAction();
action.prefix = Optional.of("job-name/");
action.runWithLock(loadRdeReportCursor());
assertThat(response.getStatus()).isEqualTo(200);
assertThat(response.getContentType()).isEqualTo(PLAIN_TEXT_UTF_8);
assertThat(response.getPayload()).isEqualTo("OK test 2006-06-06T00:00:00.000Z\n");
// Verify the HTTP request was correct.
assertThat(request.getValue().getMethod()).isSameInstanceAs(PUT);
assertThat(request.getValue().getURL().getProtocol()).isEqualTo("https");
assertThat(request.getValue().getURL().getPath()).endsWith("/test/20101017001");
Map<String, String> headers = mapifyHeaders(request.getValue().getHeaders());
assertThat(headers).containsEntry("CONTENT_TYPE", "text/xml");
assertThat(headers).containsEntry("AUTHORIZATION", "Basic dGVzdF9yeTpmb28=");
// Verify the payload XML was the same as what's in testdata/report.xml.
XjcRdeReportReport report = parseReport(request.getValue().getPayload());
assertThat(report.getId()).isEqualTo("20101017001");
assertThat(report.getCrDate()).isEqualTo(DateTime.parse("2010-10-17T00:15:00.0Z"));
assertThat(report.getWatermark()).isEqualTo(DateTime.parse("2010-10-17T00:00:00Z"));
}
@Test
void testRunWithLock_withoutPrefix_noPrefixFound() throws Exception {
RdeReportAction action = createAction();
action.prefix = Optional.empty();
assertThrows(NoContentException.class, () -> action.runWithLock(loadRdeReportCursor()));
}
@Test
void testRunWithLock_withoutPrefix() throws Exception {
when(httpResponse.getResponseCode()).thenReturn(SC_OK);
when(httpResponse.getContent()).thenReturn(IIRDEA_GOOD_XML.read());
when(urlFetchService.fetch(request.capture())).thenReturn(httpResponse);
RdeReportAction action = createAction();
action.prefix = Optional.empty();
gcsUtils.delete(reportFile);
BlobId otherReportFile1 =
BlobId.of(
"tub", "rde-2006-06-06t00-00-00z-1/test_2006-06-06_full_S1_R0-report.xml.ghostryde");
BlobId otherReportFile2 =
BlobId.of(
"tub", "rde-2006-06-06t00-00-00z-2/test_2006-06-06_full_S1_R1-report.xml.ghostryde");
// This file's content is not correct, if it is read, the action should throw.
gcsUtils.createFromBytes(
BlobId.of("tub", "job-name/test_2006-06-06_full_S1_R0-report.xml.ghostryde"),
Ghostryde.encode(REPORT_XML.read(), encryptKey));
otherReportFile1,
Ghostryde.encode(
ByteSource.wrap("BAD DATA".getBytes(StandardCharsets.UTF_8)).read(), encryptKey));
gcsUtils.createFromBytes(otherReportFile2, Ghostryde.encode(REPORT_XML.read(), encryptKey));
tm().transact(() -> RdeRevision.saveRevision("test", DateTime.parse("2006-06-06TZ"), FULL, 1));
action.runWithLock(loadRdeReportCursor());
assertThat(response.getStatus()).isEqualTo(200);
assertThat(response.getContentType()).isEqualTo(PLAIN_TEXT_UTF_8);
@@ -198,7 +242,7 @@ public class RdeReportActionTest {
@Test
void testRunWithLock_regeneratedReport() throws Exception {
gcsUtils.delete(reportFile);
BlobId newReport = BlobId.of("tub", "test_2006-06-06_full_S1_R1-report.xml.ghostryde");
BlobId newReport = BlobId.of("tub", "job-name/test_2006-06-06_full_S1_R1-report.xml.ghostryde");
PGPPublicKey encryptKey = new FakeKeyringModule().get().getRdeStagingEncryptionKey();
gcsUtils.createFromBytes(newReport, Ghostryde.encode(REPORT_XML.read(), encryptKey));
tm().transact(() -> RdeRevision.saveRevision("test", DateTime.parse("2006-06-06TZ"), FULL, 1));
@@ -343,7 +343,7 @@ public class RdeUploadActionTest {
gcsUtils.delete(GHOSTRYDE_FILE);
gcsUtils.delete(LENGTH_FILE);
gcsUtils.delete(REPORT_FILE);
// Add a folder that is alphabetically before the desired folder and fill it will nonsense data.
// Add a folder that is alphabetically before the desired folder and fill it with nonsense data.
// It should NOT be picked up.
BlobId ghostrydeFileWithPrefixBefore =
BlobId.of("bucket", JOB_PREFIX + "-job-nama/tld_2010-10-17_full_S1_R0.xml.ghostryde");
@@ -464,7 +464,7 @@ public class RdeUploadActionTest {
action.sftpCooldown = standardHours(2);
DateTime stagingCursor = DateTime.parse("2010-10-18TZ");
DateTime uploadCursor = DateTime.parse("2010-10-17TZ");
DateTime sftpCursor = uploadCursor.minusMinutes(97); // Within the 2 hour cooldown period.
DateTime sftpCursor = uploadCursor.minusMinutes(97); // Within the 2-hour cooldown period.
persistResource(Cursor.createScoped(RDE_STAGING, stagingCursor, Tld.get("tld")));
persistResource(Cursor.createScoped(RDE_UPLOAD_SFTP, sftpCursor, Tld.get("tld")));
NoContentException thrown =
@@ -477,7 +477,7 @@ public class RdeUploadActionTest {
+ " ago)");
}
private String slurp(InputStream is) throws IOException {
private static String slurp(InputStream is) throws IOException {
return CharStreams.toString(new InputStreamReader(is, UTF_8));
}
}
@@ -19,7 +19,7 @@ import static com.google.common.truth.Truth8.assertThat;
import static google.registry.model.EppResourceUtils.loadByForeignKeyCached;
import static google.registry.model.registrar.Registrar.State.ACTIVE;
import static google.registry.model.registrar.Registrar.Type.PDT;
import static google.registry.model.tld.Registries.getTlds;
import static google.registry.model.tld.Tlds.getTlds;
import static google.registry.testing.DatabaseHelper.createTlds;
import static google.registry.testing.DatabaseHelper.loadRegistrar;
import static google.registry.testing.DatabaseHelper.persistActiveDomain;
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1
View File
@@ -141,3 +141,4 @@ V140__rename_process_time_column_in_dns_refresh_request_table.sql
V141__add_ttl_columns_to_tld.sql
V142__drop_request_log_id.sql
V143__idn_per_tld.sql
V144__drop_database_migration_state_schedule_table.sql
@@ -0,0 +1,15 @@
-- Copyright 2023 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.
DROP TABLE "DatabaseMigrationStateSchedule";
@@ -318,16 +318,6 @@ CREATE TABLE public."Cursor" (
);
--
-- Name: DatabaseMigrationStateSchedule; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public."DatabaseMigrationStateSchedule" (
id bigint NOT NULL,
migration_transitions public.hstore
);
--
-- Name: DelegationSignerData; Type: TABLE; Schema: public; Owner: -
--
@@ -1301,14 +1291,6 @@ ALTER TABLE ONLY public."Cursor"
ADD CONSTRAINT "Cursor_pkey" PRIMARY KEY (scope, type);
--
-- Name: DatabaseMigrationStateSchedule DatabaseMigrationStateSchedule_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public."DatabaseMigrationStateSchedule"
ADD CONSTRAINT "DatabaseMigrationStateSchedule_pkey" PRIMARY KEY (id);
--
-- Name: DelegationSignerData DelegationSignerData_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
@@ -1572,13 +1554,6 @@ ALTER TABLE ONLY public."User"
CREATE INDEX allocation_token_domain_name_idx ON public."AllocationToken" USING btree (domain_name);
--
-- Name: database_migration_state_schedule_singleton; Type: INDEX; Schema: public; Owner: -
--
CREATE UNIQUE INDEX database_migration_state_schedule_singleton ON public."DatabaseMigrationStateSchedule" USING btree ((true));
--
-- Name: domain_history_to_ds_data_history_idx; Type: INDEX; Schema: public; Owner: -
--
+25
View File
@@ -0,0 +1,25 @@
# Registry Console Swagger API
This is the Swagger-based Registry Console API documentation. The project endpoints documentation in json format can be found in `console-api-swagger.json`, rest of the files in the folder compose Swagger standalone distributive stripped to bare miminum necessary to start the Swagger UI.
## How to run Swagger to view the endpoints documentation
Since Swagger standalone distributive is nothing but a simple static website it's extremely easy to get it started and view the documentation in a matter of seconds.
Note - just a simple opening of `index.html` wouldn't be enough, as with any static website, it'd not be able to handle relative resources requests therefore succesfully render Swagger UI. For this reason it's configured to spin off a simple node.js based http server to serve Swagger UI resources. The following steps required to succesfully start the Swagger UI:
* Install npm dependencies - `npm install`
* Run - `npm run swagger`
* Make changes in `console-api-swagger.json`
* Upon making changes make sure your browser cache is turned off
## How to update the Swagger UI
In order to update Swagger version the following steps should to be taken:
* [Download](https://swagger.io/docs/open-source-tools/swagger-ui/usage/installation/) Swagger standalone distributive
* Remove `.map.*` files as they are only needed to debug Swagger UI and not to run it
* Add the link to Console API Swagger documentation file - `console-api-swagger.json` to the `swagger-initializer.js`
* Copy with replace into the current directory
@@ -0,0 +1,351 @@
{
"swagger": "2.0",
"info": {
"title": "Registry Console API",
"version": "1.0.0"
},
"schemes": [
"https"
],
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"paths": {
"/console-api/user": {
"get": {
"summary": "Provides user type to UI",
"responses": {
"200": {
"schema": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum":[
"ADMIN",
"USER"
]
}
}
}
}
}
}
},
"/console-api/poll": {
"post": {
"summary": "Every T minutes (1?) request/response to keep front-end in sync with the back-end",
"parameters": [{
"name": "version",
"in": "body",
"required": true,
"type": "string",
"format": "string"
}, {
"name": "registrarId",
"in": "body",
"required": false,
"type": "string",
"format": "string"
}, {
"name": "notificationId",
"in": "body",
"required": false,
"type": "string",
"format": "string"
}],
"responses": {
"200": {
"schema": {
"type": "array",
"items": {
"type": "object",
"properties": {
"notificationText": {
"type": "string"
},
"notificationId": {
"type": "string"
},
"dismissable": {
"type": "boolean"
}
}
}
}
}
}
}
},
"/console-api/registrars": {
"get": {
"summary": "Provides list of available registrars to UI",
"responses": {
"200": {
"schema": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"registrarId": {
"type": "string"
}
}
}
}
}
}
}
},
"/console-api/domains": {
"get": {
"summary": "GET list of domains per registrar with pagination and filters",
"parameters": [{
"name": "registrarId",
"in": "query",
"required": false,
"type": "string",
"format": "string"
}, {
"name": "limit",
"in": "query",
"required": false,
"type": "number",
"default": 10
}, {
"name": "marker",
"description": "Name of the last domain retrieved by the user",
"in": "query",
"required": false,
"type": "string"
}, {
"name": "filterBy",
"in": "query",
"required": false,
"content": {
"schema": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"tld": {
"type":"array",
"items": {
"type":"string"
}
},
"status":{
"type":"array",
"items": {
"type":"string"
}
},
"isLocked": {
"type": "boolean"
}
}
}
}
}],
"responses": {
"200": {
"description": "Provides list of domains per registrar",
"schema": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"tld": {
"type": "string"
},
"status": {
"type": "array",
"items": {
"type": "string",
"enum":[
"CLIENT_DELETE_PROHIBITED",
"CLIENT_HOLD",
"CLIENT_RENEW_PROHIBITED",
"CLIENT_TRANSFER_PROHIBITED",
"CLIENT_UPDATE_PROHIBITED",
"INACTIVE",
"LINKED",
"OK",
"PENDING_CREATE",
"PENDING_DELETE",
"PENDING_TRANSFER",
"PENDING_UPDATE",
"SERVER_DELETE_PROHIBITED",
"SERVER_HOLD",
"SERVER_RENEW_PROHIBITED",
"SERVER_TRANSFER_PROHIBITED",
"SERVER_UPDATE_PROHIBITED"
]
}
},
"isLocked": {
"type": "boolean"
},
"creationTime": {
"type": "string"
},
"expirationTime": {
"type": "string"
}
}
}
}
}
}
}
},
"/console-api/domain": {
"post": {
"summary": "Apply action on a domain",
"responses": {
"200": {
"description": "Action has been succesfully applied"
}
},
"parameters": [
{
"name": "domain",
"in": "path",
"required": true,
"type": "string",
"format": "string"
},
{
"name": "registrarId",
"in": "body",
"required": false,
"type": "string",
"format": "string"
},
{
"name": "action",
"in": "body",
"required": true,
"type": "string",
"format": "string"
}
]
}
},
"/console-api/settings/contacts/get": {
"get": {
"summary": "GET settings contact page",
"responses": {
"200": {
"description": "Provides list of contacts per registrar",
"schema": {
"$ref": "#/definitions/settingsContacts"
}
}
},
"parameters": [
{
"name": "registrarId",
"in": "query",
"required": false,
"type": "string",
"format": "string"
}
]
}
},
"/console-api/settings/contacts/upd": {
"post": {
"summary": "Creates, updates or delete registrar contacts",
"responses": {
"200": {
"schema": {
"$ref": "#/definitions/settingsContacts"
}
}
},
"parameters": [
{
"name": "registrarId",
"in": "body",
"required": false,
"type": "string",
"format": "string"
},
{
"name": "contacts",
"in": "body",
"required": true,
"type": "array",
"schema": {
"$ref": "#/definitions/settingsContacts"
}
}
]
}
}
},
"definitions": {
"settingsContacts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"emailAddress": {
"type": "string"
},
"registrarId": {
"type": "string"
},
"registryLockEmailAddress": {
"type": "string"
},
"phoneNumber": {
"type": "string"
},
"faxNumber": {
"type": "string"
},
"types": {
"type": "string",
"enum": [
"ABUSE",
"ADMIN",
"BILLING",
"LEGAL",
"MARKETING",
"TECH",
"WHOIS"
]
},
"visibleInWhoisAsAdmin": {
"type": "boolean"
},
"visibleInWhoisAsTech": {
"type": "boolean"
},
"visibleInDomainWhoisAsAbuse": {
"type": "boolean"
},
"allowedToSetRegistryLockPassword": {
"type": "boolean"
}
}
}
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 628 B

+16
View File
@@ -0,0 +1,16 @@
html {
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
margin: 0;
background: #fafafa;
}
+19
View File
@@ -0,0 +1,19 @@
<!-- HTML for static distribution bundle build -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Swagger UI</title>
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" />
<link rel="stylesheet" type="text/css" href="index.css" />
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
</head>
<body>
<div id="swagger-ui"></div>
<script src="./swagger-ui-bundle.js" charset="UTF-8"> </script>
<script src="./swagger-ui-standalone-preset.js" charset="UTF-8"> </script>
<script src="./swagger-initializer.js" charset="UTF-8"> </script>
</body>
</html>
+780
View File
@@ -0,0 +1,780 @@
{
"name": "swagger",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "swagger",
"version": "1.0.0",
"license": "ISC",
"devDependencies": {
"http-server": "^14.1.1"
}
},
"node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/async": {
"version": "2.6.4",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
"integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
"dev": true,
"dependencies": {
"lodash": "^4.17.14"
}
},
"node_modules/basic-auth": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
"integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
"dev": true,
"dependencies": {
"safe-buffer": "5.1.2"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/call-bind": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
"dev": true,
"dependencies": {
"function-bind": "^1.1.1",
"get-intrinsic": "^1.0.2"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/corser": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz",
"integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==",
"dev": true,
"engines": {
"node": ">= 0.4.0"
}
},
"node_modules/debug": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"dev": true,
"dependencies": {
"ms": "^2.1.1"
}
},
"node_modules/eventemitter3": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
"dev": true
},
"node_modules/follow-redirects": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
"dev": true,
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
},
"node_modules/get-intrinsic": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz",
"integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==",
"dev": true,
"dependencies": {
"function-bind": "^1.1.1",
"has": "^1.0.3",
"has-proto": "^1.0.1",
"has-symbols": "^1.0.3"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"dev": true,
"dependencies": {
"function-bind": "^1.1.1"
},
"engines": {
"node": ">= 0.4.0"
}
},
"node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/has-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
"integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
"dev": true,
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-symbols": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
"dev": true,
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
"dev": true,
"bin": {
"he": "bin/he"
}
},
"node_modules/html-encoding-sniffer": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz",
"integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==",
"dev": true,
"dependencies": {
"whatwg-encoding": "^2.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/http-proxy": {
"version": "1.18.1",
"resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
"integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
"dev": true,
"dependencies": {
"eventemitter3": "^4.0.0",
"follow-redirects": "^1.0.0",
"requires-port": "^1.0.0"
},
"engines": {
"node": ">=8.0.0"
}
},
"node_modules/http-server": {
"version": "14.1.1",
"resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.1.tgz",
"integrity": "sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A==",
"dev": true,
"dependencies": {
"basic-auth": "^2.0.1",
"chalk": "^4.1.2",
"corser": "^2.0.1",
"he": "^1.2.0",
"html-encoding-sniffer": "^3.0.0",
"http-proxy": "^1.18.1",
"mime": "^1.6.0",
"minimist": "^1.2.6",
"opener": "^1.5.1",
"portfinder": "^1.0.28",
"secure-compare": "3.0.1",
"union": "~0.5.0",
"url-join": "^4.0.1"
},
"bin": {
"http-server": "bin/http-server"
},
"engines": {
"node": ">=12"
}
},
"node_modules/iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"dev": true,
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
"node_modules/mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
"dev": true,
"bin": {
"mime": "cli.js"
},
"engines": {
"node": ">=4"
}
},
"node_modules/minimist": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
"dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/mkdirp": {
"version": "0.5.6",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
"dev": true,
"dependencies": {
"minimist": "^1.2.6"
},
"bin": {
"mkdirp": "bin/cmd.js"
}
},
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true
},
"node_modules/object-inspect": {
"version": "1.12.3",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
"integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
"dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/opener": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz",
"integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==",
"dev": true,
"bin": {
"opener": "bin/opener-bin.js"
}
},
"node_modules/portfinder": {
"version": "1.0.32",
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz",
"integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==",
"dev": true,
"dependencies": {
"async": "^2.6.4",
"debug": "^3.2.7",
"mkdirp": "^0.5.6"
},
"engines": {
"node": ">= 0.12.0"
}
},
"node_modules/qs": {
"version": "6.11.1",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.1.tgz",
"integrity": "sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ==",
"dev": true,
"dependencies": {
"side-channel": "^1.0.4"
},
"engines": {
"node": ">=0.6"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/requires-port": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
"dev": true
},
"node_modules/safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"dev": true
},
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"dev": true
},
"node_modules/secure-compare": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz",
"integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==",
"dev": true
},
"node_modules/side-channel": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.0",
"get-intrinsic": "^1.0.2",
"object-inspect": "^1.9.0"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"dependencies": {
"has-flag": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/union": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz",
"integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==",
"dev": true,
"dependencies": {
"qs": "^6.4.0"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/url-join": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz",
"integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==",
"dev": true
},
"node_modules/whatwg-encoding": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz",
"integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==",
"dev": true,
"dependencies": {
"iconv-lite": "0.6.3"
},
"engines": {
"node": ">=12"
}
}
},
"dependencies": {
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"requires": {
"color-convert": "^2.0.1"
}
},
"async": {
"version": "2.6.4",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
"integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
"dev": true,
"requires": {
"lodash": "^4.17.14"
}
},
"basic-auth": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
"integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
"dev": true,
"requires": {
"safe-buffer": "5.1.2"
}
},
"call-bind": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
"dev": true,
"requires": {
"function-bind": "^1.1.1",
"get-intrinsic": "^1.0.2"
}
},
"chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"corser": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz",
"integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==",
"dev": true
},
"debug": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"dev": true,
"requires": {
"ms": "^2.1.1"
}
},
"eventemitter3": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
"dev": true
},
"follow-redirects": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
"dev": true
},
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
},
"get-intrinsic": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz",
"integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==",
"dev": true,
"requires": {
"function-bind": "^1.1.1",
"has": "^1.0.3",
"has-proto": "^1.0.1",
"has-symbols": "^1.0.3"
}
},
"has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"dev": true,
"requires": {
"function-bind": "^1.1.1"
}
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true
},
"has-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
"integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
"dev": true
},
"has-symbols": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
"dev": true
},
"he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
"dev": true
},
"html-encoding-sniffer": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz",
"integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==",
"dev": true,
"requires": {
"whatwg-encoding": "^2.0.0"
}
},
"http-proxy": {
"version": "1.18.1",
"resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
"integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
"dev": true,
"requires": {
"eventemitter3": "^4.0.0",
"follow-redirects": "^1.0.0",
"requires-port": "^1.0.0"
}
},
"http-server": {
"version": "14.1.1",
"resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.1.tgz",
"integrity": "sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A==",
"dev": true,
"requires": {
"basic-auth": "^2.0.1",
"chalk": "^4.1.2",
"corser": "^2.0.1",
"he": "^1.2.0",
"html-encoding-sniffer": "^3.0.0",
"http-proxy": "^1.18.1",
"mime": "^1.6.0",
"minimist": "^1.2.6",
"opener": "^1.5.1",
"portfinder": "^1.0.28",
"secure-compare": "3.0.1",
"union": "~0.5.0",
"url-join": "^4.0.1"
}
},
"iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"dev": true,
"requires": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
}
},
"lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
"mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
"dev": true
},
"minimist": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
"dev": true
},
"mkdirp": {
"version": "0.5.6",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
"dev": true,
"requires": {
"minimist": "^1.2.6"
}
},
"ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true
},
"object-inspect": {
"version": "1.12.3",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
"integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
"dev": true
},
"opener": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz",
"integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==",
"dev": true
},
"portfinder": {
"version": "1.0.32",
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz",
"integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==",
"dev": true,
"requires": {
"async": "^2.6.4",
"debug": "^3.2.7",
"mkdirp": "^0.5.6"
}
},
"qs": {
"version": "6.11.1",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.1.tgz",
"integrity": "sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ==",
"dev": true,
"requires": {
"side-channel": "^1.0.4"
}
},
"requires-port": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
"dev": true
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"dev": true
},
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"dev": true
},
"secure-compare": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz",
"integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==",
"dev": true
},
"side-channel": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
"dev": true,
"requires": {
"call-bind": "^1.0.0",
"get-intrinsic": "^1.0.2",
"object-inspect": "^1.9.0"
}
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"requires": {
"has-flag": "^4.0.0"
}
},
"union": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz",
"integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==",
"dev": true,
"requires": {
"qs": "^6.4.0"
}
},
"url-join": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz",
"integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==",
"dev": true
},
"whatwg-encoding": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz",
"integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==",
"dev": true,
"requires": {
"iconv-lite": "0.6.3"
}
}
}
}
+16
View File
@@ -0,0 +1,16 @@
{
"name": "swagger",
"version": "1.0.0",
"description": "",
"main": "swagger-initializer.js",
"scripts": {
"swagger": "http-server .",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"http-server": "^14.1.1"
}
}
@@ -0,0 +1,20 @@
window.onload = function() {
//<editor-fold desc="Changeable Configuration Block">
// the following lines will be replaced by docker/configurator, when it runs in a docker-container
window.ui = SwaggerUIBundle({
url: "./console-api-swagger.json",
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
});
//</editor-fold>
};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -58,8 +58,8 @@ public final class DomainNameUtils {
* <p>This function is compatible with multi-part tlds, e.g. {@code co.uk}. This function will
* also work on domains for which the registry is not authoritative. If you are certain that the
* input will be under a TLD this registry controls, then it is preferable to use {@link
* google.registry.model.tld.Registries#findTldForName(InternetDomainName)
* Registries#findTldForName}, which will work on hostnames in addition to domains.
* google.registry.model.tld.Tlds#findTldForName(InternetDomainName) Registries#findTldForName},
* which will work on hostnames in addition to domains.
*
* @param domainName must be a punycode SLD (not a host or unicode)
* @throws IllegalArgumentException if there is no TLD