mirror of
https://github.com/google/nomulus
synced 2026-02-11 23:31:37 +00:00
Compare commits
9 Commits
nomulus-20
...
tlds-20231
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e5e2370923 | ||
|
|
b3b0efd47e | ||
|
|
e82cbe60a9 | ||
|
|
923bc13e3a | ||
|
|
4893ea307b | ||
|
|
01f868cefc | ||
|
|
1b0919eaff | ||
|
|
92b23bac16 | ||
|
|
cc9b3f5965 |
@@ -1,7 +1,13 @@
|
||||
<div class="console-domains">
|
||||
<mat-form-field>
|
||||
<mat-label>Filter</mat-label>
|
||||
<input matInput (keyup)="applyFilter($event)" #input />
|
||||
<input
|
||||
type="search"
|
||||
matInput
|
||||
[(ngModel)]="searchTerm"
|
||||
(ngModelChange)="sendInput()"
|
||||
#input
|
||||
/>
|
||||
</mat-form-field>
|
||||
|
||||
<div *ngIf="isLoading; else domains_content" class="console-domains__loading">
|
||||
|
||||
@@ -18,6 +18,7 @@ import { BackendService } from '../shared/services/backend.service';
|
||||
import { MatPaginator, PageEvent } from '@angular/material/paginator';
|
||||
import { RegistrarService } from '../registrar/registrar.service';
|
||||
import { Domain, DomainListService } from './domainList.service';
|
||||
import { Subject, debounceTime } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'app-domain-list',
|
||||
@@ -27,6 +28,7 @@ import { Domain, DomainListService } from './domainList.service';
|
||||
})
|
||||
export class DomainListComponent {
|
||||
public static PATH = 'domain-list';
|
||||
private readonly DEBOUNCE_MS = 500;
|
||||
|
||||
displayedColumns: string[] = [
|
||||
'domainName',
|
||||
@@ -38,6 +40,9 @@ export class DomainListComponent {
|
||||
dataSource: MatTableDataSource<Domain> = new MatTableDataSource();
|
||||
isLoading = true;
|
||||
|
||||
searchTermSubject = new Subject<string>();
|
||||
searchTerm?: string;
|
||||
|
||||
pageNumber?: number;
|
||||
resultsPerPage = 50;
|
||||
totalResults?: number;
|
||||
@@ -52,13 +57,28 @@ export class DomainListComponent {
|
||||
|
||||
ngOnInit() {
|
||||
this.dataSource.paginator = this.paginator;
|
||||
// Don't spam the server unnecessarily while the user is typing
|
||||
this.searchTermSubject
|
||||
.pipe(debounceTime(this.DEBOUNCE_MS))
|
||||
.subscribe((searchTermValue) => {
|
||||
this.reloadData();
|
||||
});
|
||||
this.reloadData();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.searchTermSubject.complete();
|
||||
}
|
||||
|
||||
reloadData() {
|
||||
this.isLoading = true;
|
||||
this.domainListService
|
||||
.retrieveDomains(this.pageNumber, this.resultsPerPage, this.totalResults)
|
||||
.retrieveDomains(
|
||||
this.pageNumber,
|
||||
this.resultsPerPage,
|
||||
this.totalResults,
|
||||
this.searchTerm
|
||||
)
|
||||
.subscribe((domainListResult) => {
|
||||
this.dataSource.data = domainListResult.domains;
|
||||
this.totalResults = domainListResult.totalResults;
|
||||
@@ -66,10 +86,8 @@ export class DomainListComponent {
|
||||
});
|
||||
}
|
||||
|
||||
/** TODO: the backend will need to accept a filter string. */
|
||||
applyFilter(event: KeyboardEvent) {
|
||||
// const filterValue = (event.target as HTMLInputElement).value;
|
||||
this.reloadData();
|
||||
sendInput() {
|
||||
this.searchTermSubject.next(this.searchTerm!);
|
||||
}
|
||||
|
||||
onPageChange(event: PageEvent) {
|
||||
|
||||
@@ -47,7 +47,8 @@ export class DomainListService {
|
||||
retrieveDomains(
|
||||
pageNumber?: number,
|
||||
resultsPerPage?: number,
|
||||
totalResults?: number
|
||||
totalResults?: number,
|
||||
searchTerm?: string
|
||||
) {
|
||||
return this.backendService
|
||||
.getDomains(
|
||||
@@ -55,7 +56,8 @@ export class DomainListService {
|
||||
this.checkpointTime,
|
||||
pageNumber,
|
||||
resultsPerPage,
|
||||
totalResults
|
||||
totalResults,
|
||||
searchTerm
|
||||
)
|
||||
.pipe(
|
||||
tap((domainListResult: DomainListResult) => {
|
||||
|
||||
@@ -69,7 +69,8 @@ export class BackendService {
|
||||
checkpointTime?: string,
|
||||
pageNumber?: number,
|
||||
resultsPerPage?: number,
|
||||
totalResults?: number
|
||||
totalResults?: number,
|
||||
searchTerm?: string
|
||||
): Observable<DomainListResult> {
|
||||
var url = `/console-api/domain-list?registrarId=${registrarId}`;
|
||||
if (checkpointTime) {
|
||||
@@ -84,6 +85,9 @@ export class BackendService {
|
||||
if (totalResults) {
|
||||
url += `&totalResults=${totalResults}`;
|
||||
}
|
||||
if (searchTerm) {
|
||||
url += `&searchTerm=${searchTerm}`;
|
||||
}
|
||||
return this.http
|
||||
.get<DomainListResult>(url)
|
||||
.pipe(catchError((err) => this.errorCatcher<DomainListResult>(err)));
|
||||
|
||||
@@ -16,8 +16,8 @@ package google.registry.bsa;
|
||||
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static com.google.common.collect.Maps.transformValues;
|
||||
import static google.registry.model.tld.Tld.isEnrolledWithBsa;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
@@ -50,14 +50,6 @@ public class IdnChecker {
|
||||
allTlds = idnToTlds.values().stream().flatMap(ImmutableSet::stream).collect(toImmutableSet());
|
||||
}
|
||||
|
||||
// TODO(11/30/2023): Remove below when new Tld schema is deployed and the `getBsaEnrollStartTime`
|
||||
// method is no longer hardcoded.
|
||||
@VisibleForTesting
|
||||
IdnChecker(ImmutableMap<IdnTableEnum, ImmutableSet<Tld>> idnToTlds) {
|
||||
this.idnToTlds = idnToTlds;
|
||||
allTlds = idnToTlds.values().stream().flatMap(ImmutableSet::stream).collect(toImmutableSet());
|
||||
}
|
||||
|
||||
/** Returns all IDNs in which the {@code label} is valid. */
|
||||
ImmutableSet<IdnTableEnum> getAllValidIdns(String label) {
|
||||
return idnToTlds.keySet().stream()
|
||||
@@ -88,11 +80,6 @@ public class IdnChecker {
|
||||
return Sets.difference(allTlds, getSupportingTlds(idnTables));
|
||||
}
|
||||
|
||||
private static boolean isEnrolledWithBsa(Tld tld, DateTime now) {
|
||||
DateTime enrollTime = tld.getBsaEnrollStartTime();
|
||||
return enrollTime != null && enrollTime.isBefore(now);
|
||||
}
|
||||
|
||||
private static ImmutableMap<IdnTableEnum, ImmutableSet<Tld>> getIdnToTldMap(DateTime now) {
|
||||
ImmutableMultimap.Builder<IdnTableEnum, Tld> idnToTldMap = new ImmutableMultimap.Builder();
|
||||
Tlds.getTldEntitiesOfType(TldType.REAL).stream()
|
||||
|
||||
@@ -256,6 +256,11 @@ public class Tld extends ImmutableObject implements Buildable, UnsafeSerializabl
|
||||
return VKey.create(Tld.class, tldStr);
|
||||
}
|
||||
|
||||
/** Checks if {@code tld} is enrolled with BSA. */
|
||||
public static boolean isEnrolledWithBsa(Tld tld, DateTime now) {
|
||||
return tld.getBsaEnrollStartTime().orElse(END_OF_TIME).isBefore(now);
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of the pricing engine that this TLD uses.
|
||||
*
|
||||
@@ -550,9 +555,15 @@ public class Tld extends ImmutableObject implements Buildable, UnsafeSerializabl
|
||||
@JsonSerialize(using = SortedEnumSetSerializer.class)
|
||||
Set<IdnTableEnum> idnTables;
|
||||
|
||||
// TODO(11/30/2023): uncomment below two lines
|
||||
// /** The start time of this TLD's enrollment in the BSA program, if applicable. */
|
||||
// @JsonIgnore @Nullable DateTime bsaEnrollStartTime;
|
||||
/**
|
||||
* The start time of this TLD's enrollment in the BSA program, if applicable.
|
||||
*
|
||||
* <p>This property is excluded from source-based configuration and is managed directly in the
|
||||
* database.
|
||||
*/
|
||||
// TODO(b/309175410): implement setup and cleanup procedure for joining or leaving BSA, and see
|
||||
// if it can be integrated with the ConfigTldCommand.
|
||||
@JsonIgnore @Nullable DateTime bsaEnrollStartTime;
|
||||
|
||||
public String getTldStr() {
|
||||
return tldStr;
|
||||
@@ -574,12 +585,9 @@ public class Tld extends ImmutableObject implements Buildable, UnsafeSerializabl
|
||||
}
|
||||
|
||||
/** Returns the time when this TLD was enrolled in the Brand Safety Alliance (BSA) program. */
|
||||
@JsonIgnore // Annotation can be removed once we add the field and annotate it.
|
||||
@Nullable
|
||||
public DateTime getBsaEnrollStartTime() {
|
||||
// TODO(11/30/2023): uncomment below.
|
||||
// return this.bsaEnrollStartTime;
|
||||
return null;
|
||||
@JsonIgnore
|
||||
public Optional<DateTime> getBsaEnrollStartTime() {
|
||||
return Optional.ofNullable(this.bsaEnrollStartTime);
|
||||
}
|
||||
|
||||
/** Retrieve whether invoicing is enabled. */
|
||||
@@ -1101,10 +1109,9 @@ public class Tld extends ImmutableObject implements Buildable, UnsafeSerializabl
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setBsaEnrollStartTime(DateTime enrollTime) {
|
||||
public Builder setBsaEnrollStartTime(Optional<DateTime> enrollTime) {
|
||||
// TODO(b/309175133): forbid if enrolled with BSA
|
||||
// TODO(11/30/2023): uncomment below line
|
||||
// getInstance().bsaEnrollStartTime = enrollTime;
|
||||
getInstance().bsaEnrollStartTime = enrollTime.orElse(null);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.flogger.StackSize;
|
||||
import google.registry.config.RegistryEnvironment;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.persistence.JpaRetries;
|
||||
import google.registry.persistence.PersistenceModule.TransactionIsolationLevel;
|
||||
@@ -164,7 +165,10 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
|
||||
if (!getHibernateAllowNestedTransactions()) {
|
||||
throw new IllegalStateException(NESTED_TRANSACTION_MESSAGE);
|
||||
}
|
||||
logger.atWarning().withStackTrace(StackSize.MEDIUM).log(NESTED_TRANSACTION_MESSAGE);
|
||||
if (RegistryEnvironment.get() != RegistryEnvironment.PRODUCTION
|
||||
&& RegistryEnvironment.get() != RegistryEnvironment.UNITTEST) {
|
||||
logger.atWarning().withStackTrace(StackSize.MEDIUM).log(NESTED_TRANSACTION_MESSAGE);
|
||||
}
|
||||
// This prevents inner transaction from retrying, thus avoiding a cascade retry effect.
|
||||
return transactNoRetry(work, isolationLevel);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.google.common.net.MediaType;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URLConnection;
|
||||
import java.util.Random;
|
||||
|
||||
@@ -36,26 +37,37 @@ public final class UrlConnectionUtils {
|
||||
|
||||
private UrlConnectionUtils() {}
|
||||
|
||||
/** Retrieves the response from the given connection as a byte array. */
|
||||
public static byte[] getResponseBytes(URLConnection connection) throws IOException {
|
||||
try (InputStream is = connection.getInputStream()) {
|
||||
/**
|
||||
* Retrieves the response from the given connection as a byte array.
|
||||
*
|
||||
* <p>Note that in the event the response code is 4XX or 5XX, we use the error stream as any
|
||||
* payload is included there.
|
||||
*
|
||||
* @see HttpURLConnection#getErrorStream()
|
||||
*/
|
||||
public static byte[] getResponseBytes(HttpURLConnection connection) throws IOException {
|
||||
int responseCode = connection.getResponseCode();
|
||||
try (InputStream is =
|
||||
responseCode < 400 ? connection.getInputStream() : connection.getErrorStream()) {
|
||||
return ByteStreams.toByteArray(is);
|
||||
} catch (NullPointerException e) {
|
||||
return new byte[] {};
|
||||
}
|
||||
}
|
||||
|
||||
/** Sets auth on the given connection with the given username/password. */
|
||||
public static void setBasicAuth(URLConnection connection, String username, String password) {
|
||||
public static void setBasicAuth(HttpURLConnection connection, String username, String password) {
|
||||
setBasicAuth(connection, String.format("%s:%s", username, password));
|
||||
}
|
||||
|
||||
/** Sets auth on the given connection with the given string, formatted "username:password". */
|
||||
public static void setBasicAuth(URLConnection connection, String usernameAndPassword) {
|
||||
public static void setBasicAuth(HttpURLConnection connection, String usernameAndPassword) {
|
||||
String token = base64().encode(usernameAndPassword.getBytes(UTF_8));
|
||||
connection.setRequestProperty(AUTHORIZATION, "Basic " + token);
|
||||
}
|
||||
|
||||
/** Sets the given byte[] payload on the given connection with a particular content type. */
|
||||
public static void setPayload(URLConnection connection, byte[] bytes, String contentType)
|
||||
public static void setPayload(HttpURLConnection connection, byte[] bytes, String contentType)
|
||||
throws IOException {
|
||||
connection.setRequestProperty(CONTENT_TYPE, contentType);
|
||||
connection.setDoOutput(true);
|
||||
@@ -72,7 +84,7 @@ public final class UrlConnectionUtils {
|
||||
* @see <a href="http://www.ietf.org/rfc/rfc2388.txt">RFC2388 - Returning Values from Forms</a>
|
||||
*/
|
||||
public static void setPayloadMultipart(
|
||||
URLConnection connection,
|
||||
HttpURLConnection connection,
|
||||
String name,
|
||||
String filename,
|
||||
MediaType contentType,
|
||||
|
||||
@@ -72,9 +72,9 @@ public class ConfigureTldCommand extends MutatingCommand {
|
||||
boolean breakglass;
|
||||
|
||||
@Parameter(
|
||||
names = {"-d", "--dryrun"},
|
||||
names = {"-d", "--dry_run"},
|
||||
description = "Does not execute the entity mutation")
|
||||
boolean dryrun;
|
||||
boolean dryRun;
|
||||
|
||||
@Inject ObjectMapper mapper;
|
||||
|
||||
@@ -122,6 +122,13 @@ public class ConfigureTldCommand extends MutatingCommand {
|
||||
checkPremiumList(newTld);
|
||||
checkDnsWriters(newTld);
|
||||
checkCurrency(newTld);
|
||||
// bsaEnrollStartTime only exists in DB. Need to carry it over to the updated copy. See Tld.java
|
||||
// for more information.
|
||||
Optional<DateTime> bsaEnrollTime =
|
||||
Optional.ofNullable(oldTld).flatMap(Tld::getBsaEnrollStartTime);
|
||||
if (bsaEnrollTime.isPresent()) {
|
||||
newTld = newTld.asBuilder().setBsaEnrollStartTime(bsaEnrollTime).build();
|
||||
}
|
||||
// Set the new TLD to breakglass mode if breakglass flag was used
|
||||
if (breakglass) {
|
||||
newTld = newTld.asBuilder().setBreakglassMode(true).build();
|
||||
@@ -131,7 +138,7 @@ public class ConfigureTldCommand extends MutatingCommand {
|
||||
|
||||
@Override
|
||||
protected boolean dontRunCommand() {
|
||||
if (dryrun) {
|
||||
if (dryRun) {
|
||||
return true;
|
||||
}
|
||||
if (!newDiff) {
|
||||
|
||||
@@ -67,9 +67,12 @@ abstract class UpdateOrDeleteAllocationTokensCommand extends ConfirmingCommand {
|
||||
checkArgument(!prefix.isEmpty(), "Provided prefix should not be blank");
|
||||
return tm().transact(
|
||||
() ->
|
||||
tm().loadAllOf(AllocationToken.class).stream()
|
||||
.filter(token -> token.getToken().startsWith(prefix))
|
||||
.map(AllocationToken::createVKey)
|
||||
tm().query(
|
||||
"SELECT token FROM AllocationToken WHERE token LIKE :prefix",
|
||||
String.class)
|
||||
.setParameter("prefix", String.format("%s%%", prefix))
|
||||
.getResultStream()
|
||||
.map(token -> VKey.create(AllocationToken.class, token))
|
||||
.collect(toImmutableList()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.util.ListNamingUtils.convertFilePathToName;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.Parameters;
|
||||
import com.google.common.base.Strings;
|
||||
import google.registry.model.tld.label.PremiumList;
|
||||
@@ -29,6 +30,14 @@ import java.nio.file.Files;
|
||||
@Parameters(separators = " =", commandDescription = "Update a PremiumList in Database.")
|
||||
class UpdatePremiumListCommand extends CreateOrUpdatePremiumListCommand {
|
||||
|
||||
@Parameter(
|
||||
names = {"-d", "--dry_run"},
|
||||
description = "Does not execute the entity mutation")
|
||||
boolean dryRun;
|
||||
|
||||
// indicates if there is a new change made by this command
|
||||
private boolean newChange = false;
|
||||
|
||||
@Override
|
||||
protected String prompt() throws Exception {
|
||||
name = Strings.isNullOrEmpty(name) ? convertFilePathToName(inputFile) : name;
|
||||
@@ -43,8 +52,23 @@ class UpdatePremiumListCommand extends CreateOrUpdatePremiumListCommand {
|
||||
checkArgument(!inputData.isEmpty(), "New premium list data cannot be empty");
|
||||
currency = existingList.getCurrency();
|
||||
PremiumList updatedPremiumList = PremiumListUtils.parseToPremiumList(name, currency, inputData);
|
||||
return String.format(
|
||||
"Update premium list for %s?\n Old List: %s\n New List: %s",
|
||||
name, existingList, updatedPremiumList);
|
||||
if (!existingList
|
||||
.getLabelsToPrices()
|
||||
.entrySet()
|
||||
.equals(updatedPremiumList.getLabelsToPrices().entrySet())) {
|
||||
newChange = true;
|
||||
return String.format(
|
||||
"Update premium list for %s?\n Old List: %s\n New List: %s",
|
||||
name, existingList, updatedPremiumList);
|
||||
} else {
|
||||
return String.format(
|
||||
"This update contains no changes to the premium list for %s.\n List Contents: %s",
|
||||
name, existingList);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean dontRunCommand() {
|
||||
return dryRun || !newChange;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,38 +15,65 @@
|
||||
package google.registry.bsa;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static google.registry.tldconfig.idn.IdnTableEnum.EXTENDED_LATIN;
|
||||
import static google.registry.tldconfig.idn.IdnTableEnum.JA;
|
||||
import static google.registry.tldconfig.idn.IdnTableEnum.UNCONFUSABLE_LATIN;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.model.tld.Tld;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationWithCoverageExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import java.util.Optional;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
/** Unit tests for {@link IdnChecker}. */
|
||||
public class IdnCheckerTest {
|
||||
|
||||
@Mock Tld jaonly;
|
||||
@Mock Tld jandelatin;
|
||||
@Mock Tld strictlatin;
|
||||
FakeClock fakeClock = new FakeClock();
|
||||
|
||||
@RegisterExtension
|
||||
final JpaIntegrationWithCoverageExtension jpa =
|
||||
new JpaTestExtensions.Builder().withClock(fakeClock).buildIntegrationWithCoverageExtension();
|
||||
|
||||
Tld jaonly;
|
||||
Tld jandelatin;
|
||||
Tld strictlatin;
|
||||
IdnChecker idnChecker;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
idnChecker =
|
||||
new IdnChecker(
|
||||
ImmutableMap.of(
|
||||
JA,
|
||||
ImmutableSet.of(jandelatin, jaonly),
|
||||
EXTENDED_LATIN,
|
||||
ImmutableSet.of(jandelatin),
|
||||
UNCONFUSABLE_LATIN,
|
||||
ImmutableSet.of(strictlatin)));
|
||||
jaonly = createTld("jaonly");
|
||||
jandelatin = createTld("jandelatin");
|
||||
strictlatin = createTld("strictlatin");
|
||||
|
||||
jaonly =
|
||||
persistResource(
|
||||
jaonly
|
||||
.asBuilder()
|
||||
.setBsaEnrollStartTime(Optional.of(fakeClock.nowUtc()))
|
||||
.setIdnTables(ImmutableSet.of(JA))
|
||||
.build());
|
||||
jandelatin =
|
||||
persistResource(
|
||||
jandelatin
|
||||
.asBuilder()
|
||||
.setBsaEnrollStartTime(Optional.of(fakeClock.nowUtc()))
|
||||
.setIdnTables(ImmutableSet.of(JA, EXTENDED_LATIN))
|
||||
.build());
|
||||
strictlatin =
|
||||
persistResource(
|
||||
strictlatin
|
||||
.asBuilder()
|
||||
.setBsaEnrollStartTime(Optional.of(fakeClock.nowUtc()))
|
||||
.setIdnTables(ImmutableSet.of(UNCONFUSABLE_LATIN))
|
||||
.build());
|
||||
fakeClock.advanceOneMilli();
|
||||
idnChecker = new IdnChecker(fakeClock);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -263,7 +263,7 @@ public class RdeReportActionTest {
|
||||
@Test
|
||||
void testRunWithLock_badRequest_throws500WithErrorInfo() throws Exception {
|
||||
when(httpUrlConnection.getResponseCode()).thenReturn(STATUS_CODE_BAD_REQUEST);
|
||||
when(httpUrlConnection.getInputStream()).thenReturn(IIRDEA_BAD_XML.openBufferedStream());
|
||||
when(httpUrlConnection.getErrorStream()).thenReturn(IIRDEA_BAD_XML.openBufferedStream());
|
||||
InternalServerErrorException thrown =
|
||||
assertThrows(
|
||||
InternalServerErrorException.class,
|
||||
|
||||
@@ -99,10 +99,10 @@ class IcannHttpReporterTest {
|
||||
|
||||
@Test
|
||||
void testFail_BadIirdeaResponse() throws Exception {
|
||||
when(connection.getInputStream()).thenReturn(IIRDEA_BAD_XML.openBufferedStream());
|
||||
when(connection.getResponseCode()).thenReturn(STATUS_CODE_BAD_REQUEST);
|
||||
when(connection.getErrorStream()).thenReturn(IIRDEA_BAD_XML.openBufferedStream());
|
||||
assertThat(reporter.send(FAKE_PAYLOAD, "test-transactions-201706.csv")).isFalse();
|
||||
verify(connection).getInputStream();
|
||||
verify(connection).getErrorStream();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -29,6 +29,7 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -104,4 +105,21 @@ public class UrlConnectionUtilsTest {
|
||||
"Multipart data contains autogenerated boundary: "
|
||||
+ "------------------------------AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testErrorStream() throws Exception {
|
||||
HttpsURLConnection connection = mock(HttpsURLConnection.class);
|
||||
when(connection.getResponseCode()).thenReturn(400);
|
||||
when(connection.getErrorStream())
|
||||
.thenReturn(new ByteArrayInputStream("Failure".getBytes(UTF_8)));
|
||||
assertThat(UrlConnectionUtils.getResponseBytes(connection))
|
||||
.isEqualTo("Failure".getBytes(UTF_8));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testErrorStream_null() throws Exception {
|
||||
HttpsURLConnection connection = mock(HttpsURLConnection.class);
|
||||
when(connection.getResponseCode()).thenReturn(400);
|
||||
assertThat(UrlConnectionUtils.getResponseBytes(connection)).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,6 +108,8 @@ class NordnUploadActionTest {
|
||||
void beforeEach() throws Exception {
|
||||
when(httpUrlConnection.getInputStream())
|
||||
.thenReturn(new ByteArrayInputStream("Success".getBytes(UTF_8)));
|
||||
when(httpUrlConnection.getErrorStream())
|
||||
.thenReturn(new ByteArrayInputStream("Failure".getBytes(UTF_8)));
|
||||
when(httpUrlConnection.getResponseCode()).thenReturn(SC_ACCEPTED);
|
||||
when(httpUrlConnection.getHeaderField(LOCATION)).thenReturn("http://trololol");
|
||||
when(httpUrlConnection.getOutputStream()).thenReturn(connectionOutputStream);
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
package google.registry.tools;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.Truth8.assertThat;
|
||||
import static google.registry.model.EntityYamlUtils.createObjectMapper;
|
||||
import static google.registry.model.domain.token.AllocationToken.TokenType.DEFAULT_PROMO;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.persistPremiumList;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
@@ -46,6 +46,7 @@ import google.registry.model.tld.Tld.TldNotFoundException;
|
||||
import google.registry.model.tld.label.PremiumList;
|
||||
import google.registry.model.tld.label.PremiumListDao;
|
||||
import java.io.File;
|
||||
import java.util.Optional;
|
||||
import java.util.logging.Logger;
|
||||
import org.joda.money.Money;
|
||||
import org.joda.time.DateTime;
|
||||
@@ -101,20 +102,19 @@ public class ConfigureTldCommandTest extends CommandTestCase<ConfigureTldCommand
|
||||
assertThat(updatedTld.getCreateBillingCost()).isEqualTo(Money.of(USD, 25));
|
||||
testTldConfiguredSuccessfully(updatedTld, "tld.yaml");
|
||||
assertThat(updatedTld.getBreakglassMode()).isFalse();
|
||||
assertThat(tld.getBsaEnrollStartTime()).isNull();
|
||||
assertThat(tld.getBsaEnrollStartTime()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_updateTld_bsaTimeUnaffected() throws Exception {
|
||||
void testSuccess_updateTld_existingBsaTimeCarriedOver() throws Exception {
|
||||
Tld tld = createTld("tld");
|
||||
DateTime bsaStartTime = DateTime.now(DateTimeZone.UTC);
|
||||
tm().transact(() -> tm().put(tld.asBuilder().setBsaEnrollStartTime(bsaStartTime).build()));
|
||||
persistResource(tld.asBuilder().setBsaEnrollStartTime(Optional.of(bsaStartTime)).build());
|
||||
File tldFile = tmpDir.resolve("tld.yaml").toFile();
|
||||
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "tld.yaml"));
|
||||
runCommandForced("--input=" + tldFile);
|
||||
// TODO(11/30/2023): uncomment below two lines
|
||||
// Tld updatedTld = Tld.get("tld");
|
||||
// assertThat(tld.getBsaEnrollStartTime()).isEqualTo(bsaStartTime);
|
||||
Tld updatedTld = Tld.get("tld");
|
||||
assertThat(updatedTld.getBsaEnrollStartTime()).hasValue(bsaStartTime);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -593,7 +593,7 @@ public class ConfigureTldCommandTest extends CommandTestCase<ConfigureTldCommand
|
||||
void testSuccess_dryRunOnCreate_noChanges() throws Exception {
|
||||
File tldFile = tmpDir.resolve("tld.yaml").toFile();
|
||||
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "tld.yaml"));
|
||||
runCommandForced("--input=" + tldFile, "--dryrun");
|
||||
runCommandForced("--input=" + tldFile, "--dry_run");
|
||||
assertThrows(TldNotFoundException.class, () -> Tld.get("tld"));
|
||||
}
|
||||
|
||||
|
||||
@@ -63,10 +63,19 @@ class UpdatePremiumListCommandTest<C extends UpdatePremiumListCommand>
|
||||
UpdatePremiumListCommand command = new UpdatePremiumListCommand();
|
||||
command.inputFile = Paths.get(tmpFile.getPath());
|
||||
command.name = TLD_TEST;
|
||||
command.prompt();
|
||||
assertThat(command.prompt()).contains("Update premium list for prime?");
|
||||
}
|
||||
|
||||
@Test
|
||||
void commandPrompt_successStageNoChange() throws Exception {
|
||||
File tmpFile = tmpDir.resolve(String.format("%s.txt", TLD_TEST)).toFile();
|
||||
UpdatePremiumListCommand command = new UpdatePremiumListCommand();
|
||||
command.inputFile = Paths.get(tmpFile.getPath());
|
||||
command.name = TLD_TEST;
|
||||
assertThat(command.prompt())
|
||||
.contains("This update contains no changes to the premium list for prime.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void commandRun_successUpdateList() throws Exception {
|
||||
File tmpFile = tmpDir.resolve(String.format("%s.txt", TLD_TEST)).toFile();
|
||||
@@ -83,6 +92,18 @@ class UpdatePremiumListCommandTest<C extends UpdatePremiumListCommand>
|
||||
.containsExactly(PremiumEntry.create(0L, new BigDecimal("9999.00"), "eth"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void commandRun_successNoChange() throws Exception {
|
||||
File tmpFile = tmpDir.resolve(String.format("%s.txt", TLD_TEST)).toFile();
|
||||
|
||||
UpdatePremiumListCommand command = new UpdatePremiumListCommand();
|
||||
command.inputFile = Paths.get(tmpFile.getPath());
|
||||
runCommandForced("--name=" + TLD_TEST, "--input=" + command.inputFile);
|
||||
|
||||
assertThat(PremiumListDao.loadAllPremiumEntries(TLD_TEST))
|
||||
.containsExactly(PremiumEntry.create(0L, new BigDecimal("9090.00"), "doge"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void commandRun_successUpdateList_whenExistingListIsEmpty() throws Exception {
|
||||
File existingPremiumFile = tmpDir.resolve(TLD_TEST + ".txt").toFile();
|
||||
@@ -169,4 +190,19 @@ class UpdatePremiumListCommandTest<C extends UpdatePremiumListCommand>
|
||||
.hasMessageThat()
|
||||
.isEqualTo("Could not update premium list random3 because it doesn't exist");
|
||||
}
|
||||
|
||||
@Test
|
||||
void commandDryRun_noChangesMade() throws Exception {
|
||||
File tmpFile = tmpDir.resolve(String.format("%s.txt", TLD_TEST)).toFile();
|
||||
String newPremiumListData = "eth,USD 9999";
|
||||
Files.asCharSink(tmpFile, UTF_8).write(newPremiumListData);
|
||||
|
||||
UpdatePremiumListCommand command = new UpdatePremiumListCommand();
|
||||
command.inputFile = Paths.get(tmpFile.getPath());
|
||||
runCommandForced("--name=" + TLD_TEST, "--input=" + command.inputFile, "--dry_run");
|
||||
|
||||
assertThat(PremiumListDao.loadAllPremiumEntries(TLD_TEST))
|
||||
.comparingElementsUsing(immutableObjectCorrespondence("revisionId"))
|
||||
.containsExactly(PremiumEntry.create(0L, new BigDecimal("9090.00"), "doge"));
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -149,3 +149,4 @@ V148__add_bsa_download_and_label_tables.sql
|
||||
V149__add_bsa_domain_in_use_table.sql
|
||||
V150__add_tld_bsa_enroll_date.sql
|
||||
V151__add_bsa_unblockable_domain_table.sql
|
||||
V152__add_bsa_domain_refresh_table.sql
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
-- 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.
|
||||
|
||||
CREATE TABLE "BsaDomainRefresh" (
|
||||
job_id bigserial not null,
|
||||
creation_time timestamptz not null,
|
||||
stage text not null,
|
||||
update_timestamp timestamptz,
|
||||
primary key (job_id)
|
||||
);
|
||||
@@ -728,6 +728,7 @@
|
||||
auto_renew_grace_period_length interval not null,
|
||||
automatic_transfer_length interval not null,
|
||||
breakglass_mode boolean not null,
|
||||
bsa_enroll_start_time timestamptz,
|
||||
claims_period_end timestamptz not null,
|
||||
create_billing_cost_amount numeric(19, 2),
|
||||
create_billing_cost_currency text,
|
||||
|
||||
@@ -135,6 +135,37 @@ CREATE TABLE public."BsaDomainInUse" (
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: BsaDomainRefresh; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public."BsaDomainRefresh" (
|
||||
job_id bigint NOT NULL,
|
||||
creation_time timestamp with time zone NOT NULL,
|
||||
stage text NOT NULL,
|
||||
update_timestamp timestamp with time zone
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: BsaDomainRefresh_job_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public."BsaDomainRefresh_job_id_seq"
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: BsaDomainRefresh_job_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public."BsaDomainRefresh_job_id_seq" OWNED BY public."BsaDomainRefresh".job_id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: BsaDownload; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
@@ -1222,6 +1253,13 @@ CREATE SEQUENCE public.project_wide_unique_id_seq
|
||||
CACHE 10;
|
||||
|
||||
|
||||
--
|
||||
-- Name: BsaDomainRefresh job_id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."BsaDomainRefresh" ALTER COLUMN job_id SET DEFAULT nextval('public."BsaDomainRefresh_job_id_seq"'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: BsaDownload job_id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -1339,6 +1377,14 @@ ALTER TABLE ONLY public."BsaDomainInUse"
|
||||
ADD CONSTRAINT "BsaDomainInUse_pkey" PRIMARY KEY (label, tld);
|
||||
|
||||
|
||||
--
|
||||
-- Name: BsaDomainRefresh BsaDomainRefresh_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."BsaDomainRefresh"
|
||||
ADD CONSTRAINT "BsaDomainRefresh_pkey" PRIMARY KEY (job_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: BsaDownload BsaDownload_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
@@ -78,8 +78,8 @@ steps:
|
||||
grep -e "^backend\|^default\|^bsa\|^pubapi\|^tools" |\
|
||||
while read line; do echo "${TAG_NAME},$line"; done | tee "$local_map"
|
||||
num_versions=$(cat "$local_map" | wc -l)
|
||||
if [ "$num_versions" -ne 4 ]; then
|
||||
echo "Expecting exactly four active services. Found $num_versions"
|
||||
if [ "$num_versions" -ne 5 ]; then
|
||||
echo "Expecting exactly five active services. Found $num_versions"
|
||||
exit 1
|
||||
fi
|
||||
gsutil cp "$local_map" gs://$PROJECT_ID-deployed-tags/nomulus.${_ENV}.tmp
|
||||
|
||||
Reference in New Issue
Block a user