1
0
mirror of https://github.com/google/nomulus synced 2026-05-25 09:10:51 +00:00

Compare commits

..

10 Commits

Author SHA1 Message Date
Lai Jiang
e4132db8ed Delete SetClockExtension (#1738)
We no longer write to commit logs, and the ReplayExtension that this
extension is supposed to be used with is already deleted.
2022-08-11 13:16:30 -04:00
Pavlo Tkach
45d90e7c68 Extend IP validation test with message verification (#1736) 2022-08-10 13:27:55 -04:00
sarahcaseybot
028005906a Add allocation token to transfer command (#1737) 2022-08-09 15:18:23 -04:00
sarahcaseybot
78d78e21cb Add CurrentPackageToken to Domain table (#1720)
* Add allocation token to Domain table

* Add tests

* Change column name

* change test names
2022-08-09 11:23:21 -04:00
Lai Jiang
2f3ac2e43b Remove unused columns in BillingCancellation (#1721)
We stopped using these columns after BillingVKey is removed in
https://github.com/google/nomulus/pull/1710.
2022-08-08 10:28:30 -04:00
gbrodman
632e3831e5 Add caches to ClaimsListDao and ClaimsList (#1731)
We cache the ClaimsList Java object for six hours (we don't expect it to
change frequently, and the cron job to update it only runs every twelve
hours). Subsequent calls to ClaimsListDao::get will return the cached
value.

Within the ClaimsList Java object itself, we cache any labels that we
have retrieved. While we already have a form of a cache here in the
"labelsToKeys" map, that only handles situations where we've loaded the
entire map from the database. We want to have a non-guaranteed cache in
order to make repeated calls to getClaimKey fast.
2022-08-05 17:29:59 -04:00
Ben McIlwain
9ff25f9a67 Make domain transfers use (and retain) the renewal price/behavior (#1701)
* Use the new renewal price logic in transfer flow

* Fix build

* Add renewal handling on all transfer flows

* Merge branch 'master' into transfer-retain-renewal-price

* Merge branch 'master' into transfer-retain-renewal-price

* Add more tests
2022-08-05 15:53:27 -04:00
gbrodman
eb1a314666 Add base object classes for new user/role permissioning model (#1707)
* Add base object classes for new user/role permissioning model

- Adds the permissions themselves
- Adds the six roles that a user may have -- three global, three
  per-registrar
- Adds the mapping from role -> set of permissions
- Adds a UserRoles object to encapsulate the answer to the question of
  "does this user have this permission?"
- Adds a User class as a base to show how we will use the new UserRoles
  object
2022-08-05 14:18:16 -04:00
Ben McIlwain
0e182546f9 Rename HostResource -> Host (#1733)
* Rename HostResource -> Host
2022-08-05 10:28:45 -04:00
Pavlo Tkach
ad06ba2e1e Extend registrar allowed IPs auth exception text with IP address (#1726) 2022-08-03 15:24:00 -04:00
169 changed files with 4651 additions and 3138 deletions

View File

@@ -29,7 +29,7 @@ import com.google.common.flogger.FluentLogger;
import google.registry.config.RegistryConfig.Config;
import google.registry.model.EppResource;
import google.registry.model.eppcommon.Trid;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.persistence.VKey;
import google.registry.request.Action.Service;
import google.registry.util.CloudTasksUtils;
@@ -140,8 +140,8 @@ public final class AsyncTaskEnqueuer {
}
/** Enqueues a task to asynchronously refresh DNS for a renamed host. */
public void enqueueAsyncDnsRefresh(HostResource host, DateTime now) {
VKey<HostResource> hostKey = host.createVKey();
public void enqueueAsyncDnsRefresh(Host host, DateTime now) {
VKey<Host> hostKey = host.createVKey();
logger.atInfo().log("Enqueuing async DNS refresh for renamed host %s.", hostKey);
addTaskToQueueWithRetry(
asyncDnsRefreshPullQueue,

View File

@@ -31,7 +31,7 @@ import google.registry.model.EppResource;
import google.registry.model.EppResourceUtils;
import google.registry.model.contact.ContactResource;
import google.registry.model.domain.Domain;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.model.poll.PollMessage;
import google.registry.model.reporting.HistoryEntry;
import google.registry.model.reporting.HistoryEntryDao;
@@ -43,8 +43,8 @@ import google.registry.util.Clock;
import javax.inject.Inject;
/**
* Hard deletes load-test ContactResources, HostResources, their subordinate history entries, and
* the associated ForeignKey and EppResourceIndex entities.
* Hard deletes load-test ContactResources, Hosts, their subordinate history entries, and the
* associated ForeignKey and EppResourceIndex entities.
*
* <p>This only deletes contacts and hosts, NOT domains. To delete domains, use {@link
* DeleteProberDataAction} and pass it the TLD(s) that the load test domains were created on. Note
@@ -93,7 +93,7 @@ public class DeleteLoadTestDataAction implements Runnable {
() -> {
LOAD_TEST_REGISTRARS.forEach(this::deletePollMessages);
tm().loadAllOfStream(ContactResource.class).forEach(this::deleteContact);
tm().loadAllOfStream(HostResource.class).forEach(this::deleteHost);
tm().loadAllOfStream(Host.class).forEach(this::deleteHost);
});
}
@@ -123,11 +123,11 @@ public class DeleteLoadTestDataAction implements Runnable {
deleteResource(contact);
}
private void deleteHost(HostResource host) {
private void deleteHost(Host host) {
if (!LOAD_TEST_REGISTRARS.contains(host.getPersistedCurrentSponsorRegistrarId())) {
return;
}
VKey<HostResource> hostVKey = host.createVKey();
VKey<Host> hostVKey = host.createVKey();
// We can remove hosts from linked domains, so we should do so then delete the hosts
ImmutableSet<VKey<Domain>> linkedDomains =
EppResourceUtils.getLinkedDomainKeys(hostVKey, clock.nowUtc(), null);
@@ -135,7 +135,7 @@ public class DeleteLoadTestDataAction implements Runnable {
.values()
.forEach(
domain -> {
ImmutableSet<VKey<HostResource>> remainingHosts =
ImmutableSet<VKey<Host>> remainingHosts =
domain.getNsHosts().stream()
.filter(vkey -> !vkey.equals(hostVKey))
.collect(toImmutableSet());

View File

@@ -49,8 +49,8 @@ import google.registry.model.contact.ContactHistory;
import google.registry.model.contact.ContactResource;
import google.registry.model.domain.Domain;
import google.registry.model.domain.DomainHistory;
import google.registry.model.host.Host;
import google.registry.model.host.HostHistory;
import google.registry.model.host.HostResource;
import google.registry.model.rde.RdeMode;
import google.registry.model.registrar.Registrar;
import google.registry.model.registrar.Registrar.Type;
@@ -148,7 +148,7 @@ import org.joda.time.DateTime;
* then loaded from the remaining referenced contact histories, and marshalled into (pending
* deposit: deposit fragment) pairs.
*
* <h3>{@link HostResource}</h3>
* <h3>{@link Host}</h3>
*
* Similar to {@link ContactResource}, we join the most recent host history with referenced hosts to
* find most recent referenced hosts. For external hosts we do the same treatment as we did on
@@ -467,10 +467,9 @@ public class RdePipeline implements Serializable {
Counter activeDomainCounter = Metrics.counter("RDE", "ActiveDomainBase");
Counter domainFragmentCounter = Metrics.counter("RDE", "DomainFragment");
Counter referencedContactCounter = Metrics.counter("RDE", "ReferencedContactResource");
Counter referencedHostCounter = Metrics.counter("RDE", "ReferencedHostResource");
Counter referencedHostCounter = Metrics.counter("RDE", "ReferencedHost");
return domainHistories.apply(
"Map DomainHistory to DepositFragment "
+ "and emit referenced ContactResource and HostResource",
"Map DomainHistory to DepositFragment " + "and emit referenced ContactResource and Host",
ParDo.of(
new DoFn<KV<String, Long>, KV<PendingDeposit, DepositFragment>>() {
@ProcessElement
@@ -565,10 +564,10 @@ public class RdePipeline implements Serializable {
private PCollectionTuple processHostHistories(
PCollection<KV<String, PendingDeposit>> referencedHosts,
PCollection<KV<String, Long>> hostHistories) {
Counter subordinateHostCounter = Metrics.counter("RDE", "SubordinateHostResource");
Counter externalHostCounter = Metrics.counter("RDE", "ExternalHostResource");
Counter subordinateHostCounter = Metrics.counter("RDE", "SubordinateHost");
Counter externalHostCounter = Metrics.counter("RDE", "ExternalHost");
Counter externalHostFragmentCounter = Metrics.counter("RDE", "ExternalHostFragment");
return removeUnreferencedResource(referencedHosts, hostHistories, HostResource.class)
return removeUnreferencedResource(referencedHosts, hostHistories, Host.class)
.apply(
"Map external DomainResource to DepositFragment and process subordinate domains",
ParDo.of(
@@ -576,8 +575,8 @@ public class RdePipeline implements Serializable {
@ProcessElement
public void processElement(
@Element KV<String, CoGbkResult> kv, MultiOutputReceiver receiver) {
HostResource host =
(HostResource)
Host host =
(Host)
loadResourceByHistoryEntryId(
HostHistory.class,
kv.getKey(),
@@ -631,11 +630,9 @@ public class RdePipeline implements Serializable {
Counter referencedSubordinateHostCounter = Metrics.counter("RDE", "ReferencedSubordinateHost");
return KeyedPCollectionTuple.of(HOST_TO_PENDING_DEPOSIT, superordinateDomains)
.and(REVISION_ID, domainHistories)
.apply("Join Host:PendingDeposits with DomainHistory on Domain", CoGroupByKey.create())
.apply(
"Join HostResource:PendingDeposits with DomainHistory on DomainResource",
CoGroupByKey.create())
.apply(
" Remove unreferenced DomainResource",
" Remove unreferenced Domain",
Filter.by(
kv -> {
boolean toInclude =
@@ -647,7 +644,7 @@ public class RdePipeline implements Serializable {
return toInclude;
}))
.apply(
"Map subordinate HostResource to DepositFragment",
"Map subordinate Host to DepositFragment",
FlatMapElements.into(
kvs(
TypeDescriptor.of(PendingDeposit.class),
@@ -664,8 +661,8 @@ public class RdePipeline implements Serializable {
new ImmutableSet.Builder<>();
for (KV<String, CoGbkResult> hostToPendingDeposits :
kv.getValue().getAll(HOST_TO_PENDING_DEPOSIT)) {
HostResource host =
(HostResource)
Host host =
(Host)
loadResourceByHistoryEntryId(
HostHistory.class,
hostToPendingDeposits.getKey(),

View File

@@ -25,7 +25,7 @@ import google.registry.model.EppResource;
import google.registry.model.contact.ContactResource;
import google.registry.model.domain.Domain;
import google.registry.model.domain.DomainBase;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.persistence.PersistenceModule.TransactionIsolationLevel;
import google.registry.persistence.transaction.CriteriaQueryBuilder;
import google.registry.util.DateTimeUtils;
@@ -52,7 +52,7 @@ import org.joda.time.DateTime;
public class ResaveAllEppResourcesPipeline implements Serializable {
private static final ImmutableSet<Class<? extends EppResource>> EPP_RESOURCE_CLASSES =
ImmutableSet.of(ContactResource.class, Domain.class, HostResource.class);
ImmutableSet.of(ContactResource.class, Domain.class, Host.class);
/**
* There exist three possible situations where we know we'll want to project domains to the

View File

@@ -1427,6 +1427,11 @@ public final class RegistryConfig {
return CONFIG_SETTINGS.get().caching.eppResourceMaxCachedEntries;
}
/** Returns the amount of time that a particular claims list should be cached. */
public static java.time.Duration getClaimsListCacheDuration() {
return java.time.Duration.ofSeconds(CONFIG_SETTINGS.get().caching.claimsListCachingSeconds);
}
/** Returns the email address that outgoing emails from the app are sent from. */
public static InternetAddress getGSuiteOutgoingEmailAddress() {
return parseEmailAddress(CONFIG_SETTINGS.get().gSuite.outgoingEmailAddress);

View File

@@ -155,6 +155,7 @@ public class RegistryConfigSettings {
public boolean eppResourceCachingEnabled;
public int eppResourceCachingSeconds;
public int eppResourceMaxCachedEntries;
public int claimsListCachingSeconds;
}
/** Configuration for ICANN monthly reporting. */

View File

@@ -294,6 +294,10 @@ caching:
# have to be very large to achieve the vast majority of possible gains.
eppResourceMaxCachedEntries: 500
# Length of time that a claims list will be cached after retrieval. A fairly
# long duration is acceptable because claims lists don't change frequently.
claimsListCachingSeconds: 21600 # six hours
oAuth:
# OAuth scopes to detect on access tokens. Superset of requiredOauthScopes.
availableOauthScopes:

View File

@@ -21,7 +21,7 @@ import google.registry.model.EppResource;
import google.registry.model.EppResource.ForeignKeyedEppResource;
import google.registry.model.annotations.ExternalMessagingName;
import google.registry.model.domain.Domain;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.request.Action;
import google.registry.request.HttpException.BadRequestException;
import google.registry.request.HttpException.NotFoundException;
@@ -66,7 +66,7 @@ public final class RefreshDnsAction implements Runnable {
dnsQueue.addDomainRefreshTask(domainOrHostName);
break;
case HOST:
verifyHostIsSubordinate(loadAndVerifyExistence(HostResource.class, domainOrHostName));
verifyHostIsSubordinate(loadAndVerifyExistence(Host.class, domainOrHostName));
dnsQueue.addHostRefreshTask(domainOrHostName);
break;
default:
@@ -86,7 +86,7 @@ public final class RefreshDnsAction implements Runnable {
domainOrHostName)));
}
private static void verifyHostIsSubordinate(HostResource host) {
private static void verifyHostIsSubordinate(Host host) {
if (!host.isSubordinate()) {
throw new BadRequestException(
String.format("%s isn't a subordinate hostname", host.getHostName()));

View File

@@ -38,7 +38,7 @@ import google.registry.dns.writer.DnsWriter;
import google.registry.dns.writer.DnsWriterZone;
import google.registry.model.domain.Domain;
import google.registry.model.domain.secdns.DelegationSignerData;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.model.tld.Registries;
import google.registry.util.Clock;
import google.registry.util.Concurrent;
@@ -190,7 +190,7 @@ public class CloudDnsWriter extends BaseDnsWriter {
// Load the target host. Note that it can be absent if this host was just deleted.
// desiredRecords is populated with an empty set to indicate that all existing records
// should be deleted.
Optional<HostResource> host = loadByForeignKey(HostResource.class, hostName, clock.nowUtc());
Optional<Host> host = loadByForeignKey(Host.class, hostName, clock.nowUtc());
// Return early if the host is deleted.
if (!host.isPresent()) {

View File

@@ -29,7 +29,7 @@ import google.registry.dns.writer.BaseDnsWriter;
import google.registry.dns.writer.DnsWriterZone;
import google.registry.model.domain.Domain;
import google.registry.model.domain.secdns.DelegationSignerData;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.model.tld.Registries;
import google.registry.util.Clock;
import java.io.IOException;
@@ -215,7 +215,7 @@ public class DnsUpdateWriter extends BaseDnsWriter {
private void addInBailiwickNameServerSet(Domain domain, Update update) {
for (String hostName :
intersection(domain.loadNameserverHostNames(), domain.getSubordinateHosts())) {
Optional<HostResource> host = loadByForeignKey(HostResource.class, hostName, clock.nowUtc());
Optional<Host> host = loadByForeignKey(Host.class, hostName, clock.nowUtc());
checkState(host.isPresent(), "Host %s cannot be loaded", hostName);
update.add(makeAddressSet(host.get()));
update.add(makeV6AddressSet(host.get()));
@@ -236,7 +236,7 @@ public class DnsUpdateWriter extends BaseDnsWriter {
return nameServerSet;
}
private RRset makeAddressSet(HostResource host) {
private RRset makeAddressSet(Host host) {
RRset addressSet = new RRset();
for (InetAddress address : host.getInetAddresses()) {
if (address instanceof Inet4Address) {
@@ -252,7 +252,7 @@ public class DnsUpdateWriter extends BaseDnsWriter {
return addressSet;
}
private RRset makeV6AddressSet(HostResource host) {
private RRset makeV6AddressSet(Host host) {
RRset addressSet = new RRset();
for (InetAddress address : host.getInetAddresses()) {
if (address instanceof Inet6Address) {

View File

@@ -26,7 +26,7 @@
<property name="creationTime" direction="desc"/>
</datastore-index>
<!-- For finding host resources by registrar. -->
<datastore-index kind="HostResource" ancestor="false" source="manual">
<datastore-index kind="Host" ancestor="false" source="manual">
<property name="currentSponsorClientId" direction="asc"/>
<property name="deletionTime" direction="asc"/>
<property name="fullyQualifiedHostName" direction="asc"/>
@@ -52,7 +52,7 @@
<property name="deletionTime" direction="asc"/>
</datastore-index>
<!-- For WHOIS IP address lookup -->
<datastore-index kind="HostResource" ancestor="false" source="manual">
<datastore-index kind="Host" ancestor="false" source="manual">
<property name="inetAddresses" direction="asc"/>
<property name="deletionTime" direction="asc"/>
</datastore-index>
@@ -87,7 +87,7 @@
<property name="tld" direction="asc"/>
<property name="fullyQualifiedDomainName" direction="asc"/>
</datastore-index>
<datastore-index kind="HostResource" ancestor="false" source="manual">
<datastore-index kind="Host" ancestor="false" source="manual">
<property name="deletionTime" direction="asc"/>
<property name="fullyQualifiedHostName" direction="asc"/>
</datastore-index>

View File

@@ -114,7 +114,7 @@ public class TlsCredentials implements TransportCredentials {
"Authentication error: IP address %s is not allow-listed for registrar %s; allow list is:"
+ " %s",
clientInetAddr, registrar.getRegistrarId(), ipAddressAllowList);
throw new BadRegistrarIpAddressException();
throw new BadRegistrarIpAddressException(clientInetAddr);
}
@VisibleForTesting
@@ -216,8 +216,13 @@ public class TlsCredentials implements TransportCredentials {
/** Registrar IP address is not in stored allow list. */
public static class BadRegistrarIpAddressException extends AuthenticationErrorException {
BadRegistrarIpAddressException() {
super("Registrar IP address is not in stored allow list");
BadRegistrarIpAddressException(Optional<InetAddress> clientInetAddr) {
super(
clientInetAddr.isPresent()
? String.format(
"Registrar IP address %s is not in stored allow list",
clientInetAddr.get().getHostAddress())
: "Registrar IP address is not in stored allow list");
}
}

View File

@@ -64,6 +64,7 @@ import google.registry.flows.custom.DomainDeleteFlowCustomLogic.BeforeSaveParame
import google.registry.flows.custom.EntityChanges;
import google.registry.model.ImmutableObject;
import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.Recurring;
import google.registry.model.domain.Domain;
import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.DomainHistory.DomainHistoryId;
@@ -260,8 +261,9 @@ public final class DomainDeleteFlow implements TransactionalFlow {
handlePendingTransferOnDelete(existingDomain, newDomain, now, domainHistory);
// Close the autorenew billing event and poll message. This may delete the poll message. Store
// the updated recurring billing event, we'll need it later and can't reload it.
Recurring existingRecurring = tm().loadByKey(existingDomain.getAutorenewBillingEvent());
BillingEvent.Recurring recurringBillingEvent =
updateAutorenewRecurrenceEndTime(existingDomain, now);
updateAutorenewRecurrenceEndTime(existingDomain, existingRecurring, now);
// If there's a pending transfer, the gaining client's autorenew billing
// event and poll message will already have been deleted in
// ResourceDeleteFlow since it's listed in serverApproveEntities.

View File

@@ -114,7 +114,7 @@ import google.registry.model.domain.secdns.SecDnsUpdateExtension.Remove;
import google.registry.model.domain.token.AllocationToken;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.model.poll.PollMessage;
import google.registry.model.registrar.Registrar;
import google.registry.model.registrar.Registrar.State;
@@ -375,7 +375,7 @@ public class DomainFlowUtils {
static void verifyNotInPendingDelete(
Set<DesignatedContact> contacts,
VKey<ContactResource> registrant,
Set<VKey<HostResource>> nameservers)
Set<VKey<Host>> nameservers)
throws EppException {
ImmutableList.Builder<VKey<? extends EppResource>> keysToLoad = new ImmutableList.Builder<>();
contacts.stream().map(DesignatedContact::getContactKey).forEach(keysToLoad::add);
@@ -583,7 +583,8 @@ public class DomainFlowUtils {
*
* <p>Returns the new autorenew recurring billing event.
*/
public static Recurring updateAutorenewRecurrenceEndTime(Domain domain, DateTime newEndTime) {
public static Recurring updateAutorenewRecurrenceEndTime(
Domain domain, Recurring existingRecurring, DateTime newEndTime) {
Optional<PollMessage.Autorenew> autorenewPollMessage =
tm().loadByKeyIfPresent(domain.getAutorenewPollMessage());
@@ -611,13 +612,9 @@ public class DomainFlowUtils {
tm().put(updatedAutorenewPollMessage);
}
Recurring recurring =
tm().loadByKey(domain.getAutorenewBillingEvent())
.asBuilder()
.setRecurrenceEndTime(newEndTime)
.build();
tm().put(recurring);
return recurring;
Recurring newRecurring = existingRecurring.asBuilder().setRecurrenceEndTime(newEndTime).build();
tm().put(newRecurring);
return newRecurring;
}
/**
@@ -708,7 +705,10 @@ public class DomainFlowUtils {
throw new TransfersAreAlwaysForOneYearException();
}
builder.setAvailIfSupported(true);
fees = pricingLogic.getTransferPrice(registry, domainNameString, now).getFees();
fees =
pricingLogic
.getTransferPrice(registry, domainNameString, now, recurringBillingEvent)
.getFees();
break;
case UPDATE:
builder.setAvailIfSupported(true);
@@ -767,7 +767,7 @@ public class DomainFlowUtils {
final Optional<? extends FeeTransformCommandExtension> feeCommand,
FeesAndCredits feesAndCredits)
throws EppException {
if (isDomainPremium(domainName, priceTime) && !feeCommand.isPresent()) {
if (feesAndCredits.hasAnyPremiumFees() && !feeCommand.isPresent()) {
throw new FeesRequiredForPremiumNameException();
}
validateFeesAckedIfPresent(feeCommand, feesAndCredits);

View File

@@ -195,9 +195,14 @@ public final class DomainPricingLogic {
}
/** Returns a new transfer price for the pricer. */
FeesAndCredits getTransferPrice(Registry registry, String domainName, DateTime dateTime)
FeesAndCredits getTransferPrice(
Registry registry,
String domainName,
DateTime dateTime,
@Nullable Recurring recurringBillingEvent)
throws EppException {
DomainPrices domainPrices = getPricesForDomainName(domainName, dateTime);
FeesAndCredits renewPrice =
getRenewPrice(registry, domainName, dateTime, 1, recurringBillingEvent);
return customLogic.customizeTransferPrice(
TransferPriceParameters.newBuilder()
.setFeesAndCredits(
@@ -205,9 +210,9 @@ public final class DomainPricingLogic {
.setCurrency(registry.getCurrency())
.addFeeOrCredit(
Fee.create(
domainPrices.getRenewCost().getAmount(),
renewPrice.getRenewCost().getAmount(),
FeeType.RENEW,
domainPrices.isPremium()))
renewPrice.hasAnyPremiumFees()))
.build())
.setRegistry(registry)
.setDomainName(InternetDomainName.from(domainName))

View File

@@ -222,7 +222,8 @@ public final class DomainRenewFlow implements TransactionalFlow {
domainHistoryKey.getParent().getName(), domainHistoryKey.getId()))
.build();
// End the old autorenew billing event and poll message now. This may delete the poll message.
updateAutorenewRecurrenceEndTime(existingDomain, now);
Recurring existingRecurring = tm().loadByKey(existingDomain.getAutorenewBillingEvent());
updateAutorenewRecurrenceEndTime(existingDomain, existingRecurring, now);
Domain newDomain =
existingDomain
.asBuilder()

View File

@@ -31,7 +31,6 @@ import static google.registry.model.ResourceTransferUtils.approvePendingTransfer
import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.TRANSFER_SUCCESSFUL;
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_TRANSFER_APPROVE;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost;
import static google.registry.util.CollectionUtils.union;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
@@ -45,17 +44,22 @@ import google.registry.flows.FlowModule.Superuser;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.TransactionalFlow;
import google.registry.flows.annotations.ReportingSpec;
import google.registry.flows.domain.token.AllocationTokenFlowUtils;
import google.registry.model.ImmutableObject;
import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.Flag;
import google.registry.model.billing.BillingEvent.Reason;
import google.registry.model.billing.BillingEvent.Recurring;
import google.registry.model.domain.Domain;
import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.DomainHistory.DomainHistoryId;
import google.registry.model.domain.GracePeriod;
import google.registry.model.domain.metadata.MetadataExtension;
import google.registry.model.domain.rgp.GracePeriodStatus;
import google.registry.model.domain.token.AllocationToken;
import google.registry.model.domain.token.AllocationTokenExtension;
import google.registry.model.eppcommon.AuthInfo;
import google.registry.model.eppinput.EppInput;
import google.registry.model.eppoutput.EppResponse;
import google.registry.model.poll.PollMessage;
import google.registry.model.reporting.DomainTransactionRecord;
@@ -85,6 +89,18 @@ import org.joda.time.DateTime;
* @error {@link google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException}
* @error {@link google.registry.flows.exceptions.NotPendingTransferException}
* @error {@link DomainFlowUtils.NotAuthorizedForTldException}
* @error {@link
* google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForDomainException}
* @error {@link
* google.registry.flows.domain.token.AllocationTokenFlowUtils.InvalidAllocationTokenException}
* @error {@link
* google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotInPromotionException}
* @error {@link
* google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForRegistrarException}
* @error {@link
* google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForTldException}
* @error {@link
* google.registry.flows.domain.token.AllocationTokenFlowUtils.AlreadyRedeemedAllocationTokenException}
*/
@ReportingSpec(ActivityReportField.DOMAIN_TRANSFER_APPROVE)
public final class DomainTransferApproveFlow implements TransactionalFlow {
@@ -96,6 +112,10 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
@Inject @Superuser boolean isSuperuser;
@Inject DomainHistory.Builder historyBuilder;
@Inject EppResponse.Builder responseBuilder;
@Inject DomainPricingLogic pricingLogic;
@Inject AllocationTokenFlowUtils allocationTokenFlowUtils;
@Inject EppInput eppInput;
@Inject DomainTransferApproveFlow() {}
/**
@@ -104,11 +124,20 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
*/
@Override
public EppResponse run() throws EppException {
extensionManager.register(MetadataExtension.class);
extensionManager.register(MetadataExtension.class, AllocationTokenExtension.class);
validateRegistrarIsLoggedIn(registrarId);
extensionManager.validate();
DateTime now = tm().getTransactionTime();
Domain existingDomain = loadAndVerifyExistence(Domain.class, targetId, now);
// Currently we do not do anything with this allocation token, but just want it loaded and
// available in this flow in case we use it in the future
Optional<AllocationToken> allocationToken =
allocationTokenFlowUtils.verifyAllocationTokenIfPresent(
existingDomain,
Registry.get(existingDomain.getTld()),
registrarId,
now,
eppInput.getSingleExtension(AllocationTokenExtension.class));
verifyOptionalAuthInfo(authInfo, existingDomain);
verifyHasPendingTransfer(existingDomain);
verifyResourceOwnership(registrarId, existingDomain);
@@ -120,6 +149,7 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
String gainingRegistrarId = transferData.getGainingRegistrarId();
// Create a transfer billing event for 1 year, unless the superuser extension was used to set
// the transfer period to zero. There is not a transfer cost if the transfer period is zero.
Recurring existingRecurring = tm().loadByKey(existingDomain.getAutorenewBillingEvent());
Key<DomainHistory> domainHistoryKey = createHistoryKey(existingDomain, DomainHistory.class);
historyBuilder.setId(domainHistoryKey.getId());
Optional<BillingEvent.OneTime> billingEvent =
@@ -131,7 +161,14 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
.setTargetId(targetId)
.setRegistrarId(gainingRegistrarId)
.setPeriodYears(1)
.setCost(getDomainRenewCost(targetId, transferData.getTransferRequestTime(), 1))
.setCost(
pricingLogic
.getTransferPrice(
Registry.get(tld),
targetId,
transferData.getTransferRequestTime(),
existingRecurring)
.getRenewCost())
.setEventTime(now)
.setBillingTime(now.plus(Registry.get(tld).getTransferGracePeriodLength()))
.setDomainHistoryId(
@@ -161,7 +198,7 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
}
// Close the old autorenew event and poll message at the transfer time (aka now). This may end
// up deleting the poll message.
updateAutorenewRecurrenceEndTime(existingDomain, now);
updateAutorenewRecurrenceEndTime(existingDomain, existingRecurring, now);
DateTime newExpirationTime =
computeExDateForApprovalTime(existingDomain, now, transferData.getTransferPeriod());
// Create a new autorenew event starting at the expiration time.
@@ -172,6 +209,8 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
.setTargetId(targetId)
.setRegistrarId(gainingRegistrarId)
.setEventTime(newExpirationTime)
.setRenewalPriceBehavior(existingRecurring.getRenewalPriceBehavior())
.setRenewalPrice(existingRecurring.getRenewalPrice().orElse(null))
.setRecurrenceEndTime(END_OF_TIME)
.setDomainHistoryId(
new DomainHistoryId(

View File

@@ -40,6 +40,7 @@ import google.registry.flows.FlowModule.Superuser;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.TransactionalFlow;
import google.registry.flows.annotations.ReportingSpec;
import google.registry.model.billing.BillingEvent.Recurring;
import google.registry.model.domain.Domain;
import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.metadata.MetadataExtension;
@@ -114,7 +115,8 @@ public final class DomainTransferCancelFlow implements TransactionalFlow {
targetId, newDomain.getTransferData(), null, domainHistoryKey));
// Reopen the autorenew event and poll message that we closed for the implicit transfer. This
// may recreate the autorenew poll message if it was deleted when the transfer request was made.
updateAutorenewRecurrenceEndTime(existingDomain, END_OF_TIME);
Recurring existingRecurring = tm().loadByKey(existingDomain.getAutorenewBillingEvent());
updateAutorenewRecurrenceEndTime(existingDomain, existingRecurring, END_OF_TIME);
// Delete the billing event and poll messages that were written in case the transfer would have
// been implicitly server approved.
tm().delete(existingDomain.getTransferData().getServerApproveEntities());

View File

@@ -42,6 +42,7 @@ import google.registry.flows.FlowModule.Superuser;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.TransactionalFlow;
import google.registry.flows.annotations.ReportingSpec;
import google.registry.model.billing.BillingEvent.Recurring;
import google.registry.model.domain.Domain;
import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.metadata.MetadataExtension;
@@ -115,7 +116,8 @@ public final class DomainTransferRejectFlow implements TransactionalFlow {
targetId, newDomain.getTransferData(), null, now, domainHistoryKey));
// Reopen the autorenew event and poll message that we closed for the implicit transfer. This
// may end up recreating the poll message if it was deleted upon the transfer request.
updateAutorenewRecurrenceEndTime(existingDomain, END_OF_TIME);
Recurring existingRecurring = tm().loadByKey(existingDomain.getAutorenewBillingEvent());
updateAutorenewRecurrenceEndTime(existingDomain, existingRecurring, END_OF_TIME);
// Delete the billing event and poll messages that were written in case the transfer would have
// been implicitly server approved.
tm().delete(existingDomain.getTransferData().getServerApproveEntities());

View File

@@ -47,11 +47,13 @@ import google.registry.flows.FlowModule.Superuser;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.TransactionalFlow;
import google.registry.flows.annotations.ReportingSpec;
import google.registry.flows.domain.token.AllocationTokenFlowUtils;
import google.registry.flows.exceptions.AlreadyPendingTransferException;
import google.registry.flows.exceptions.InvalidTransferPeriodValueException;
import google.registry.flows.exceptions.ObjectAlreadySponsoredException;
import google.registry.flows.exceptions.TransferPeriodMustBeOneYearException;
import google.registry.flows.exceptions.TransferPeriodZeroAndFeeTransferExtensionException;
import google.registry.model.billing.BillingEvent.Recurring;
import google.registry.model.domain.Domain;
import google.registry.model.domain.DomainCommand.Transfer;
import google.registry.model.domain.DomainHistory;
@@ -60,6 +62,8 @@ import google.registry.model.domain.fee.FeeTransferCommandExtension;
import google.registry.model.domain.fee.FeeTransformResponseExtension;
import google.registry.model.domain.metadata.MetadataExtension;
import google.registry.model.domain.superuser.DomainTransferRequestSuperuserExtension;
import google.registry.model.domain.token.AllocationToken;
import google.registry.model.domain.token.AllocationTokenExtension;
import google.registry.model.eppcommon.AuthInfo;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.eppcommon.Trid;
@@ -116,6 +120,18 @@ import org.joda.time.DateTime;
* @error {@link DomainFlowUtils.PremiumNameBlockedException}
* @error {@link DomainFlowUtils.RegistrarMustBeActiveForThisOperationException}
* @error {@link DomainFlowUtils.UnsupportedFeeAttributeException}
* @error {@link
* google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForDomainException}
* @error {@link
* google.registry.flows.domain.token.AllocationTokenFlowUtils.InvalidAllocationTokenException}
* @error {@link
* google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotInPromotionException}
* @error {@link
* google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForRegistrarException}
* @error {@link
* google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForTldException}
* @error {@link
* google.registry.flows.domain.token.AllocationTokenFlowUtils.AlreadyRedeemedAllocationTokenException}
*/
@ReportingSpec(ActivityReportField.DOMAIN_TRANSFER_REQUEST)
public final class DomainTransferRequestFlow implements TransactionalFlow {
@@ -137,6 +153,8 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
@Inject AsyncTaskEnqueuer asyncTaskEnqueuer;
@Inject EppResponse.Builder responseBuilder;
@Inject DomainPricingLogic pricingLogic;
@Inject AllocationTokenFlowUtils allocationTokenFlowUtils;
@Inject DomainTransferRequestFlow() {}
@Override
@@ -144,12 +162,22 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
extensionManager.register(
DomainTransferRequestSuperuserExtension.class,
FeeTransferCommandExtension.class,
MetadataExtension.class);
MetadataExtension.class,
AllocationTokenExtension.class);
validateRegistrarIsLoggedIn(gainingClientId);
verifyRegistrarIsActive(gainingClientId);
extensionManager.validate();
DateTime now = tm().getTransactionTime();
Domain existingDomain = loadAndVerifyExistence(Domain.class, targetId, now);
// Currently we do not do anything with this allocation token, but just want it loaded and
// available in this flow in case we use it in the future
Optional<AllocationToken> allocationToken =
allocationTokenFlowUtils.verifyAllocationTokenIfPresent(
existingDomain,
Registry.get(existingDomain.getTld()),
gainingClientId,
now,
eppInput.getSingleExtension(AllocationTokenExtension.class));
Optional<DomainTransferRequestSuperuserExtension> superuserExtension =
eppInput.getSingleExtension(DomainTransferRequestSuperuserExtension.class);
Period period =
@@ -168,10 +196,12 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
throw new TransferPeriodZeroAndFeeTransferExtensionException();
}
// If the period is zero, then there is no fee for the transfer.
Recurring existingRecurring = tm().loadByKey(existingDomain.getAutorenewBillingEvent());
Optional<FeesAndCredits> feesAndCredits =
(period.getValue() == 0)
? Optional.empty()
: Optional.of(pricingLogic.getTransferPrice(registry, targetId, now));
: Optional.of(
pricingLogic.getTransferPrice(registry, targetId, now, existingRecurring));
if (feesAndCredits.isPresent()) {
validateFeeChallenge(targetId, now, feeTransfer, feesAndCredits.get());
}
@@ -201,6 +231,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
serverApproveNewExpirationTime,
domainHistoryKey,
existingDomain,
existingRecurring,
trid,
gainingClientId,
feesAndCredits.map(FeesAndCredits::getTotalCost),
@@ -230,7 +261,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
// the poll message if it has no events left. Note that if the automatic transfer succeeds, then
// cloneProjectedAtTime() will replace these old autorenew entities with the server approve ones
// that we've created in this flow and stored in pendingTransferData.
updateAutorenewRecurrenceEndTime(existingDomain, automaticTransferTime);
updateAutorenewRecurrenceEndTime(existingDomain, existingRecurring, automaticTransferTime);
Domain newDomain =
existingDomain
.asBuilder()

View File

@@ -24,6 +24,7 @@ import com.googlecode.objectify.Key;
import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.Flag;
import google.registry.model.billing.BillingEvent.Reason;
import google.registry.model.billing.BillingEvent.Recurring;
import google.registry.model.domain.Domain;
import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.DomainHistory.DomainHistoryId;
@@ -110,6 +111,7 @@ public final class DomainTransferUtils {
DateTime serverApproveNewExpirationTime,
Key<DomainHistory> domainHistoryKey,
Domain existingDomain,
Recurring existingRecurring,
Trid trid,
String gainingRegistrarId,
Optional<Money> transferCost,
@@ -144,7 +146,11 @@ public final class DomainTransferUtils {
return builder
.add(
createGainingClientAutorenewEvent(
serverApproveNewExpirationTime, domainHistoryKey, targetId, gainingRegistrarId))
existingRecurring,
serverApproveNewExpirationTime,
domainHistoryKey,
targetId,
gainingRegistrarId))
.add(
createGainingClientAutorenewPollMessage(
serverApproveNewExpirationTime, domainHistoryKey, targetId, gainingRegistrarId))
@@ -239,6 +245,7 @@ public final class DomainTransferUtils {
}
private static BillingEvent.Recurring createGainingClientAutorenewEvent(
Recurring existingRecurring,
DateTime serverApproveNewExpirationTime,
Key<DomainHistory> domainHistoryKey,
String targetId,
@@ -250,6 +257,8 @@ public final class DomainTransferUtils {
.setRegistrarId(gainingRegistrarId)
.setEventTime(serverApproveNewExpirationTime)
.setRecurrenceEndTime(END_OF_TIME)
.setRenewalPriceBehavior(existingRecurring.getRenewalPriceBehavior())
.setRenewalPrice(existingRecurring.getRenewalPrice().orElse(null))
.setDomainHistoryId(
new DomainHistoryId(domainHistoryKey.getParent().getName(), domainHistoryKey.getId()))
.build();

View File

@@ -30,8 +30,8 @@ import google.registry.model.eppinput.ResourceCommand;
import google.registry.model.eppoutput.CheckData.HostCheck;
import google.registry.model.eppoutput.CheckData.HostCheckData;
import google.registry.model.eppoutput.EppResponse;
import google.registry.model.host.Host;
import google.registry.model.host.HostCommand.Check;
import google.registry.model.host.HostResource;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
import google.registry.util.Clock;
import javax.inject.Inject;
@@ -61,8 +61,7 @@ public final class HostCheckFlow implements Flow {
extensionManager.validate(); // There are no legal extensions for this flow.
ImmutableList<String> hostnames = ((Check) resourceCommand).getTargetIds();
verifyTargetIdCount(hostnames, maxChecks);
ImmutableSet<String> existingIds =
checkResourcesExist(HostResource.class, hostnames, clock.nowUtc());
ImmutableSet<String> existingIds = checkResourcesExist(Host.class, hostnames, clock.nowUtc());
ImmutableList.Builder<HostCheck> checks = new ImmutableList.Builder<>();
for (String hostname : hostnames) {
boolean unused = !existingIds.contains(hostname);

View File

@@ -46,9 +46,9 @@ import google.registry.model.domain.metadata.MetadataExtension;
import google.registry.model.eppinput.ResourceCommand;
import google.registry.model.eppoutput.CreateData.HostCreateData;
import google.registry.model.eppoutput.EppResponse;
import google.registry.model.host.Host;
import google.registry.model.host.HostCommand.Create;
import google.registry.model.host.HostHistory;
import google.registry.model.host.HostResource;
import google.registry.model.index.EppResourceIndex;
import google.registry.model.index.ForeignKeyIndex;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
@@ -105,7 +105,7 @@ public final class HostCreateFlow implements TransactionalFlow {
extensionManager.validate();
Create command = (Create) resourceCommand;
DateTime now = tm().getTransactionTime();
verifyResourceDoesNotExist(HostResource.class, targetId, now, registrarId);
verifyResourceDoesNotExist(Host.class, targetId, now, registrarId);
// The superordinate domain of the host object if creating an in-bailiwick host, or null if
// creating an external host. This is looked up before we actually create the Host object so
// we can detect error conditions earlier.
@@ -121,8 +121,8 @@ public final class HostCreateFlow implements TransactionalFlow {
? new SubordinateHostMustHaveIpException()
: new UnexpectedExternalHostIpException();
}
HostResource newHost =
new HostResource.Builder()
Host newHost =
new Host.Builder()
.setCreationRegistrarId(registrarId)
.setPersistedCurrentSponsorRegistrarId(registrarId)
.setHostName(targetId)

View File

@@ -38,8 +38,8 @@ import google.registry.model.domain.metadata.MetadataExtension;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.eppcommon.Trid;
import google.registry.model.eppoutput.EppResponse;
import google.registry.model.host.Host;
import google.registry.model.host.HostHistory;
import google.registry.model.host.HostResource;
import google.registry.model.reporting.HistoryEntry.Type;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
import javax.inject.Inject;
@@ -92,8 +92,8 @@ public final class HostDeleteFlow implements TransactionalFlow {
extensionManager.validate();
DateTime now = tm().getTransactionTime();
validateHostName(targetId);
checkLinkedDomains(targetId, now, HostResource.class);
HostResource existingHost = loadAndVerifyExistence(HostResource.class, targetId, now);
checkLinkedDomains(targetId, now, Host.class);
Host existingHost = loadAndVerifyExistence(Host.class, targetId, now);
verifyNoDisallowedStatuses(existingHost, DISALLOWED_STATUSES);
if (!isSuperuser) {
// Hosts transfer with their superordinate domains, so for hosts with a superordinate domain,
@@ -104,8 +104,7 @@ public final class HostDeleteFlow implements TransactionalFlow {
: existingHost;
verifyResourceOwnership(registrarId, owningResource);
}
HostResource newHost =
existingHost.asBuilder().setStatusValues(null).setDeletionTime(now).build();
Host newHost = existingHost.asBuilder().setStatusValues(null).setDeletionTime(now).build();
if (existingHost.isSubordinate()) {
dnsQueue.addHostRefreshTask(existingHost.getHostName());
tm().update(

View File

@@ -30,8 +30,8 @@ import google.registry.flows.annotations.ReportingSpec;
import google.registry.model.domain.Domain;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.eppoutput.EppResponse;
import google.registry.model.host.Host;
import google.registry.model.host.HostInfoData;
import google.registry.model.host.HostResource;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
import google.registry.util.Clock;
import javax.inject.Inject;
@@ -65,7 +65,7 @@ public final class HostInfoFlow implements Flow {
extensionManager.validate(); // There are no legal extensions for this flow.
validateHostName(targetId);
DateTime now = clock.nowUtc();
HostResource host = loadAndVerifyExistence(HostResource.class, targetId, now);
Host host = loadAndVerifyExistence(Host.class, targetId, now);
ImmutableSet.Builder<StatusValue> statusValues = new ImmutableSet.Builder<>();
statusValues.addAll(host.getStatusValues());
if (isLinked(host.createVKey(), now)) {

View File

@@ -52,11 +52,11 @@ import google.registry.model.domain.metadata.MetadataExtension;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.eppinput.ResourceCommand;
import google.registry.model.eppoutput.EppResponse;
import google.registry.model.host.Host;
import google.registry.model.host.HostCommand.Update;
import google.registry.model.host.HostCommand.Update.AddRemove;
import google.registry.model.host.HostCommand.Update.Change;
import google.registry.model.host.HostHistory;
import google.registry.model.host.HostResource;
import google.registry.model.index.ForeignKeyIndex;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
import google.registry.persistence.VKey;
@@ -133,7 +133,7 @@ public final class HostUpdateFlow implements TransactionalFlow {
String suppliedNewHostName = change.getFullyQualifiedHostName();
DateTime now = tm().getTransactionTime();
validateHostName(targetId);
HostResource existingHost = loadAndVerifyExistence(HostResource.class, targetId, now);
Host existingHost = loadAndVerifyExistence(Host.class, targetId, now);
boolean isHostRename = suppliedNewHostName != null;
String oldHostName = targetId;
String newHostName = firstNonNull(suppliedNewHostName, oldHostName);
@@ -148,7 +148,7 @@ public final class HostUpdateFlow implements TransactionalFlow {
EppResource owningResource = firstNonNull(oldSuperordinateDomain, existingHost);
verifyUpdateAllowed(
command, existingHost, newSuperordinateDomain.orElse(null), owningResource, isHostRename);
if (isHostRename && loadAndGetKey(HostResource.class, newHostName, now) != null) {
if (isHostRename && loadAndGetKey(Host.class, newHostName, now) != null) {
throw new HostAlreadyExistsException(newHostName);
}
AddRemove add = command.getInnerAdd();
@@ -175,7 +175,7 @@ public final class HostUpdateFlow implements TransactionalFlow {
newSuperordinateDomain.isPresent()
? newSuperordinateDomain.get().getCurrentSponsorRegistrarId()
: owningResource.getPersistedCurrentSponsorRegistrarId();
HostResource newHost =
Host newHost =
existingHost
.asBuilder()
.setHostName(newHostName)
@@ -210,7 +210,7 @@ public final class HostUpdateFlow implements TransactionalFlow {
private void verifyUpdateAllowed(
Update command,
HostResource existingHost,
Host existingHost,
Domain newSuperordinateDomain,
EppResource owningResource,
boolean isHostRename)
@@ -237,8 +237,8 @@ public final class HostUpdateFlow implements TransactionalFlow {
verifyNoDisallowedStatuses(existingHost, DISALLOWED_STATUSES);
}
private void verifyHasIpsIffIsExternal(
Update command, HostResource existingHost, HostResource newHost) throws EppException {
private void verifyHasIpsIffIsExternal(Update command, Host existingHost, Host newHost)
throws EppException {
boolean wasSubordinate = existingHost.isSubordinate();
boolean willBeSubordinate = newHost.isSubordinate();
boolean willBeExternal = !willBeSubordinate;
@@ -258,7 +258,7 @@ public final class HostUpdateFlow implements TransactionalFlow {
}
}
private void enqueueTasks(HostResource existingHost, HostResource newHost) {
private void enqueueTasks(Host existingHost, Host newHost) {
// Only update DNS for subordinate hosts. External hosts have no glue to write, so they
// are only written as NS records from the referencing domain.
if (existingHost.isSubordinate()) {
@@ -277,7 +277,7 @@ public final class HostUpdateFlow implements TransactionalFlow {
}
}
private static void updateSuperordinateDomains(HostResource existingHost, HostResource newHost) {
private static void updateSuperordinateDomains(Host existingHost, Host newHost) {
if (existingHost.isSubordinate()
&& newHost.isSubordinate()
&& Objects.equals(

View File

@@ -41,7 +41,7 @@ public abstract class BackupGroupRoot extends ImmutableObject implements UnsafeS
* that this is updated on every save, rather than only in response to an {@code <update>} command
*/
@XmlTransient
// Prevents subclasses from unexpectedly accessing as property (e.g., HostResource), which would
// Prevents subclasses from unexpectedly accessing as property (e.g., Host), which would
// require an unnecessary non-private setter method.
@Access(AccessType.FIELD)
@AttributeOverride(name = "lastUpdateTime", column = @Column(name = "updateTimestamp"))

View File

@@ -23,8 +23,8 @@ import google.registry.model.contact.ContactResource;
import google.registry.model.domain.Domain;
import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.token.AllocationToken;
import google.registry.model.host.Host;
import google.registry.model.host.HostHistory;
import google.registry.model.host.HostResource;
import google.registry.model.index.EppResourceIndex;
import google.registry.model.index.EppResourceIndexBucket;
import google.registry.model.index.ForeignKeyIndex;
@@ -55,8 +55,8 @@ public final class EntityClasses {
ForeignKeyIndex.ForeignKeyHostIndex.class,
GaeUserIdConverter.class,
HistoryEntry.class,
Host.class,
HostHistory.class,
HostResource.class,
Lock.class,
PollMessage.class,
PollMessage.Autorenew.class,

View File

@@ -35,7 +35,7 @@ import google.registry.model.EppResource.ResourceWithTransferData;
import google.registry.model.contact.ContactResource;
import google.registry.model.domain.Domain;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.model.index.ForeignKeyIndex;
import google.registry.model.reporting.HistoryEntry;
import google.registry.model.reporting.HistoryEntryDao;
@@ -345,8 +345,8 @@ public final class EppResourceUtils {
public static ImmutableSet<VKey<Domain>> getLinkedDomainKeys(
VKey<? extends EppResource> key, DateTime now, @Nullable Integer limit) {
checkArgument(
key.getKind().equals(ContactResource.class) || key.getKind().equals(HostResource.class),
"key must be either VKey<ContactResource> or VKey<HostResource>, but it is %s",
key.getKind().equals(ContactResource.class) || key.getKind().equals(Host.class),
"key must be either VKey<ContactResource> or VKey<Host>, but it is %s",
key);
boolean isContactKey = key.getKind().equals(ContactResource.class);
if (tm().isOfy()) {

View File

@@ -26,7 +26,7 @@ import google.registry.model.domain.GracePeriod;
import google.registry.model.domain.GracePeriod.GracePeriodHistory;
import google.registry.model.domain.secdns.DelegationSignerData;
import google.registry.model.domain.secdns.DomainDsDataHistory;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.model.reporting.DomainTransactionRecord;
import google.registry.persistence.VKey;
import google.registry.persistence.transaction.JpaTransactionManager;
@@ -68,7 +68,7 @@ public class BulkQueryEntities {
DomainLite domainLite,
ImmutableSet<GracePeriod> gracePeriods,
ImmutableSet<DelegationSignerData> delegationSignerData,
ImmutableSet<VKey<HostResource>> nsHosts) {
ImmutableSet<VKey<Host>> nsHosts) {
Domain.Builder builder = new Domain.Builder();
builder.copyFrom(domainLite);
builder.setGracePeriods(gracePeriods);
@@ -82,7 +82,7 @@ public class BulkQueryEntities {
public static DomainHistory assembleDomainHistory(
DomainHistoryLite domainHistoryLite,
ImmutableSet<DomainDsDataHistory> dsDataHistories,
ImmutableSet<VKey<HostResource>> domainHistoryHosts,
ImmutableSet<VKey<Host>> domainHistoryHosts,
ImmutableSet<GracePeriodHistory> gracePeriodHistories,
ImmutableSet<DomainTransactionRecord> transactionRecords) {
DomainHistory.Builder builder = new DomainHistory.Builder();

View File

@@ -16,7 +16,7 @@ package google.registry.model.bulkquery;
import com.google.common.base.Objects;
import google.registry.model.domain.DomainHistory.DomainHistoryId;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.persistence.VKey;
import java.io.Serializable;
import javax.persistence.Access;
@@ -44,8 +44,8 @@ public class DomainHistoryHost implements Serializable {
return new DomainHistoryId(domainHistoryDomainRepoId, domainHistoryHistoryRevisionId);
}
public VKey<HostResource> getHostVKey() {
return VKey.create(HostResource.class, hostRepoId);
public VKey<Host> getHostVKey() {
return VKey.create(Host.class, hostRepoId);
}
@Override

View File

@@ -15,7 +15,7 @@
package google.registry.model.bulkquery;
import com.google.common.base.Objects;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.persistence.VKey;
import java.io.Serializable;
import javax.persistence.Access;
@@ -40,8 +40,8 @@ public class DomainHost implements Serializable {
return domainRepoId;
}
public VKey<HostResource> getHostVKey() {
return VKey.create(HostResource.class, hostRepoId);
public VKey<Host> getHostVKey() {
return VKey.create(Host.class, hostRepoId);
}
@Override

View File

@@ -0,0 +1,67 @@
// Copyright 2022 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.console;
/** Permissions that users may have in the UI, either per-registrar or globally. */
public enum ConsolePermission {
/** Add, update, or remove other console users. */
MANAGE_USERS,
/** Add, update, or remove registrars. */
MANAGE_REGISTRARS,
/** Manage related registrars, e.g. when one registrar owns another. */
MANAGE_ACCREDITATION,
/** Set up the EPP connection (e.g. certs). */
CONFIGURE_EPP_CONNECTION,
/** Retrieve the unredacted registrant email from a domain. */
GET_REGISTRANT_EMAIL,
/** Suspend a domain for compliance (non-URS) reasons. */
SUSPEND_DOMAIN,
/** Suspend a domain for the Uniform Rapid Suspension process. */
SUSPEND_DOMAIN_URS,
/** Download a list of domains under management. */
DOWNLOAD_DOMAINS,
/** Change the password for a registrar. */
CHANGE_NOMULUS_PASSWORD,
/** View all possible TLDs. */
VIEW_TLD_PORTFOLIO,
/** Onboarding the registrar(s) to extra programs like registry locking. */
ONBOARD_ADDITIONAL_PROGRAMS,
/** Execute arbitrary EPP commands through the UI. */
EXECUTE_EPP_COMMANDS,
/** Send messages to the registry support team. */
CONTACT_SUPPORT,
/** Access billing and payment details for a registrar. */
ACCESS_BILLING_DETAILS,
/** Access any available documentation about the registry. */
ACCESS_DOCUMENTATION,
/** Change the documentation available in the UI about the registry. */
MANAGE_DOCUMENTATION,
/** Viewing the onboarding status of a registrar on a TLD. */
CHECK_ONBOARDING_STATUS,
/** View premium and/or reserved lists for a TLD. */
VIEW_PREMIUM_RESERVED_LISTS,
/** Sign and/or change legal documents like RRAs. */
UPLOAD_CONTRACTS,
/** Viewing legal documents like RRAs. */
ACCESS_CONTRACTS,
/** View analytics on operations and billing data (possibly TBD). */
VIEW_OPERATIONAL_DATA,
/** Create announcements that can be displayed in the UI. */
SEND_ANNOUNCEMENTS,
/** View announcements in the UI. */
VIEW_ANNOUNCEMENTS,
/** Viewing a record of actions performed in the UI for a particular registrar. */
VIEW_ACTIVITY_LOG
}

View File

@@ -0,0 +1,104 @@
// Copyright 2022 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.console;
import com.google.common.collect.ImmutableSet;
/**
* Definitions of the {@link ConsolePermission} sets that each role contains.
*
* <p>Note: within the "registry" and "registrar" groupings, permissions expand hierarchically,
* where each role has all the permissions of the role below it plus some others.
*/
public class ConsoleRoleDefinitions {
/** Permissions for a registry support agent. */
static final ImmutableSet<ConsolePermission> SUPPORT_AGENT_PERMISSIONS =
ImmutableSet.of(
ConsolePermission.MANAGE_USERS,
ConsolePermission.MANAGE_ACCREDITATION,
ConsolePermission.CONFIGURE_EPP_CONNECTION,
ConsolePermission.DOWNLOAD_DOMAINS,
ConsolePermission.VIEW_TLD_PORTFOLIO,
ConsolePermission.ONBOARD_ADDITIONAL_PROGRAMS,
ConsolePermission.CONTACT_SUPPORT,
ConsolePermission.ACCESS_BILLING_DETAILS,
ConsolePermission.ACCESS_DOCUMENTATION,
ConsolePermission.SUSPEND_DOMAIN_URS,
ConsolePermission.CHECK_ONBOARDING_STATUS,
ConsolePermission.VIEW_PREMIUM_RESERVED_LISTS,
ConsolePermission.UPLOAD_CONTRACTS,
ConsolePermission.ACCESS_CONTRACTS,
ConsolePermission.VIEW_OPERATIONAL_DATA,
ConsolePermission.SEND_ANNOUNCEMENTS,
ConsolePermission.VIEW_ANNOUNCEMENTS,
ConsolePermission.VIEW_ACTIVITY_LOG);
/** Permissions for a registry support lead. */
static final ImmutableSet<ConsolePermission> SUPPORT_LEAD_PERMISSIONS =
new ImmutableSet.Builder<ConsolePermission>()
.addAll(SUPPORT_AGENT_PERMISSIONS)
.add(
ConsolePermission.MANAGE_REGISTRARS,
ConsolePermission.GET_REGISTRANT_EMAIL,
ConsolePermission.SUSPEND_DOMAIN,
ConsolePermission.EXECUTE_EPP_COMMANDS,
ConsolePermission.MANAGE_DOCUMENTATION)
.build();
/** Permissions for a registry full-time employee. */
static final ImmutableSet<ConsolePermission> FTE_PERMISSIONS =
new ImmutableSet.Builder<ConsolePermission>()
.addAll(SUPPORT_LEAD_PERMISSIONS)
.add(ConsolePermission.CHANGE_NOMULUS_PASSWORD)
.build();
/** Permissions for a registrar partner account manager. */
static final ImmutableSet<ConsolePermission> ACCOUNT_MANAGER_PERMISSIONS =
ImmutableSet.of(
ConsolePermission.DOWNLOAD_DOMAINS,
ConsolePermission.VIEW_TLD_PORTFOLIO,
ConsolePermission.CONTACT_SUPPORT,
ConsolePermission.ACCESS_DOCUMENTATION,
ConsolePermission.VIEW_PREMIUM_RESERVED_LISTS,
ConsolePermission.VIEW_OPERATIONAL_DATA,
ConsolePermission.VIEW_ANNOUNCEMENTS);
/** Permissions for the tech contact of a registrar. */
static final ImmutableSet<ConsolePermission> TECH_CONTACT_PERMISSIONS =
new ImmutableSet.Builder<ConsolePermission>()
.addAll(ACCOUNT_MANAGER_PERMISSIONS)
.add(
ConsolePermission.MANAGE_ACCREDITATION,
ConsolePermission.CONFIGURE_EPP_CONNECTION,
ConsolePermission.CHANGE_NOMULUS_PASSWORD,
ConsolePermission.ONBOARD_ADDITIONAL_PROGRAMS,
ConsolePermission.EXECUTE_EPP_COMMANDS,
ConsolePermission.ACCESS_BILLING_DETAILS,
ConsolePermission.CHECK_ONBOARDING_STATUS,
ConsolePermission.UPLOAD_CONTRACTS,
ConsolePermission.ACCESS_CONTRACTS,
ConsolePermission.VIEW_ACTIVITY_LOG)
.build();
/** Permissions for the primary registrar contact. */
static final ImmutableSet<ConsolePermission> PRIMARY_CONTACT_PERMISSIONS =
new ImmutableSet.Builder<ConsolePermission>()
.addAll(TECH_CONTACT_PERMISSIONS)
.add(ConsolePermission.MANAGE_USERS)
.build();
private ConsoleRoleDefinitions() {}
}

View File

@@ -0,0 +1,44 @@
// Copyright 2022 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.console;
import static google.registry.model.console.ConsoleRoleDefinitions.FTE_PERMISSIONS;
import static google.registry.model.console.ConsoleRoleDefinitions.SUPPORT_AGENT_PERMISSIONS;
import static google.registry.model.console.ConsoleRoleDefinitions.SUPPORT_LEAD_PERMISSIONS;
import com.google.common.collect.ImmutableSet;
/** Roles for registry employees that apply across all registrars. */
public enum GlobalRole {
/** The user has no global role, i.e. they're a registrar partner. */
NONE(ImmutableSet.of()),
/** The user is a registry support agent. */
SUPPORT_AGENT(SUPPORT_AGENT_PERMISSIONS),
/** The user is a registry support lead. */
SUPPORT_LEAD(SUPPORT_LEAD_PERMISSIONS),
/** The user is a registry full-time employee. */
FTE(FTE_PERMISSIONS);
private final ImmutableSet<ConsolePermission> permissions;
GlobalRole(ImmutableSet<ConsolePermission> permissions) {
this.permissions = permissions;
}
public boolean hasPermission(ConsolePermission permission) {
return permissions.contains(permission);
}
}

View File

@@ -0,0 +1,42 @@
// Copyright 2022 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.console;
import static google.registry.model.console.ConsoleRoleDefinitions.ACCOUNT_MANAGER_PERMISSIONS;
import static google.registry.model.console.ConsoleRoleDefinitions.PRIMARY_CONTACT_PERMISSIONS;
import static google.registry.model.console.ConsoleRoleDefinitions.TECH_CONTACT_PERMISSIONS;
import com.google.common.collect.ImmutableSet;
/** Roles for registrar partners that apply to only one registrar. */
public enum RegistrarRole {
/** The user is a standard account manager at a registrar. */
ACCOUNT_MANAGER(ACCOUNT_MANAGER_PERMISSIONS),
/** The user is a technical contact of a registrar. */
TECH_CONTACT(TECH_CONTACT_PERMISSIONS),
/** The user is the primary contact at a registrar. */
PRIMARY_CONTACT(PRIMARY_CONTACT_PERMISSIONS);
private final ImmutableSet<ConsolePermission> permissions;
RegistrarRole(ImmutableSet<ConsolePermission> permissions) {
this.permissions = permissions;
}
public boolean hasPermission(ConsolePermission permission) {
return permissions.contains(permission);
}
}

View File

@@ -0,0 +1,148 @@
// Copyright 2022 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.console;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Strings.isNullOrEmpty;
import static com.google.common.io.BaseEncoding.base64;
import static google.registry.model.registrar.Registrar.checkValidEmail;
import static google.registry.util.PasswordUtils.SALT_SUPPLIER;
import static google.registry.util.PasswordUtils.hashPassword;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import google.registry.model.Buildable;
import google.registry.model.ImmutableObject;
/** A console user, either a registry employee or a registrar partner. */
public class User extends ImmutableObject implements Buildable {
/** Autogenerated unique ID of this user. */
private long id;
/** GAIA ID associated with the user in question. */
private String gaiaId;
/** Email address of the user in question. */
private String emailAddress;
/** Roles (which grant permissions) associated with this user. */
private UserRoles userRoles;
/**
* Whether the contact is allowed to set their registry lock password through the registrar
* console. This will be set to false on contact creation and when the user sets a password.
*/
boolean allowedToSetRegistryLockPassword = false;
/**
* A hashed password that exists iff this contact is registry-lock-enabled. The hash is a base64
* encoded SHA256 string.
*/
String registryLockPasswordHash;
/** Randomly generated hash salt. */
String registryLockPasswordSalt;
public String getGaiaId() {
return gaiaId;
}
public String getEmailAddress() {
return emailAddress;
}
public UserRoles getUserRoles() {
return userRoles;
}
public boolean isAllowedToSetRegistryLockPassword() {
return allowedToSetRegistryLockPassword;
}
public boolean isRegistryLockAllowed() {
return !isNullOrEmpty(registryLockPasswordHash) && !isNullOrEmpty(registryLockPasswordSalt);
}
public boolean verifyRegistryLockPassword(String registryLockPassword) {
if (isNullOrEmpty(registryLockPassword)
|| isNullOrEmpty(registryLockPasswordSalt)
|| isNullOrEmpty(registryLockPasswordHash)) {
return false;
}
return hashPassword(registryLockPassword, registryLockPasswordSalt)
.equals(registryLockPasswordHash);
}
@Override
public Builder asBuilder() {
return new Builder(clone(this));
}
/** Builder for constructing immutable {@link User} objects. */
public static class Builder extends Buildable.Builder<User> {
public Builder() {}
public Builder(User user) {
super(user);
}
public User build() {
checkArgumentNotNull(getInstance().gaiaId, "Gaia ID cannot be null");
checkArgumentNotNull(getInstance().emailAddress, "Email address cannot be null");
checkArgumentNotNull(getInstance().userRoles, "User roles cannot be null");
return super.build();
}
public Builder setGaiaId(String gaiaId) {
checkArgument(!isNullOrEmpty(gaiaId), "Gaia ID cannot be null or empty");
getInstance().gaiaId = gaiaId;
return this;
}
public Builder setEmailAddress(String emailAddress) {
getInstance().emailAddress = checkValidEmail(emailAddress);
return this;
}
public Builder setUserRoles(UserRoles userRoles) {
checkArgumentNotNull(userRoles, "User roles cannot be null");
getInstance().userRoles = userRoles;
return this;
}
public Builder setAllowedToSetRegistryLockPassword(boolean allowedToSetRegistryLockPassword) {
if (allowedToSetRegistryLockPassword) {
getInstance().registryLockPasswordSalt = null;
getInstance().registryLockPasswordHash = null;
}
getInstance().allowedToSetRegistryLockPassword = allowedToSetRegistryLockPassword;
return this;
}
public Builder setRegistryLockPassword(String registryLockPassword) {
checkArgument(
getInstance().allowedToSetRegistryLockPassword,
"Not allowed to set registry lock password for this user");
checkArgument(
!isNullOrEmpty(registryLockPassword), "Registry lock password was null or empty");
getInstance().registryLockPasswordSalt = base64().encode(SALT_SUPPLIER.get());
getInstance().registryLockPasswordHash =
hashPassword(registryLockPassword, getInstance().registryLockPasswordSalt);
getInstance().allowedToSetRegistryLockPassword = false;
return this;
}
}
}

View File

@@ -0,0 +1,120 @@
// Copyright 2022 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.console;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import com.google.common.collect.ImmutableMap;
import google.registry.model.Buildable;
import google.registry.model.ImmutableObject;
import java.util.Map;
/**
* Contains the global and per-registrar roles for a given user.
*
* <p>See <a href="https://go/nomulus-console-authz">go/nomulus-console-authz</a> for more
* information.
*/
public class UserRoles extends ImmutableObject implements Buildable {
/** Whether the user is a global admin, who has access to everything. */
private boolean isAdmin = false;
/**
* The global role (e.g. {@link GlobalRole#SUPPORT_AGENT}) that the user has across all
* registrars.
*/
private GlobalRole globalRole = GlobalRole.NONE;
/** Any per-registrar roles that this user may have. */
private Map<String, RegistrarRole> registrarRoles = ImmutableMap.of();
/** Whether the user is a global admin, who has access to everything. */
public boolean isAdmin() {
return isAdmin;
}
/**
* The global role (e.g. {@link GlobalRole#SUPPORT_AGENT}) that the user has across all
* registrars.
*/
public GlobalRole getGlobalRole() {
return globalRole;
}
/** Any per-registrar roles that this user may have. */
public Map<String, RegistrarRole> getRegistrarRoles() {
return ImmutableMap.copyOf(registrarRoles);
}
/** If the user has the given permission either globally or on the given registrar. */
public boolean hasPermission(String registrarId, ConsolePermission permission) {
if (hasGlobalPermission(permission)) {
return true;
}
if (!registrarRoles.containsKey(registrarId)) {
return false;
}
return registrarRoles.get(registrarId).hasPermission(permission);
}
/** If the user has the given permission globally across all registrars. */
public boolean hasGlobalPermission(ConsolePermission permission) {
return isAdmin || globalRole.hasPermission(permission);
}
@Override
public Builder asBuilder() {
return new Builder(clone(this));
}
/** Builder for constructing immutable {@link UserRoles} objects. */
public static class Builder extends Buildable.Builder<UserRoles> {
public Builder() {}
private Builder(UserRoles userRoles) {
super(userRoles);
}
@Override
public UserRoles build() {
// Users should only have a global role or per-registrar roles, not both
checkArgument(
getInstance().globalRole.equals(GlobalRole.NONE)
|| getInstance().registrarRoles.isEmpty(),
"Users cannot have both global and per-registrar roles");
return super.build();
}
public Builder setIsAdmin(boolean isAdmin) {
getInstance().isAdmin = isAdmin;
return this;
}
public Builder setGlobalRole(GlobalRole globalRole) {
checkArgumentNotNull(globalRole, "Global role cannot be null");
getInstance().globalRole = globalRole;
return this;
}
public Builder setRegistrarRoles(Map<String, RegistrarRole> registrarRoles) {
checkArgumentNotNull(registrarRoles, "Registrar roles map cannot be null");
getInstance().registrarRoles = ImmutableMap.copyOf(registrarRoles);
return this;
}
}
}

View File

@@ -20,7 +20,7 @@ import google.registry.model.EppResource.ForeignKeyedEppResource;
import google.registry.model.annotations.ExternalMessagingName;
import google.registry.model.annotations.ReportedOn;
import google.registry.model.domain.secdns.DelegationSignerData;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.persistence.VKey;
import google.registry.persistence.WithStringVKey;
import java.util.Set;
@@ -89,7 +89,7 @@ public class Domain extends DomainBase implements ForeignKeyedEppResource {
})
@Access(AccessType.PROPERTY)
@Column(name = "host_repo_id")
public Set<VKey<HostResource>> getNsHosts() {
public Set<VKey<Host>> getNsHosts() {
return super.nsHosts;
}
@@ -210,7 +210,8 @@ public class Domain extends DomainBase implements ForeignKeyedEppResource {
.setSubordinateHosts(domainBase.getSubordinateHosts())
.setStatusValues(domainBase.getStatusValues())
.setTransferData(domainBase.getTransferData())
.setDnsRefreshRequestTime(domainBase.getDnsRefreshRequestTime());
.setDnsRefreshRequestTime(domainBase.getDnsRefreshRequestTime())
.setCurrentPackageToken(domainBase.getCurrentPackageToken().orElse(null));
}
}
}

View File

@@ -56,8 +56,9 @@ import google.registry.model.contact.ContactResource;
import google.registry.model.domain.launch.LaunchNotice;
import google.registry.model.domain.rgp.GracePeriodStatus;
import google.registry.model.domain.secdns.DelegationSignerData;
import google.registry.model.domain.token.AllocationToken;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.model.poll.PollMessage;
import google.registry.model.reporting.HistoryEntry;
import google.registry.model.tld.Registry;
@@ -128,7 +129,7 @@ public class DomainBase extends EppResource
@Index String tld;
/** References to hosts that are the nameservers for the domain. */
@EmptySetToNull @Index @Transient Set<VKey<HostResource>> nsHosts;
@EmptySetToNull @Index @Transient Set<VKey<Host>> nsHosts;
/** Contacts. */
VKey<ContactResource> adminContact;
@@ -282,6 +283,9 @@ public class DomainBase extends EppResource
// TODO(mcilwain): Start using this field once we are further along in the DB migration.
@Ignore DateTime dnsRefreshRequestTime;
/** The {@link AllocationToken} for the package this domain is currently a part of. */
@Nullable VKey<AllocationToken> currentPackageToken;
/**
* Returns the DNS refresh request time iff this domain's DNS needs refreshing, otherwise absent.
*/
@@ -330,6 +334,10 @@ public class DomainBase extends EppResource
return smdId;
}
public Optional<VKey<AllocationToken>> getCurrentPackageToken() {
return Optional.ofNullable(currentPackageToken);
}
/**
* Returns the autorenew end time if there is one, otherwise empty.
*
@@ -372,13 +380,13 @@ public class DomainBase extends EppResource
return idnTableName;
}
public ImmutableSet<VKey<HostResource>> getNameservers() {
public ImmutableSet<VKey<Host>> getNameservers() {
return nullToEmptyImmutableCopy(nsHosts);
}
// Hibernate needs this in order to populate nsHosts but no one else should ever use it
@SuppressWarnings("UnusedMethod")
private void setNsHosts(Set<VKey<HostResource>> nsHosts) {
private void setNsHosts(Set<VKey<Host>> nsHosts) {
this.nsHosts = forceEmptyToNull(nsHosts);
}
@@ -602,7 +610,7 @@ public class DomainBase extends EppResource
return tm().transact(
() ->
tm().loadByKeys(getNameservers()).values().stream()
.map(HostResource::getHostName)
.map(Host::getHostName)
.collect(toImmutableSortedSet(Ordering.natural())));
}
@@ -787,32 +795,32 @@ public class DomainBase extends EppResource
return thisCastToDerived();
}
public B setNameservers(VKey<HostResource> nameserver) {
public B setNameservers(VKey<Host> nameserver) {
getInstance().nsHosts = ImmutableSet.of(nameserver);
getInstance().resetUpdateTimestamp();
return thisCastToDerived();
}
public B setNameservers(ImmutableSet<VKey<HostResource>> nameservers) {
public B setNameservers(ImmutableSet<VKey<Host>> nameservers) {
getInstance().nsHosts = forceEmptyToNull(nameservers);
getInstance().resetUpdateTimestamp();
return thisCastToDerived();
}
public B addNameserver(VKey<HostResource> nameserver) {
public B addNameserver(VKey<Host> nameserver) {
return addNameservers(ImmutableSet.of(nameserver));
}
public B addNameservers(ImmutableSet<VKey<HostResource>> nameservers) {
public B addNameservers(ImmutableSet<VKey<Host>> nameservers) {
return setNameservers(
ImmutableSet.copyOf(Sets.union(getInstance().getNameservers(), nameservers)));
}
public B removeNameserver(VKey<HostResource> nameserver) {
public B removeNameserver(VKey<Host> nameserver) {
return removeNameservers(ImmutableSet.of(nameserver));
}
public B removeNameservers(ImmutableSet<VKey<HostResource>> nameservers) {
public B removeNameservers(ImmutableSet<VKey<Host>> nameservers) {
return setNameservers(
ImmutableSet.copyOf(difference(getInstance().getNameservers(), nameservers)));
}
@@ -938,5 +946,10 @@ public class DomainBase extends EppResource
getInstance().lastTransferTime = lastTransferTime;
return thisCastToDerived();
}
public B setCurrentPackageToken(@Nullable VKey<AllocationToken> currentPackageToken) {
getInstance().currentPackageToken = currentPackageToken;
return thisCastToDerived();
}
}
}

View File

@@ -38,7 +38,7 @@ import google.registry.model.eppinput.ResourceCommand.ResourceCheck;
import google.registry.model.eppinput.ResourceCommand.ResourceCreateOrChange;
import google.registry.model.eppinput.ResourceCommand.ResourceUpdate;
import google.registry.model.eppinput.ResourceCommand.SingleResourceCommand;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.model.index.ForeignKeyIndex;
import google.registry.persistence.VKey;
import java.util.Set;
@@ -126,7 +126,7 @@ public class DomainCommand {
Set<String> nameserverFullyQualifiedHostNames;
/** Resolved keys to hosts that are the nameservers for the domain. */
@XmlTransient Set<VKey<HostResource>> nameservers;
@XmlTransient Set<VKey<Host>> nameservers;
/** Foreign keyed associated contacts for the domain (other than registrant). */
@XmlElement(name = "contact")
@@ -156,7 +156,7 @@ public class DomainCommand {
return nullToEmptyImmutableCopy(nameserverFullyQualifiedHostNames);
}
public ImmutableSet<VKey<HostResource>> getNameservers() {
public ImmutableSet<VKey<Host>> getNameservers() {
return nullToEmptyImmutableCopy(nameservers);
}
@@ -349,7 +349,7 @@ public class DomainCommand {
Set<String> nameserverFullyQualifiedHostNames;
/** Resolved keys to hosts that are the nameservers for the domain. */
@XmlTransient Set<VKey<HostResource>> nameservers;
@XmlTransient Set<VKey<Host>> nameservers;
/** Foreign keyed associated contacts for the domain (other than registrant). */
@XmlElement(name = "contact")
@@ -363,7 +363,7 @@ public class DomainCommand {
return nullSafeImmutableCopy(nameserverFullyQualifiedHostNames);
}
public ImmutableSet<VKey<HostResource>> getNameservers() {
public ImmutableSet<VKey<Host>> getNameservers() {
return nullToEmptyImmutableCopy(nameservers);
}
@@ -413,13 +413,13 @@ public class DomainCommand {
}
}
private static Set<VKey<HostResource>> linkHosts(
Set<String> fullyQualifiedHostNames, DateTime now) throws InvalidReferencesException {
private static Set<VKey<Host>> linkHosts(Set<String> fullyQualifiedHostNames, DateTime now)
throws InvalidReferencesException {
if (fullyQualifiedHostNames == null) {
return null;
}
return ImmutableSet.copyOf(
loadByForeignKeysCached(fullyQualifiedHostNames, HostResource.class, now).values());
loadByForeignKeysCached(fullyQualifiedHostNames, Host.class, now).values());
}
private static Set<DesignatedContact> linkContacts(

View File

@@ -26,7 +26,7 @@ import google.registry.model.domain.DomainHistory.DomainHistoryId;
import google.registry.model.domain.GracePeriod.GracePeriodHistory;
import google.registry.model.domain.secdns.DelegationSignerData;
import google.registry.model.domain.secdns.DomainDsDataHistory;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.model.reporting.DomainTransactionRecord;
import google.registry.model.reporting.HistoryEntry;
import google.registry.persistence.VKey;
@@ -113,7 +113,7 @@ public class DomainHistory extends HistoryEntry {
})
@ImmutableObject.EmptySetToNull
@Column(name = "host_repo_id")
Set<VKey<HostResource>> nsHosts;
Set<VKey<Host>> nsHosts;
@DoNotCompare
@OneToMany(
@@ -221,8 +221,8 @@ public class DomainHistory extends HistoryEntry {
return new DomainHistoryId(getDomainRepoId(), getId());
}
/** Returns keys to the {@link HostResource} that are the nameservers for the domain. */
public Set<VKey<HostResource>> getNsHosts() {
/** Returns keys to the {@link Host} that are the nameservers for the domain. */
public Set<VKey<Host>> getNsHosts() {
return nsHosts;
}
@@ -406,7 +406,7 @@ public class DomainHistory extends HistoryEntry {
public DomainHistory buildAndAssemble(
ImmutableSet<DomainDsDataHistory> dsDataHistories,
ImmutableSet<VKey<HostResource>> domainHistoryHosts,
ImmutableSet<VKey<Host>> domainHistoryHosts,
ImmutableSet<GracePeriodHistory> gracePeriodHistories,
ImmutableSet<DomainTransactionRecord> transactionRecords) {
DomainHistory instance = super.build();

View File

@@ -24,8 +24,8 @@ import google.registry.model.contact.ContactBase;
import google.registry.model.contact.ContactResource;
import google.registry.model.domain.Domain;
import google.registry.model.domain.DomainBase;
import google.registry.model.host.Host;
import google.registry.model.host.HostBase;
import google.registry.model.host.HostResource;
import google.registry.model.translators.EnumToAttributeAdapter.EppEnum;
import google.registry.model.translators.StatusValueAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@@ -135,7 +135,7 @@ public enum StatusValue implements EppEnum {
DomainBase.class,
Domain.class,
HostBase.class,
HostResource.class),
Host.class),
NONE,
DOMAINS(DomainBase.class, Domain.class);

View File

@@ -27,7 +27,7 @@ import javax.persistence.AccessType;
/**
* A persistable Host resource including mutable and non-mutable fields.
*
* <p>The {@link javax.persistence.Id} of the HostResource is the repoId.
* <p>The {@link javax.persistence.Id} of the Host is the repoId.
*/
@ReportedOn
@Entity
@@ -54,7 +54,7 @@ import javax.persistence.AccessType;
@ExternalMessagingName("host")
@WithStringVKey
@Access(AccessType.FIELD) // otherwise it'll use the default if the repoId (property)
public class HostResource extends HostBase implements ForeignKeyedEppResource {
public class Host extends HostBase implements ForeignKeyedEppResource {
@Override
@javax.persistence.Id
@@ -64,8 +64,8 @@ public class HostResource extends HostBase implements ForeignKeyedEppResource {
}
@Override
public VKey<HostResource> createVKey() {
return VKey.create(HostResource.class, getRepoId(), Key.create(this));
public VKey<Host> createVKey() {
return VKey.create(Host.class, getRepoId(), Key.create(this));
}
@Override
@@ -73,11 +73,11 @@ public class HostResource extends HostBase implements ForeignKeyedEppResource {
return new Builder(clone(this));
}
/** A builder for constructing {@link HostResource}, since it is immutable. */
public static class Builder extends HostBase.Builder<HostResource, Builder> {
/** A builder for constructing {@link Host}, since it is immutable. */
public static class Builder extends HostBase.Builder<Host, Builder> {
public Builder() {}
private Builder(HostResource instance) {
private Builder(Host instance) {
super(instance);
}

View File

@@ -126,8 +126,7 @@ public class HostBase extends EppResource {
@Override
public VKey<? extends HostBase> createVKey() {
throw new UnsupportedOperationException(
"HostBase is not an actual persisted entity you can create a key to;"
+ " use HostResource instead");
"HostBase is not an actual persisted entity you can create a key to; use Host instead");
}
@Deprecated

View File

@@ -29,26 +29,26 @@ import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;
/** A collection of {@link HostResource} commands. */
/** A collection of {@link Host} commands. */
public class HostCommand {
/** The fields on "chgType" from <a href="http://tools.ietf.org/html/rfc5732">RFC5732</a>. */
@XmlTransient
abstract static class HostCreateOrChange extends AbstractSingleResourceCommand
implements ResourceCreateOrChange<HostResource.Builder> {
implements ResourceCreateOrChange<Host.Builder> {
public String getFullyQualifiedHostName() {
return getTargetId();
}
}
/**
* A create command for a {@link HostResource}, mapping "createType" from <a
* A create command for a {@link Host}, mapping "createType" from <a
* href="http://tools.ietf.org/html/rfc5732">RFC5732</a>.
*/
@XmlType(propOrder = {"targetId", "inetAddresses"})
@XmlRootElement
public static class Create extends HostCreateOrChange
implements ResourceCreateOrChange<HostResource.Builder> {
implements ResourceCreateOrChange<Host.Builder> {
/** IP Addresses for this host. Can be null if this is an external host. */
@XmlElement(name = "addr")
Set<InetAddress> inetAddresses;
@@ -58,23 +58,22 @@ public class HostCommand {
}
}
/** A delete command for a {@link HostResource}. */
/** A delete command for a {@link Host}. */
@XmlRootElement
public static class Delete extends AbstractSingleResourceCommand {}
/** An info request for a {@link HostResource}. */
/** An info request for a {@link Host}. */
@XmlRootElement
public static class Info extends AbstractSingleResourceCommand {}
/** A check request for {@link HostResource}. */
/** A check request for {@link Host}. */
@XmlRootElement
public static class Check extends ResourceCheck {}
/** An update to a {@link HostResource}. */
/** An update to a {@link Host}. */
@XmlRootElement
@XmlType(propOrder = {"targetId", "innerAdd", "innerRemove", "innerChange"})
public static class Update extends ResourceUpdate
<Update.AddRemove, HostResource.Builder, Update.Change> {
public static class Update extends ResourceUpdate<Update.AddRemove, Host.Builder, Update.Change> {
@XmlElement(name = "chg")
protected Change innerChange;

View File

@@ -59,7 +59,7 @@ import javax.persistence.PostLoad;
@IdClass(HostHistoryId.class)
public class HostHistory extends HistoryEntry implements UnsafeSerializable {
// Store HostBase instead of HostResource so we don't pick up its @Id
// Store HostBase instead of Host so we don't pick up its @Id
// Nullable for the sake of pre-Registry-3.0 history objects
@DoNotCompare @Nullable HostBase hostBase;
@@ -74,7 +74,7 @@ public class HostHistory extends HistoryEntry implements UnsafeSerializable {
/** This method is private because it is only used by Hibernate. */
@SuppressWarnings("unused")
private void setHostRepoId(String hostRepoId) {
parent = Key.create(HostResource.class, hostRepoId);
parent = Key.create(Host.class, hostRepoId);
}
@Id
@@ -99,9 +99,9 @@ public class HostHistory extends HistoryEntry implements UnsafeSerializable {
return Optional.ofNullable(hostBase);
}
/** The key to the {@link google.registry.model.host.HostResource} this is based off of. */
public VKey<HostResource> getParentVKey() {
return VKey.create(HostResource.class, getHostRepoId());
/** The key to the {@link Host} this is based off of. */
public VKey<Host> getParentVKey() {
return VKey.create(Host.class, getHostRepoId());
}
/** Creates a {@link VKey} instance for this entity. */
@@ -113,7 +113,7 @@ public class HostHistory extends HistoryEntry implements UnsafeSerializable {
@Override
public Optional<? extends EppResource> getResourceAtPointInTime() {
return getHostBase().map(hostBase -> new HostResource.Builder().copyFrom(hostBase).build());
return getHostBase().map(hostBase -> new Host.Builder().copyFrom(hostBase).build());
}
@PostLoad
@@ -210,7 +210,7 @@ public class HostHistory extends HistoryEntry implements UnsafeSerializable {
}
public Builder setHostRepoId(String hostRepoId) {
getInstance().parent = Key.create(HostResource.class, hostRepoId);
getInstance().parent = Key.create(Host.class, hostRepoId);
return this;
}
}

View File

@@ -49,7 +49,7 @@ import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.annotations.ReportedOn;
import google.registry.model.contact.ContactResource;
import google.registry.model.domain.Domain;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.persistence.VKey;
import google.registry.persistence.transaction.CriteriaQueryBuilder;
import google.registry.persistence.transaction.JpaTransactionManager;
@@ -80,10 +80,10 @@ public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroup
@Entity
public static class ForeignKeyDomainIndex extends ForeignKeyIndex<Domain> {}
/** The {@link ForeignKeyIndex} type for {@link HostResource} entities. */
/** The {@link ForeignKeyIndex} type for {@link Host} entities. */
@ReportedOn
@Entity
public static class ForeignKeyHostIndex extends ForeignKeyIndex<HostResource> {}
public static class ForeignKeyHostIndex extends ForeignKeyIndex<Host> {}
private static final ImmutableBiMap<
Class<? extends EppResource>, Class<? extends ForeignKeyIndex<?>>>
@@ -91,14 +91,14 @@ public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroup
ImmutableBiMap.of(
ContactResource.class, ForeignKeyContactIndex.class,
Domain.class, ForeignKeyDomainIndex.class,
HostResource.class, ForeignKeyHostIndex.class);
Host.class, ForeignKeyHostIndex.class);
private static final ImmutableMap<Class<? extends EppResource>, String>
RESOURCE_CLASS_TO_FKI_PROPERTY =
ImmutableMap.of(
ContactResource.class, "contactId",
Domain.class, "fullyQualifiedDomainName",
HostResource.class, "fullyQualifiedHostName");
Host.class, "fullyQualifiedHostName");
@Id String foreignKey;
@@ -106,7 +106,7 @@ public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroup
* The deletion time of this {@link ForeignKeyIndex}.
*
* <p>This will generally be equal to the deletion time of {@link #topReference}. However, in the
* case of a {@link HostResource} that was renamed, this field will hold the time of the rename.
* case of a {@link Host} that was renamed, this field will hold the time of the rename.
*/
@Index DateTime deletionTime;

View File

@@ -33,7 +33,7 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
* via Objectify.
*
* <p>All first class entities are represented as a resource class - {@link
* google.registry.model.domain.Domain}, {@link google.registry.model.host.HostResource}, {@link
* google.registry.model.domain.Domain}, {@link google.registry.model.host.Host}, {@link
* google.registry.model.contact.ContactResource}, and {@link
* google.registry.model.registrar.Registrar}. Resource objects are written in a single shared
* entity group per TLD. All commands that operate on those entities are grouped in a "Command"

View File

@@ -40,9 +40,9 @@ import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.DomainHistory.DomainHistoryId;
import google.registry.model.domain.DomainRenewData;
import google.registry.model.eppoutput.EppResponse.ResponseData;
import google.registry.model.host.Host;
import google.registry.model.host.HostHistory;
import google.registry.model.host.HostHistory.HostHistoryId;
import google.registry.model.host.HostResource;
import google.registry.model.poll.PendingActionNotificationResponse.ContactPendingActionNotificationResponse;
import google.registry.model.poll.PendingActionNotificationResponse.DomainPendingActionNotificationResponse;
import google.registry.model.poll.PendingActionNotificationResponse.HostPendingActionNotificationResponse;
@@ -105,7 +105,7 @@ public abstract class PollMessage extends ImmutableObject
public enum Type {
DOMAIN(1L, Domain.class),
CONTACT(2L, ContactResource.class),
HOST(3L, HostResource.class);
HOST(3L, Host.class);
private final long id;
private final Class<?> clazz;
@@ -216,7 +216,7 @@ public abstract class PollMessage extends ImmutableObject
/**
* Returns the host repo id.
*
* <p>This may only be used on a HostResource poll event.
* <p>This may only be used on a Host poll event.
*/
public String getHostRepoId() {
checkArgument(getType() == Type.DOMAIN);

View File

@@ -964,7 +964,7 @@ public class Registrar extends ImmutableObject
}
/** Verifies that the email address in question is not null and has a valid format. */
static String checkValidEmail(String email) {
public static String checkValidEmail(String email) {
checkNotNull(email, "Provided email was null");
try {
InternetAddress internetAddress = new InternetAddress(email, true);

View File

@@ -44,10 +44,10 @@ import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.DomainHistory.DomainHistoryId;
import google.registry.model.domain.Period;
import google.registry.model.eppcommon.Trid;
import google.registry.model.host.Host;
import google.registry.model.host.HostBase;
import google.registry.model.host.HostHistory;
import google.registry.model.host.HostHistory.HostHistoryId;
import google.registry.model.host.HostResource;
import google.registry.persistence.VKey;
import java.util.Optional;
import java.util.Set;
@@ -389,7 +389,7 @@ public class HistoryEntry extends ImmutableObject implements Buildable, UnsafeSe
if (parentKind.equals(getKind(Domain.class))) {
resultEntity =
new DomainHistory.Builder().copyFrom(this).setDomainRepoId(parent.getName()).build();
} else if (parentKind.equals(getKind(HostResource.class))) {
} else if (parentKind.equals(getKind(Host.class))) {
resultEntity =
new HostHistory.Builder().copyFrom(this).setHostRepoId(parent.getName()).build();
} else if (parentKind.equals(getKind(ContactResource.class))) {
@@ -413,7 +413,7 @@ public class HistoryEntry extends ImmutableObject implements Buildable, UnsafeSe
DomainHistory.class,
new DomainHistoryId(repoId, id),
Key.create(parent, DomainHistory.class, id));
} else if (parentKind.equals(getKind(HostResource.class))) {
} else if (parentKind.equals(getKind(Host.class))) {
return VKey.create(
HostHistory.class,
new HostHistoryId(repoId, id),

View File

@@ -29,8 +29,8 @@ import google.registry.model.contact.ContactHistory;
import google.registry.model.contact.ContactResource;
import google.registry.model.domain.Domain;
import google.registry.model.domain.DomainHistory;
import google.registry.model.host.Host;
import google.registry.model.host.HostHistory;
import google.registry.model.host.HostResource;
import google.registry.persistence.VKey;
import google.registry.persistence.transaction.CriteriaQueryBuilder;
import java.util.Comparator;
@@ -55,7 +55,7 @@ public class HistoryEntryDao {
ContactHistory.class,
Domain.class,
DomainHistory.class,
HostResource.class,
Host.class,
HostHistory.class);
public static ImmutableMap<Class<? extends HistoryEntry>, String> REPO_ID_FIELD_NAMES =

View File

@@ -73,7 +73,7 @@ public class PremiumListDao {
}
/**
* In-memory price cache for for a given premium list revision and domain label.
* In-memory price cache for a given premium list revision and domain label.
*
* <p>Note that premium list revision ids are globally unique, so this cache is specific to a
* given premium list. Premium list entries might not be present, as indicated by the Optional

View File

@@ -90,12 +90,13 @@ public final class ReservedList
*
* <p>We need to persist the list entries, but only on the initial insert (not on update) since
* the entries themselves never get changed, so we only annotate it with {@link PostPersist}, not
* {@link PostUpdate}.
* PostUpdate.
*/
@PostPersist
void postPersist() {
if (reservedListMap != null) {
reservedListMap.values().stream()
reservedListMap
.values()
.forEach(
entry -> {
// We can safely change the revision id since it's "Insignificant".

View File

@@ -20,7 +20,10 @@ import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static google.registry.persistence.transaction.QueryComposer.Comparator.EQ;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
import google.registry.model.CacheUtils;
import google.registry.model.CreateAutoTimestamp;
import google.registry.model.ImmutableObject;
import java.util.Map;
@@ -81,9 +84,26 @@ public class ClaimsList extends ImmutableObject {
* <p>This field requires special treatment since we want to lazy load it. We have to remove it
* from the immutability contract so we can modify it after construction and we have to handle the
* database processing on our own so we can detach it after load.
*
* <p>Unlike the cache below, this is guaranteed to contain all mappings from labels to claim keys
* if it is not null.
*/
@Insignificant @Transient ImmutableMap<String, String> labelsToKeys;
/**
* A not-necessarily-complete cache of labels to claim keys.
*
* <p>At any point in time this might or might not contain none, some, or all of the mappings from
* labels to claim keys. Exists so that repeated calls to {@link #getClaimKey(String)} can be
* quick.
*
* <p>Note: this cache has no expiration because while claims list revisions can be added over
* time, each instance of a claims list is immutable.
*/
@Insignificant @Transient @VisibleForTesting
final LoadingCache<String, Optional<String>> claimKeyCache =
CacheUtils.newCacheBuilder().build(this::getClaimKeyUncached);
@PreRemove
void preRemove() {
jpaTm()
@@ -139,18 +159,7 @@ public class ClaimsList extends ImmutableObject {
* entries and cache them locally.
*/
public Optional<String> getClaimKey(String label) {
if (labelsToKeys != null) {
return Optional.ofNullable(labelsToKeys.get(label));
}
return jpaTm()
.transact(
() ->
jpaTm()
.createQueryComposer(ClaimsEntry.class)
.where("revisionId", EQ, revisionId)
.where("domainLabel", EQ, label)
.first()
.map(ClaimsEntry::getClaimKey));
return claimKeyCache.get(label);
}
/**
@@ -192,6 +201,27 @@ public class ClaimsList extends ImmutableObject {
return labelsToKeys.size();
}
/**
* Returns the claim key for a given domain if there is one, empty otherwise.
*
* <p>This attempts to load from the base {@link #labelsToKeys} if possible, otherwise it will
* query the database for the entry requested.
*/
private Optional<String> getClaimKeyUncached(String label) {
if (labelsToKeys != null) {
return Optional.ofNullable(labelsToKeys.get(label));
}
return jpaTm()
.transact(
() ->
jpaTm()
.createQueryComposer(ClaimsEntry.class)
.where("revisionId", EQ, revisionId)
.where("domainLabel", EQ, label)
.first()
.map(ClaimsEntry::getClaimKey));
}
public static ClaimsList create(
DateTime tmdbGenerationTime, ImmutableMap<String, String> labelsToKeys) {
ClaimsList instance = new ClaimsList();

View File

@@ -14,25 +14,57 @@
package google.registry.model.tmch;
import static google.registry.config.RegistryConfig.getClaimsListCacheDuration;
import static google.registry.persistence.transaction.QueryComposer.Comparator.EQ;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
import google.registry.model.CacheUtils;
import java.time.Duration;
import java.util.Optional;
/** Data access object for {@link ClaimsList}. */
public class ClaimsListDao {
/**
* Cache of the {@link ClaimsList} instance.
*
* <p>The key is meaningless since we only have one active claims list, this is essentially a
* memoizing Supplier that can be reset.
*/
@VisibleForTesting
static LoadingCache<Class<ClaimsListDao>, ClaimsList> CACHE =
createCache(getClaimsListCacheDuration());
@VisibleForTesting
public static void setCacheForTest(Optional<Duration> expiry) {
Duration effectiveExpiry = expiry.orElse(getClaimsListCacheDuration());
CACHE = createCache(effectiveExpiry);
}
private static LoadingCache<Class<ClaimsListDao>, ClaimsList> createCache(Duration expiry) {
return CacheUtils.newCacheBuilder(expiry).build(ignored -> ClaimsListDao.getUncached());
}
/** Saves the given {@link ClaimsList} to Cloud SQL. */
public static void save(ClaimsList claimsList) {
jpaTm().transact(() -> jpaTm().insert(claimsList));
CACHE.put(ClaimsListDao.class, claimsList);
}
/** Returns the most recent revision of the {@link ClaimsList} from the cache. */
public static ClaimsList get() {
return CACHE.get(ClaimsListDao.class);
}
/**
* Returns the most recent revision of the {@link ClaimsList} in SQL or an empty list if it
* doesn't exist.
*/
public static ClaimsList get() {
private static ClaimsList getUncached() {
return jpaTm()
.transact(
() -> {

View File

@@ -37,7 +37,7 @@ import com.google.common.net.InetAddresses;
import com.google.common.primitives.Booleans;
import com.googlecode.objectify.cmd.Query;
import google.registry.model.domain.Domain;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.persistence.VKey;
import google.registry.persistence.transaction.CriteriaQueryBuilder;
import google.registry.rdap.RdapJsonFormatter.OutputDataType;
@@ -301,8 +301,7 @@ public class RdapDomainSearchAction extends RdapSearchActionBase {
*/
private DomainSearchResponse searchByNameserverLdhName(
final RdapSearchPattern partialStringQuery) {
ImmutableCollection<VKey<HostResource>> hostKeys =
getNameserverRefsByLdhName(partialStringQuery);
ImmutableCollection<VKey<Host>> hostKeys = getNameserverRefsByLdhName(partialStringQuery);
if (Iterables.isEmpty(hostKeys)) {
metricInformationBuilder.setNumHostsRetrieved(0);
throw new NotFoundException("No matching nameservers found");
@@ -311,7 +310,7 @@ public class RdapDomainSearchAction extends RdapSearchActionBase {
}
/**
* Assembles a list of {@link HostResource} keys by name.
* Assembles a list of {@link Host} keys by name.
*
* <p>Nameserver query strings with wildcards are allowed to have a suffix after the wildcard,
* which must be a domain. If the domain is not specified, or is not an existing domain in one of
@@ -320,7 +319,7 @@ public class RdapDomainSearchAction extends RdapSearchActionBase {
* initial string is not required (e.g. "*.example.tld" is valid), because we can look up the
* domain and just list all of its subordinate hosts.
*/
private ImmutableCollection<VKey<HostResource>> getNameserverRefsByLdhName(
private ImmutableCollection<VKey<Host>> getNameserverRefsByLdhName(
final RdapSearchPattern partialStringQuery) {
// Handle queries without a wildcard.
if (!partialStringQuery.getHasWildcard()) {
@@ -341,9 +340,9 @@ public class RdapDomainSearchAction extends RdapSearchActionBase {
// limit in order to avoid arbitrarily long-running queries.
Optional<String> desiredRegistrar = getDesiredRegistrar();
if (tm().isOfy()) {
Query<HostResource> query =
Query<Host> query =
queryItems(
HostResource.class,
Host.class,
"fullyQualifiedHostName",
partialStringQuery,
Optional.empty(),
@@ -359,9 +358,9 @@ public class RdapDomainSearchAction extends RdapSearchActionBase {
return replicaJpaTm()
.transact(
() -> {
CriteriaQueryBuilder<HostResource> builder =
CriteriaQueryBuilder<Host> builder =
queryItemsSql(
HostResource.class,
Host.class,
"fullyQualifiedHostName",
partialStringQuery,
Optional.empty(),
@@ -376,22 +375,22 @@ public class RdapDomainSearchAction extends RdapSearchActionBase {
return getMatchingResourcesSql(builder, true, maxNameserversInFirstStage)
.resources()
.stream()
.map(HostResource::createVKey)
.map(Host::createVKey)
.collect(toImmutableSet());
});
}
}
/** Assembles a list of {@link HostResource} keys by name when the pattern has no wildcard. */
private ImmutableList<VKey<HostResource>> getNameserverRefsByLdhNameWithoutWildcard(
/** Assembles a list of {@link Host} keys by name when the pattern has no wildcard. */
private ImmutableList<VKey<Host>> getNameserverRefsByLdhNameWithoutWildcard(
final RdapSearchPattern partialStringQuery) {
// If we need to check the sponsoring registrar, we need to load the resource rather than just
// the key.
Optional<String> desiredRegistrar = getDesiredRegistrar();
if (desiredRegistrar.isPresent()) {
Optional<HostResource> host =
Optional<Host> host =
loadByForeignKey(
HostResource.class,
Host.class,
partialStringQuery.getInitialString(),
shouldIncludeDeleted() ? START_OF_TIME : getRequestTime());
return (!host.isPresent()
@@ -399,17 +398,17 @@ public class RdapDomainSearchAction extends RdapSearchActionBase {
? ImmutableList.of()
: ImmutableList.of(host.get().createVKey());
} else {
VKey<HostResource> hostKey =
VKey<Host> hostKey =
loadAndGetKey(
HostResource.class,
Host.class,
partialStringQuery.getInitialString(),
shouldIncludeDeleted() ? START_OF_TIME : getRequestTime());
return (hostKey == null) ? ImmutableList.of() : ImmutableList.of(hostKey);
}
}
/** Assembles a list of {@link HostResource} keys by name using a superordinate domain suffix. */
private ImmutableList<VKey<HostResource>> getNameserverRefsByLdhNameWithSuffix(
/** Assembles a list of {@link Host} keys by name using a superordinate domain suffix. */
private ImmutableList<VKey<Host>> getNameserverRefsByLdhNameWithSuffix(
final RdapSearchPattern partialStringQuery) {
// The suffix must be a domain that we manage. That way, we can look up the domain and search
// through the subordinate hosts. This is more efficient, and lets us permit wildcard searches
@@ -425,17 +424,15 @@ public class RdapDomainSearchAction extends RdapSearchActionBase {
"A suffix in a lookup by nameserver name "
+ "must be a domain defined in the system"));
Optional<String> desiredRegistrar = getDesiredRegistrar();
ImmutableList.Builder<VKey<HostResource>> builder = new ImmutableList.Builder<>();
ImmutableList.Builder<VKey<Host>> builder = new ImmutableList.Builder<>();
for (String fqhn : ImmutableSortedSet.copyOf(domain.getSubordinateHosts())) {
// We can't just check that the host name starts with the initial query string, because
// then the query ns.exam*.example.com would match against nameserver ns.example.com.
if (partialStringQuery.matches(fqhn)) {
if (desiredRegistrar.isPresent()) {
Optional<HostResource> host =
Optional<Host> host =
loadByForeignKey(
HostResource.class,
fqhn,
shouldIncludeDeleted() ? START_OF_TIME : getRequestTime());
Host.class, fqhn, shouldIncludeDeleted() ? START_OF_TIME : getRequestTime());
if (host.isPresent()
&& desiredRegistrar
.get()
@@ -443,11 +440,9 @@ public class RdapDomainSearchAction extends RdapSearchActionBase {
builder.add(host.get().createVKey());
}
} else {
VKey<HostResource> hostKey =
VKey<Host> hostKey =
loadAndGetKey(
HostResource.class,
fqhn,
shouldIncludeDeleted() ? START_OF_TIME : getRequestTime());
Host.class, fqhn, shouldIncludeDeleted() ? START_OF_TIME : getRequestTime());
if (hostKey != null) {
builder.add(hostKey);
} else {
@@ -477,11 +472,11 @@ public class RdapDomainSearchAction extends RdapSearchActionBase {
*/
private DomainSearchResponse searchByNameserverIp(final InetAddress inetAddress) {
Optional<String> desiredRegistrar = getDesiredRegistrar();
ImmutableSet<VKey<HostResource>> hostKeys;
ImmutableSet<VKey<Host>> hostKeys;
if (tm().isOfy()) {
Query<HostResource> query =
Query<Host> query =
queryItems(
HostResource.class,
Host.class,
"inetAddresses",
inetAddress.getHostAddress(),
Optional.empty(),
@@ -524,7 +519,7 @@ public class RdapDomainSearchAction extends RdapSearchActionBase {
@SuppressWarnings("unchecked")
Stream<String> resultStream = query.getResultStream();
return resultStream
.map(repoId -> VKey.create(HostResource.class, repoId))
.map(repoId -> VKey.create(Host.class, repoId))
.collect(toImmutableSet());
});
}
@@ -538,7 +533,7 @@ public class RdapDomainSearchAction extends RdapSearchActionBase {
* #searchByNameserverIp} after they assemble the relevant host keys.
*/
private DomainSearchResponse searchByNameserverRefs(
final ImmutableCollection<VKey<HostResource>> hostKeys) {
final ImmutableCollection<VKey<Host>> hostKeys) {
// We must break the query up into chunks, because the in operator is limited to 30 subqueries.
// Since it is possible for the same domain to show up more than once in our result list (if
// we do a wildcard nameserver search that returns multiple nameservers used by the same
@@ -548,7 +543,7 @@ public class RdapDomainSearchAction extends RdapSearchActionBase {
ImmutableSortedSet.Builder<Domain> domainSetBuilder =
ImmutableSortedSet.orderedBy(Comparator.comparing(Domain::getDomainName));
int numHostKeysSearched = 0;
for (List<VKey<HostResource>> chunk : Iterables.partition(hostKeys, 30)) {
for (List<VKey<Host>> chunk : Iterables.partition(hostKeys, 30)) {
numHostKeysSearched += chunk.size();
if (tm().isOfy()) {
Query<Domain> query =
@@ -574,7 +569,7 @@ public class RdapDomainSearchAction extends RdapSearchActionBase {
replicaJpaTm()
.transact(
() -> {
for (VKey<HostResource> hostKey : hostKeys) {
for (VKey<Host> hostKey : hostKeys) {
CriteriaQueryBuilder<Domain> queryBuilder =
CriteriaQueryBuilder.create(replicaJpaTm(), Domain.class)
.whereFieldContains("nsHosts", hostKey)

View File

@@ -48,7 +48,7 @@ import google.registry.model.domain.DesignatedContact.Type;
import google.registry.model.domain.Domain;
import google.registry.model.eppcommon.Address;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.model.registrar.Registrar;
import google.registry.model.registrar.RegistrarAddress;
import google.registry.model.registrar.RegistrarPoc;
@@ -235,8 +235,8 @@ public class RdapJsonFormatter {
ImmutableMap.of("type", ImmutableList.of("fax"));
/** Sets the ordering for hosts; just use the fully qualified host name. */
private static final Ordering<HostResource> HOST_RESOURCE_ORDERING =
Ordering.natural().onResultOf(HostResource::getHostName);
private static final Ordering<Host> HOST_RESOURCE_ORDERING =
Ordering.natural().onResultOf(Host::getHostName);
/** Sets the ordering for designated contacts; order them in a fixed order by contact type. */
private static final Ordering<DesignatedContact> DESIGNATED_CONTACT_ORDERING =
@@ -356,7 +356,7 @@ public class RdapJsonFormatter {
// Kick off the database loads of the nameservers that we will need, so it can load
// asynchronously while we load and process the contacts.
ImmutableSet<HostResource> loadedHosts =
ImmutableSet<Host> loadedHosts =
tm().transact(() -> ImmutableSet.copyOf(tm().loadByKeys(domain.getNameservers()).values()));
// Load the registrant and other contacts and add them to the data.
ImmutableMap<VKey<? extends ContactResource>, ContactResource> loadedContacts =
@@ -393,8 +393,8 @@ public class RdapJsonFormatter {
}
// Add the nameservers to the data; the load was kicked off above for efficiency.
// RDAP Response Profile 2.9: we MUST have the nameservers
for (HostResource hostResource : HOST_RESOURCE_ORDERING.immutableSortedCopy(loadedHosts)) {
builder.nameserversBuilder().add(createRdapNameserver(hostResource, OutputDataType.INTERNAL));
for (Host host : HOST_RESOURCE_ORDERING.immutableSortedCopy(loadedHosts)) {
builder.nameserversBuilder().add(createRdapNameserver(host, OutputDataType.INTERNAL));
}
// RDAP Response Profile 2.10 - MUST contain a secureDns member including at least a
@@ -410,23 +410,23 @@ public class RdapJsonFormatter {
}
/**
* Creates a JSON object for a {@link HostResource}.
* Creates a JSON object for a {@link Host}.
*
* @param hostResource the host resource object from which the JSON object should be created
* @param host the host resource object from which the JSON object should be created
* @param outputDataType whether to generate full or summary data
*/
RdapNameserver createRdapNameserver(HostResource hostResource, OutputDataType outputDataType) {
RdapNameserver createRdapNameserver(Host host, OutputDataType outputDataType) {
RdapNameserver.Builder builder = RdapNameserver.builder();
builder.linksBuilder().add(makeSelfLink("nameserver", hostResource.getHostName()));
builder.linksBuilder().add(makeSelfLink("nameserver", host.getHostName()));
if (outputDataType != OutputDataType.FULL) {
builder.remarksBuilder().add(RdapIcannStandardInformation.SUMMARY_DATA_REMARK);
}
// We need the ldhName: RDAP Response Profile 2.9.1, 4.1
builder.setLdhName(hostResource.getHostName());
builder.setLdhName(host.getHostName());
// Handle is optional, but if given it MUST be the ROID.
// We will set it always as it's important as a "self link"
builder.setHandle(hostResource.getRepoId());
builder.setHandle(host.getRepoId());
// Status is optional for internal Nameservers - RDAP Response Profile 2.9.2
// It isn't mentioned at all anywhere else. So we can just not put it at all?
@@ -434,14 +434,14 @@ public class RdapJsonFormatter {
// To be safe, we'll put it on the "FULL" version anyway
if (outputDataType == OutputDataType.FULL) {
ImmutableSet.Builder<StatusValue> statuses = new ImmutableSet.Builder<>();
statuses.addAll(hostResource.getStatusValues());
if (isLinked(hostResource.createVKey(), getRequestTime())) {
statuses.addAll(host.getStatusValues());
if (isLinked(host.createVKey(), getRequestTime())) {
statuses.add(StatusValue.LINKED);
}
if (hostResource.isSubordinate()
if (host.isSubordinate()
&& tm().transact(
() ->
tm().loadByKey(hostResource.getSuperordinateDomain())
tm().loadByKey(host.getSuperordinateDomain())
.cloneProjectedAtTime(getRequestTime())
.getStatusValues()
.contains(StatusValue.PENDING_TRANSFER))) {
@@ -453,14 +453,14 @@ public class RdapJsonFormatter {
makeStatusValueList(
statuses.build(),
false, // isRedacted
hostResource.getDeletionTime().isBefore(getRequestTime())));
host.getDeletionTime().isBefore(getRequestTime())));
}
// For query responses - we MUST have all the ip addresses: RDAP Response Profile 4.2.
//
// However, it is optional for internal responses: RDAP Response Profile 2.9.2
if (outputDataType != OutputDataType.INTERNAL) {
for (InetAddress inetAddress : hostResource.getInetAddresses()) {
for (InetAddress inetAddress : host.getInetAddresses()) {
if (inetAddress instanceof Inet4Address) {
builder.ipv4Builder().add(InetAddresses.toAddrString(inetAddress));
} else if (inetAddress instanceof Inet6Address) {
@@ -472,8 +472,7 @@ public class RdapJsonFormatter {
// RDAP Response Profile 4.3 - Registrar member is optional, so we only set it for FULL
if (outputDataType == OutputDataType.FULL) {
Registrar registrar =
Registrar.loadRequiredRegistrarCached(
hostResource.getPersistedCurrentSponsorRegistrarId());
Registrar.loadRequiredRegistrarCached(host.getPersistedCurrentSponsorRegistrarId());
builder.entitiesBuilder().add(createRdapRegistrarEntity(registrar, OutputDataType.INTERNAL));
}
if (outputDataType != OutputDataType.INTERNAL) {

View File

@@ -21,7 +21,7 @@ import static google.registry.request.Action.Method.HEAD;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import google.registry.flows.EppException;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.rdap.RdapJsonFormatter.OutputDataType;
import google.registry.rdap.RdapMetrics.EndpointType;
import google.registry.rdap.RdapObjectClasses.RdapNameserver;
@@ -61,12 +61,12 @@ public class RdapNameserverAction extends RdapActionBase {
}
// If there are no undeleted nameservers with the given name, the foreign key should point to
// the most recently deleted one.
Optional<HostResource> hostResource =
Optional<Host> host =
loadByForeignKey(
HostResource.class,
Host.class,
pathSearchString,
shouldIncludeDeleted() ? START_OF_TIME : getRequestTime());
if (!hostResource.isPresent() || !isAuthorized(hostResource.get())) {
if (!host.isPresent() || !isAuthorized(host.get())) {
// RFC7480 5.3 - if the server wishes to respond that it doesn't have data satisfying the
// query, it MUST reply with 404 response code.
//
@@ -74,6 +74,6 @@ public class RdapNameserverAction extends RdapActionBase {
// exists but we don't want to show it to you", because we DON'T wish to say that.
throw new NotFoundException(pathSearchString + " not found");
}
return rdapJsonFormatter.createRdapNameserver(hostResource.get(), OutputDataType.FULL);
return rdapJsonFormatter.createRdapNameserver(host.get(), OutputDataType.FULL);
}
}

View File

@@ -28,7 +28,7 @@ import com.google.common.net.InetAddresses;
import com.google.common.primitives.Booleans;
import com.googlecode.objectify.cmd.Query;
import google.registry.model.domain.Domain;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.persistence.transaction.CriteriaQueryBuilder;
import google.registry.rdap.RdapJsonFormatter.OutputDataType;
import google.registry.rdap.RdapMetrics.EndpointType;
@@ -159,16 +159,15 @@ public class RdapNameserverSearchAction extends RdapSearchActionBase {
NameserverSearchResponse.builder()
.setIncompletenessWarningType(IncompletenessWarningType.COMPLETE);
Optional<HostResource> hostResource =
loadByForeignKey(
HostResource.class, partialStringQuery.getInitialString(), getRequestTime());
Optional<Host> host =
loadByForeignKey(Host.class, partialStringQuery.getInitialString(), getRequestTime());
metricInformationBuilder.setNumHostsRetrieved(hostResource.isPresent() ? 1 : 0);
metricInformationBuilder.setNumHostsRetrieved(host.isPresent() ? 1 : 0);
if (shouldBeVisible(hostResource)) {
if (shouldBeVisible(host)) {
builder
.nameserverSearchResultsBuilder()
.add(rdapJsonFormatter.createRdapNameserver(hostResource.get(), OutputDataType.FULL));
.add(rdapJsonFormatter.createRdapNameserver(host.get(), OutputDataType.FULL));
}
return builder.build();
}
@@ -187,7 +186,7 @@ public class RdapNameserverSearchAction extends RdapSearchActionBase {
throw new UnprocessableEntityException(
"A suffix after a wildcard in a nameserver lookup must be an in-bailiwick domain");
}
List<HostResource> hostList = new ArrayList<>();
List<Host> hostList = new ArrayList<>();
for (String fqhn : ImmutableSortedSet.copyOf(domain.get().getSubordinateHosts())) {
if (cursorString.isPresent() && (fqhn.compareTo(cursorString.get()) <= 0)) {
continue;
@@ -195,10 +194,9 @@ public class RdapNameserverSearchAction extends RdapSearchActionBase {
// We can't just check that the host name starts with the initial query string, because
// then the query ns.exam*.example.com would match against nameserver ns.example.com.
if (partialStringQuery.matches(fqhn)) {
Optional<HostResource> hostResource =
loadByForeignKey(HostResource.class, fqhn, getRequestTime());
if (shouldBeVisible(hostResource)) {
hostList.add(hostResource.get());
Optional<Host> host = loadByForeignKey(Host.class, fqhn, getRequestTime());
if (shouldBeVisible(host)) {
hostList.add(host.get());
if (hostList.size() > rdapResultSetMaxSize) {
break;
}
@@ -222,9 +220,9 @@ public class RdapNameserverSearchAction extends RdapSearchActionBase {
// Add 1 so we can detect truncation.
int querySizeLimit = getStandardQuerySizeLimit();
if (tm().isOfy()) {
Query<HostResource> query =
Query<Host> query =
queryItems(
HostResource.class,
Host.class,
"fullyQualifiedHostName",
partialStringQuery,
cursorString,
@@ -236,9 +234,9 @@ public class RdapNameserverSearchAction extends RdapSearchActionBase {
return replicaJpaTm()
.transact(
() -> {
CriteriaQueryBuilder<HostResource> queryBuilder =
CriteriaQueryBuilder<Host> queryBuilder =
queryItemsSql(
HostResource.class,
Host.class,
"fullyQualifiedHostName",
partialStringQuery,
cursorString,
@@ -254,11 +252,11 @@ public class RdapNameserverSearchAction extends RdapSearchActionBase {
private NameserverSearchResponse searchByIp(InetAddress inetAddress) {
// Add 1 so we can detect truncation.
int querySizeLimit = getStandardQuerySizeLimit();
RdapResultSet<HostResource> rdapResultSet;
RdapResultSet<Host> rdapResultSet;
if (tm().isOfy()) {
Query<HostResource> query =
Query<Host> query =
queryItems(
HostResource.class,
Host.class,
"inetAddresses",
inetAddress.getHostAddress(),
Optional.empty(),
@@ -296,11 +294,11 @@ public class RdapNameserverSearchAction extends RdapSearchActionBase {
javax.persistence.Query query =
replicaJpaTm()
.getEntityManager()
.createNativeQuery(queryBuilder.toString(), HostResource.class)
.createNativeQuery(queryBuilder.toString(), Host.class)
.setMaxResults(querySizeLimit);
parameters.build().forEach(query::setParameter);
@SuppressWarnings("unchecked")
List<HostResource> resultList = query.getResultList();
List<Host> resultList = query.getResultList();
return filterResourcesByVisibility(resultList, querySizeLimit);
});
}
@@ -309,7 +307,7 @@ public class RdapNameserverSearchAction extends RdapSearchActionBase {
/** Output JSON for a lists of hosts contained in an {@link RdapResultSet}. */
private NameserverSearchResponse makeSearchResults(
RdapResultSet<HostResource> resultSet, CursorType cursorType) {
RdapResultSet<Host> resultSet, CursorType cursorType) {
return makeSearchResults(
resultSet.resources(),
resultSet.incompletenessWarningType(),
@@ -319,7 +317,7 @@ public class RdapNameserverSearchAction extends RdapSearchActionBase {
/** Output JSON for a list of hosts. */
private NameserverSearchResponse makeSearchResults(
List<HostResource> hosts,
List<Host> hosts,
IncompletenessWarningType incompletenessWarningType,
int numHostsRetrieved,
CursorType cursorType) {
@@ -329,7 +327,7 @@ public class RdapNameserverSearchAction extends RdapSearchActionBase {
NameserverSearchResponse.Builder builder =
NameserverSearchResponse.builder().setIncompletenessWarningType(incompletenessWarningType);
Optional<String> newCursor = Optional.empty();
for (HostResource host : Iterables.limit(hosts, rdapResultSetMaxSize)) {
for (Host host : Iterables.limit(hosts, rdapResultSetMaxSize)) {
newCursor =
Optional.of((cursorType == CursorType.NAME) ? host.getHostName() : host.getRepoId());
builder

View File

@@ -19,7 +19,7 @@ import static com.google.common.base.Preconditions.checkArgument;
import com.google.common.net.InetAddresses;
import google.registry.model.domain.Domain;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.xjc.host.XjcHostAddrType;
import google.registry.xjc.host.XjcHostIpType;
import google.registry.xjc.host.XjcHostStatusType;
@@ -30,23 +30,23 @@ import java.net.Inet6Address;
import java.net.InetAddress;
import org.joda.time.DateTime;
/** Utility class that turns {@link HostResource} as {@link XjcRdeHostElement}. */
final class HostResourceToXjcConverter {
/** Utility class that turns a {@link Host} resource into {@link XjcRdeHostElement}. */
final class HostToXjcConverter {
/** Converts a subordinate {@link HostResource} to {@link XjcRdeHostElement}. */
static XjcRdeHostElement convertSubordinate(HostResource host, Domain superordinateDomain) {
/** Converts a subordinate {@link Host} to {@link XjcRdeHostElement}. */
static XjcRdeHostElement convertSubordinate(Host host, Domain superordinateDomain) {
checkArgument(superordinateDomain.createVKey().equals(host.getSuperordinateDomain()));
return new XjcRdeHostElement(convertSubordinateHost(host, superordinateDomain));
}
/** Converts an external {@link HostResource} to {@link XjcRdeHostElement}. */
static XjcRdeHostElement convertExternal(HostResource host) {
/** Converts an external {@link Host} to {@link XjcRdeHostElement}. */
static XjcRdeHostElement convertExternal(Host host) {
checkArgument(!host.isSubordinate());
return new XjcRdeHostElement(convertExternalHost(host));
}
/** Converts {@link HostResource} to {@link XjcRdeHost}. */
static XjcRdeHost convertSubordinateHost(HostResource model, Domain superordinateDomain) {
/** Converts {@link Host} to {@link XjcRdeHost}. */
static XjcRdeHost convertSubordinateHost(Host model, Domain superordinateDomain) {
XjcRdeHost bean =
convertHostCommon(
model,
@@ -58,14 +58,14 @@ final class HostResourceToXjcConverter {
return bean;
}
/** Converts {@link HostResource} to {@link XjcRdeHost}. */
static XjcRdeHost convertExternalHost(HostResource model) {
/** Converts {@link Host} to {@link XjcRdeHost}. */
static XjcRdeHost convertExternalHost(Host model) {
return convertHostCommon(
model, model.getPersistedCurrentSponsorRegistrarId(), model.getLastTransferTime());
}
private static XjcRdeHost convertHostCommon(
HostResource model, String registrarId, DateTime lastTransferTime) {
Host model, String registrarId, DateTime lastTransferTime) {
XjcRdeHost bean = new XjcRdeHost();
bean.setName(model.getHostName());
bean.setRoid(model.getRepoId());
@@ -105,5 +105,5 @@ final class HostResourceToXjcConverter {
return bean;
}
private HostResourceToXjcConverter() {}
private HostToXjcConverter() {}
}

View File

@@ -22,7 +22,7 @@ import com.google.common.collect.ImmutableMap;
import google.registry.model.EppResource;
import google.registry.model.contact.ContactResource;
import google.registry.model.domain.Domain;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.model.rde.RdeMode;
import java.util.HashMap;
import java.util.Map;
@@ -71,8 +71,8 @@ public class RdeFragmenter {
cache.put(WatermarkModePair.create(watermark, RdeMode.FULL), result);
cache.put(WatermarkModePair.create(watermark, RdeMode.THIN), result);
return result;
} else if (resource instanceof HostResource) {
HostResource host = (HostResource) resource;
} else if (resource instanceof Host) {
Host host = (Host) resource;
result =
Optional.of(
host.isSubordinate()

View File

@@ -22,7 +22,7 @@ import com.googlecode.objectify.Key;
import google.registry.model.ImmutableObject;
import google.registry.model.contact.ContactResource;
import google.registry.model.domain.Domain;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.model.rde.RdeMode;
import google.registry.model.registrar.Registrar;
import google.registry.tldconfig.idn.IdnTable;
@@ -129,16 +129,17 @@ public final class RdeMarshaller implements Serializable {
RdeResourceType.DOMAIN, domain, DomainToXjcConverter.convert(domain, mode));
}
/** Turns {@link HostResource} object into an XML fragment. */
public DepositFragment marshalSubordinateHost(HostResource host, Domain superordinateDomain) {
return marshalResource(RdeResourceType.HOST, host,
HostResourceToXjcConverter.convertSubordinate(host, superordinateDomain));
/** Turns {@link Host} object into an XML fragment. */
public DepositFragment marshalSubordinateHost(Host host, Domain superordinateDomain) {
return marshalResource(
RdeResourceType.HOST,
host,
HostToXjcConverter.convertSubordinate(host, superordinateDomain));
}
/** Turns {@link HostResource} object into an XML fragment. */
public DepositFragment marshalExternalHost(HostResource host) {
return marshalResource(RdeResourceType.HOST, host,
HostResourceToXjcConverter.convertExternal(host));
/** Turns {@link Host} object into an XML fragment. */
public DepositFragment marshalExternalHost(Host host) {
return marshalResource(RdeResourceType.HOST, host, HostToXjcConverter.convertExternal(host));
}
/** Turns {@link Registrar} object into an XML fragment. */

View File

@@ -47,7 +47,7 @@ import google.registry.model.common.Cursor;
import google.registry.model.common.Cursor.CursorType;
import google.registry.model.contact.ContactResource;
import google.registry.model.domain.Domain;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.model.index.EppResourceIndex;
import google.registry.model.rde.RdeMode;
import google.registry.model.registrar.Registrar;
@@ -82,8 +82,8 @@ import org.joda.time.Duration;
* type and loads the embedded resource from it, which is then projected to watermark time to
* account for things like pending transfer.
*
* <p>Only {@link ContactResource}s and {@link HostResource}s that are referenced by an included
* {@link Domain} will be included in the corresponding pending deposit.
* <p>Only {@link ContactResource}s and {@link Host}s that are referenced by an included {@link
* Domain} will be included in the corresponding pending deposit.
*
* <p>{@link Registrar} entities, both active and inactive, are included in all deposits. They are
* not rewinded point-in-time.

View File

@@ -21,7 +21,7 @@ import com.google.common.base.Strings;
import google.registry.model.EppResource;
import google.registry.model.contact.ContactResource;
import google.registry.model.domain.Domain;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.model.index.ForeignKeyIndex;
import google.registry.persistence.VKey;
import org.joda.time.DateTime;
@@ -32,7 +32,7 @@ class CommandUtilities {
/** A useful parameter enum for commands that operate on {@link EppResource} objects. */
public enum ResourceType {
CONTACT(ContactResource.class),
HOST(HostResource.class),
HOST(Host.class),
DOMAIN(Domain.class);
private final Class<? extends EppResource> clazz;

View File

@@ -26,7 +26,7 @@ import com.beust.jcommander.Parameters;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import google.registry.model.domain.Domain;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.persistence.transaction.QueryComposer.Comparator;
import google.registry.tools.params.PathParameter;
import google.registry.util.Clock;
@@ -87,8 +87,8 @@ final class GenerateDnsReportCommand implements CommandWithRemoteApi {
write(domain);
}
Iterable<HostResource> nameservers = tm().transact(() -> tm().loadAllOf(HostResource.class));
for (HostResource nameserver : nameservers) {
Iterable<Host> nameservers = tm().transact(() -> tm().loadAllOf(Host.class));
for (Host nameserver : nameservers) {
// Skip deleted hosts and external hosts.
if (isBeforeOrAt(nameserver.getDeletionTime(), now)
|| nameserver.getInetAddresses().isEmpty()) {
@@ -126,7 +126,7 @@ final class GenerateDnsReportCommand implements CommandWithRemoteApi {
writeJson(mapBuilder.build());
}
private void write(HostResource nameserver) {
private void write(Host nameserver) {
ImmutableList<String> ipAddresses =
nameserver
.getInetAddresses()

View File

@@ -30,8 +30,8 @@ import java.nio.file.Paths;
/**
* A command to download the current claims list.
*
* <p>This is not the original file we fetched from TMCH. It is just a representation of what we
* are currently storing in Datastore.
* <p>This is not the original file we fetched from TMCH. It is just a representation of what we are
* currently storing in SQL.
*/
@Parameters(separators = " =", commandDescription = "Download the current claims list")
final class GetClaimsListCommand implements CommandWithRemoteApi {

View File

@@ -18,7 +18,7 @@ import static google.registry.model.EppResourceUtils.loadByForeignKey;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.util.DomainNameUtils;
import java.util.List;
@@ -35,7 +35,6 @@ final class GetHostCommand extends GetEppResourceCommand {
public void runAndPrint() {
mainParameters.stream()
.map(DomainNameUtils::canonicalizeHostname)
.forEach(
h -> printResource("Host", h, loadByForeignKey(HostResource.class, h, readTimestamp)));
.forEach(h -> printResource("Host", h, loadByForeignKey(Host.class, h, readTimestamp)));
}
}

View File

@@ -17,7 +17,7 @@ package google.registry.tools;
import com.beust.jcommander.Parameters;
import google.registry.tools.server.ListHostsAction;
/** Command to list all HostResource entities in the system. */
/** Command to list all Host entities in the system. */
@Parameters(separators = " =", commandDescription = "List all hosts.")
final class ListHostsCommand extends ListObjectsCommand {

View File

@@ -35,7 +35,7 @@ import com.google.template.soy.data.SoyMapData;
import google.registry.model.domain.Domain;
import google.registry.model.domain.secdns.DelegationSignerData;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.tools.soy.DomainRenewSoyInfo;
import google.registry.tools.soy.UniformRapidSuspensionSoyInfo;
import google.registry.util.DomainNameUtils;
@@ -130,7 +130,7 @@ final class UniformRapidSuspensionCommand extends MutatingEppToolCommand {
checkArgumentPresent(domainOpt, "Domain '%s' does not exist or is deleted", domainName);
Domain domain = domainOpt.get();
Set<String> missingHosts =
difference(newHostsSet, checkResourcesExist(HostResource.class, newCanonicalHosts, now));
difference(newHostsSet, checkResourcesExist(Host.class, newCanonicalHosts, now));
checkArgument(missingHosts.isEmpty(), "Hosts do not exist: %s", missingHosts);
checkArgument(
locksToPreserve.isEmpty() || undo,
@@ -204,8 +204,7 @@ final class UniformRapidSuspensionCommand extends MutatingEppToolCommand {
private ImmutableSortedSet<String> getExistingNameservers(Domain domain) {
ImmutableSortedSet.Builder<String> nameservers = ImmutableSortedSet.naturalOrder();
for (HostResource host :
tm().transact(() -> tm().loadByKeys(domain.getNameservers()).values())) {
for (Host host : tm().transact(() -> tm().loadByKeys(domain.getNameservers()).values())) {
nameservers.add(host.getForeignKey());
}
return nameservers.build();

View File

@@ -32,6 +32,7 @@ import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.Recurring;
import google.registry.model.domain.Domain;
import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.Period;
@@ -215,7 +216,8 @@ class UnrenewDomainCommand extends ConfirmingCommand implements CommandWithRemot
.setHistoryEntry(domainHistory)
.build();
// End the old autorenew billing event and poll message now.
updateAutorenewRecurrenceEndTime(domain, now);
Recurring existingRecurring = tm().loadByKey(domain.getAutorenewBillingEvent());
updateAutorenewRecurrenceEndTime(domain, existingRecurring, now);
Domain newDomain =
domain
.asBuilder()

View File

@@ -17,13 +17,13 @@ package google.registry.tools.params;
import google.registry.model.EppResource;
import google.registry.model.contact.ContactResource;
import google.registry.model.domain.Domain;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
/** Enum to make it easy for a command to accept a flag that specifies an EppResource subclass. */
public enum EppResourceTypeParameter {
CONTACT(ContactResource.class),
DOMAIN(Domain.class),
HOST(HostResource.class);
HOST(Host.class);
private final Class<? extends EppResource> type;

View File

@@ -31,7 +31,7 @@ import google.registry.config.RegistryConfig.Config;
import google.registry.gcs.GcsUtils;
import google.registry.model.domain.Domain;
import google.registry.model.domain.secdns.DelegationSignerData;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.request.Action;
import google.registry.request.HttpException.BadRequestException;
import google.registry.request.JsonActionRunner;
@@ -196,8 +196,8 @@ public class GenerateZoneFilesAction implements Runnable, JsonActionRunner.JsonA
Domain domain, DateTime exportTime, ImmutableList.Builder<String> result) {
ImmutableSet<String> subordinateHosts = domain.getSubordinateHosts();
if (!subordinateHosts.isEmpty()) {
for (HostResource unprojectedHost : tm().loadByKeys(domain.getNameservers()).values()) {
HostResource host = loadAtPointInTime(unprojectedHost, exportTime);
for (Host unprojectedHost : tm().loadByKeys(domain.getNameservers()).values()) {
Host host = loadAtPointInTime(unprojectedHost, exportTime);
// A null means the host was deleted (or not created) at this time.
if (host != null && subordinateHosts.contains(host.getHostName())) {
String stanza = hostStanza(host, domain.getTld());
@@ -232,7 +232,7 @@ public class GenerateZoneFilesAction implements Runnable, JsonActionRunner.JsonA
private String domainStanza(Domain domain, DateTime exportTime) {
StringBuilder result = new StringBuilder();
String domainLabel = stripTld(domain.getDomainName(), domain.getTld());
for (HostResource nameserver : tm().loadByKeys(domain.getNameservers()).values()) {
for (Host nameserver : tm().loadByKeys(domain.getNameservers()).values()) {
result.append(
String.format(
NS_FORMAT,
@@ -267,7 +267,7 @@ public class GenerateZoneFilesAction implements Runnable, JsonActionRunner.JsonA
* }
* </pre>
*/
private String hostStanza(HostResource host, String tld) {
private String hostStanza(Host host, String tld) {
StringBuilder result = new StringBuilder();
for (InetAddress addr : host.getInetAddresses()) {
// must be either IPv4 or IPv6

View File

@@ -22,7 +22,7 @@ import static java.util.Comparator.comparing;
import com.google.common.collect.ImmutableSet;
import google.registry.model.EppResourceUtils;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.request.Action;
import google.registry.request.auth.Auth;
import google.registry.util.Clock;
@@ -35,7 +35,7 @@ import org.joda.time.DateTime;
path = ListHostsAction.PATH,
method = {GET, POST},
auth = Auth.AUTH_INTERNAL_OR_ADMIN)
public final class ListHostsAction extends ListObjectsAction<HostResource> {
public final class ListHostsAction extends ListObjectsAction<Host> {
public static final String PATH = "/_dr/admin/list/hosts";
@@ -48,10 +48,10 @@ public final class ListHostsAction extends ListObjectsAction<HostResource> {
}
@Override
public ImmutableSet<HostResource> loadObjects() {
public ImmutableSet<Host> loadObjects() {
final DateTime now = clock.nowUtc();
return tm().transact(() -> tm().loadAllOf(HostResource.class)).stream()
return tm().transact(() -> tm().loadAllOf(Host.class)).stream()
.filter(host -> EppResourceUtils.isActive(host, now))
.collect(toImmutableSortedSet(comparing(HostResource::getHostName)));
.collect(toImmutableSortedSet(comparing(Host::getHostName)));
}
}

View File

@@ -18,7 +18,7 @@ import static google.registry.model.EppResourceUtils.loadByForeignKey;
import static google.registry.model.EppResourceUtils.loadByForeignKeyCached;
import com.google.common.net.InternetDomainName;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import java.util.Optional;
import org.joda.time.DateTime;
@@ -34,10 +34,10 @@ public class NameserverLookupByHostCommand extends DomainOrHostLookupCommand {
@Override
protected Optional<WhoisResponse> getResponse(InternetDomainName hostName, DateTime now) {
Optional<HostResource> hostResource =
Optional<Host> host =
cached
? loadByForeignKeyCached(HostResource.class, hostName.toString(), now)
: loadByForeignKey(HostResource.class, hostName.toString(), now);
return hostResource.map(host -> new NameserverWhoisResponse(host, now));
? loadByForeignKeyCached(Host.class, hostName.toString(), now)
: loadByForeignKey(Host.class, hostName.toString(), now);
return host.map(h -> new NameserverWhoisResponse(h, now));
}
}

View File

@@ -26,7 +26,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.Streams;
import com.google.common.net.InetAddresses;
import com.google.common.net.InternetDomainName;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.model.tld.Registries;
import java.net.InetAddress;
import org.joda.time.DateTime;
@@ -51,12 +51,12 @@ final class NameserverLookupByIpCommand implements WhoisCommand {
@Override
@SuppressWarnings("unchecked")
public WhoisResponse executeQuery(DateTime now) throws WhoisException {
Iterable<HostResource> hostsFromDb;
Iterable<Host> hostsFromDb;
if (tm().isOfy()) {
hostsFromDb =
auditedOfy()
.load()
.type(HostResource.class)
.type(Host.class)
.filter("inetAddresses", ipAddress)
.filter("deletionTime >", now.toDate());
} else {
@@ -76,12 +76,12 @@ final class NameserverLookupByIpCommand implements WhoisCommand {
"SELECT * From \"Host\" WHERE "
+ "ARRAY[ CAST(:address AS TEXT) ] <@ inet_addresses AND "
+ "deletion_time > CAST(:now AS timestamptz)",
HostResource.class)
Host.class)
.setParameter("address", InetAddresses.toAddrString(ipAddress))
.setParameter("now", now.toString())
.getResultList());
}
ImmutableList<HostResource> hosts =
ImmutableList<Host> hosts =
Streams.stream(hostsFromDb)
.filter(
host ->

View File

@@ -23,7 +23,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.net.InetAddresses;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.model.registrar.Registrar;
import java.util.Optional;
import org.joda.time.DateTime;
@@ -32,15 +32,15 @@ import org.joda.time.DateTime;
final class NameserverWhoisResponse extends WhoisResponseImpl {
/** Nameserver(s) which were the target of this WHOIS command. */
private final ImmutableList<HostResource> hosts;
private final ImmutableList<Host> hosts;
/** Creates new WHOIS nameserver response on the given host. */
NameserverWhoisResponse(HostResource host, DateTime timestamp) {
NameserverWhoisResponse(Host host, DateTime timestamp) {
this(ImmutableList.of(checkNotNull(host, "host")), timestamp);
}
/** Creates new WHOIS nameserver response on the given list of hosts. */
NameserverWhoisResponse(ImmutableList<HostResource> hosts, DateTime timestamp) {
NameserverWhoisResponse(ImmutableList<Host> hosts, DateTime timestamp) {
super(timestamp);
this.hosts = checkNotNull(hosts, "hosts");
}
@@ -48,9 +48,9 @@ final class NameserverWhoisResponse extends WhoisResponseImpl {
@Override
public WhoisResponseResults getResponse(boolean preferUnicode, String disclaimer) {
// If we have subordinate hosts, load their registrar ids in a single transaction up-front.
ImmutableList<HostResource> subordinateHosts =
hosts.stream().filter(HostResource::isSubordinate).collect(toImmutableList());
ImmutableMap<HostResource, String> hostRegistrars =
ImmutableList<Host> subordinateHosts =
hosts.stream().filter(Host::isSubordinate).collect(toImmutableList());
ImmutableMap<Host, String> hostRegistrars =
subordinateHosts.isEmpty()
? ImmutableMap.of()
: tm().transact(
@@ -64,7 +64,7 @@ final class NameserverWhoisResponse extends WhoisResponseImpl {
BasicEmitter emitter = new BasicEmitter();
for (int i = 0; i < hosts.size(); i++) {
HostResource host = hosts.get(i);
Host host = hosts.get(i);
String registrarId =
host.isSubordinate()
? hostRegistrars.get(host)

View File

@@ -53,7 +53,7 @@
<class>google.registry.model.domain.secdns.DomainDsDataHistory</class>
<class>google.registry.model.domain.token.AllocationToken</class>
<class>google.registry.model.host.HostHistory</class>
<class>google.registry.model.host.HostResource</class>
<class>google.registry.model.host.Host</class>
<class>google.registry.model.poll.PollMessage</class>
<class>google.registry.model.poll.PollMessage$OneTime</class>
<class>google.registry.model.poll.PollMessage$Autorenew</class>
@@ -104,7 +104,7 @@
<class>google.registry.model.contact.VKeyConverter_ContactResource</class>
<class>google.registry.model.domain.VKeyConverter_Domain</class>
<class>google.registry.model.domain.token.VKeyConverter_AllocationToken</class>
<class>google.registry.model.host.VKeyConverter_HostResource</class>
<class>google.registry.model.host.VKeyConverter_Host</class>
<class>google.registry.model.poll.VKeyConverter_Autorenew</class>
<class>google.registry.model.poll.VKeyConverter_OneTime</class>

View File

@@ -37,7 +37,7 @@ import com.google.cloud.tasks.v2.HttpMethod;
import com.google.common.collect.ImmutableSet;
import google.registry.model.domain.Domain;
import google.registry.model.domain.RegistryLock;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.testing.AppEngineExtension;
import google.registry.testing.CloudTasksHelper;
import google.registry.testing.CloudTasksHelper.TaskMatcher;
@@ -95,7 +95,7 @@ public class RelockDomainActionTest {
@BeforeEach
void beforeEach() throws Exception {
createTlds("tld", "net");
HostResource host = persistActiveHost("ns1.example.net");
Host host = persistActiveHost("ns1.example.net");
domain = persistResource(DatabaseHelper.newDomain(DOMAIN_NAME, host));
oldLock = domainLockUtils.administrativelyApplyLock(DOMAIN_NAME, CLIENT_ID, POC_ID, false);

View File

@@ -62,9 +62,9 @@ import google.registry.model.domain.DomainBase;
import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.Period;
import google.registry.model.eppcommon.Trid;
import google.registry.model.host.Host;
import google.registry.model.host.HostBase;
import google.registry.model.host.HostHistory;
import google.registry.model.host.HostResource;
import google.registry.model.rde.RdeMode;
import google.registry.model.rde.RdeRevision;
import google.registry.model.rde.RdeRevision.RdeRevisionId;
@@ -272,7 +272,7 @@ public class RdePipelineTest {
// This host is never referenced.
persistHostHistory(persistActiveHost("ns0.domain.tld"));
HostResource host1 = persistActiveHost("ns1.external.tld");
Host host1 = persistActiveHost("ns1.external.tld");
persistHostHistory(host1);
Domain helloDomain =
persistEppResource(
@@ -282,7 +282,7 @@ public class RdePipelineTest {
.build());
persistDomainHistory(helloDomain);
persistHostHistory(persistActiveHost("not-used-subordinate.hello.soy"));
HostResource host2 = persistActiveHost("ns1.hello.soy");
Host host2 = persistActiveHost("ns1.hello.soy");
persistHostHistory(host2);
Domain kittyDomain =
persistEppResource(
@@ -306,7 +306,7 @@ public class RdePipelineTest {
persistContactHistory(contact3);
// This is a subordinate domain in TLD .cat, which is not included in any pending deposit. But
// it should still be included as a subordinate host in the pendign deposit for .soy.
HostResource host3 = persistActiveHost("ns1.lol.cat");
Host host3 = persistActiveHost("ns1.lol.cat");
persistHostHistory(host3);
persistDomainHistory(
helloDomain
@@ -331,7 +331,7 @@ public class RdePipelineTest {
persistDomainHistory(kittyDomain.asBuilder().setDeletionTime(clock.nowUtc()).build());
ContactResource futureContact = persistActiveContact("future-contact");
persistContactHistory(futureContact);
HostResource futureHost = persistActiveHost("ns1.future.tld");
Host futureHost = persistActiveHost("ns1.future.tld");
persistHostHistory(futureHost);
persistDomainHistory(
persistEppResource(

View File

@@ -18,7 +18,7 @@ import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.io.BaseEncoding.base16;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.testing.DatabaseHelper.createTld;
import static google.registry.testing.DatabaseHelper.newHostResource;
import static google.registry.testing.DatabaseHelper.newHost;
import static google.registry.testing.DatabaseHelper.persistResource;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doThrow;
@@ -41,7 +41,7 @@ import google.registry.dns.writer.clouddns.CloudDnsWriter.ZoneStateException;
import google.registry.model.domain.Domain;
import google.registry.model.domain.secdns.DelegationSignerData;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.persistence.VKey;
import google.registry.testing.AppEngineExtension;
import google.registry.testing.DatabaseHelper;
@@ -283,31 +283,28 @@ public class CloudDnsWriterTest {
/** Returns a domain to be persisted in Datastore. */
private static Domain fakeDomain(
String domainName, ImmutableSet<HostResource> nameservers, int numDsRecords) {
String domainName, ImmutableSet<Host> nameservers, int numDsRecords) {
ImmutableSet.Builder<DelegationSignerData> dsDataBuilder = new ImmutableSet.Builder<>();
for (int i = 0; i < numDsRecords; i++) {
dsDataBuilder.add(DelegationSignerData.create(i, 3, 1, base16().decode("1234567890ABCDEF")));
}
ImmutableSet.Builder<VKey<HostResource>> hostResourceRefBuilder = new ImmutableSet.Builder<>();
for (HostResource nameserver : nameservers) {
hostResourceRefBuilder.add(nameserver.createVKey());
ImmutableSet.Builder<VKey<Host>> hostRefBuilder = new ImmutableSet.Builder<>();
for (Host nameserver : nameservers) {
hostRefBuilder.add(nameserver.createVKey());
}
return DatabaseHelper.newDomain(domainName)
.asBuilder()
.setNameservers(hostResourceRefBuilder.build())
.setNameservers(hostRefBuilder.build())
.setDsData(dsDataBuilder.build())
.build();
}
/** Returns a nameserver used for its NS record. */
private static HostResource fakeHost(String nameserver, InetAddress... addresses) {
return newHostResource(nameserver)
.asBuilder()
.setInetAddresses(ImmutableSet.copyOf(addresses))
.build();
private static Host fakeHost(String nameserver, InetAddress... addresses) {
return newHost(nameserver).asBuilder().setInetAddresses(ImmutableSet.copyOf(addresses)).build();
}
@MockitoSettings(strictness = Strictness.LENIENT)

View File

@@ -18,7 +18,7 @@ import static com.google.common.io.BaseEncoding.base16;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static google.registry.testing.DatabaseHelper.createTld;
import static google.registry.testing.DatabaseHelper.newHostResource;
import static google.registry.testing.DatabaseHelper.newHost;
import static google.registry.testing.DatabaseHelper.persistActiveDomain;
import static google.registry.testing.DatabaseHelper.persistActiveHost;
import static google.registry.testing.DatabaseHelper.persistActiveSubordinateHost;
@@ -38,7 +38,7 @@ import com.google.common.net.InetAddresses;
import google.registry.model.domain.Domain;
import google.registry.model.domain.secdns.DelegationSignerData;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.model.ofy.Ofy;
import google.registry.testing.AppEngineExtension;
import google.registry.testing.DatabaseHelper;
@@ -98,8 +98,8 @@ public class DnsUpdateWriterTest {
@Test
void testPublishDomainCreate_publishesNameServers() throws Exception {
HostResource host1 = persistActiveHost("ns1.example.tld");
HostResource host2 = persistActiveHost("ns2.example.tld");
Host host1 = persistActiveHost("ns1.example.tld");
Host host2 = persistActiveHost("ns2.example.tld");
Domain domain =
persistActiveDomain("example.tld")
.asBuilder()
@@ -121,7 +121,7 @@ public class DnsUpdateWriterTest {
@MockitoSettings(strictness = Strictness.LENIENT)
@Test
void testPublishAtomic_noCommit() {
HostResource host1 = persistActiveHost("ns.example1.tld");
Host host1 = persistActiveHost("ns.example1.tld");
Domain domain1 =
persistActiveDomain("example1.tld")
.asBuilder()
@@ -129,7 +129,7 @@ public class DnsUpdateWriterTest {
.build();
persistResource(domain1);
HostResource host2 = persistActiveHost("ns.example2.tld");
Host host2 = persistActiveHost("ns.example2.tld");
Domain domain2 =
persistActiveDomain("example2.tld")
.asBuilder()
@@ -145,7 +145,7 @@ public class DnsUpdateWriterTest {
@Test
void testPublishAtomic_oneUpdate() throws Exception {
HostResource host1 = persistActiveHost("ns.example1.tld");
Host host1 = persistActiveHost("ns.example1.tld");
Domain domain1 =
persistActiveDomain("example1.tld")
.asBuilder()
@@ -153,7 +153,7 @@ public class DnsUpdateWriterTest {
.build();
persistResource(domain1);
HostResource host2 = persistActiveHost("ns.example2.tld");
Host host2 = persistActiveHost("ns.example2.tld");
Domain domain2 =
persistActiveDomain("example2.tld")
.asBuilder()
@@ -235,9 +235,9 @@ public class DnsUpdateWriterTest {
@Test
void testPublishHostCreate_publishesAddressRecords() throws Exception {
HostResource host =
Host host =
persistResource(
newHostResource("ns1.example.tld")
newHost("ns1.example.tld")
.asBuilder()
.setInetAddresses(
ImmutableSet.of(
@@ -305,10 +305,10 @@ public class DnsUpdateWriterTest {
@Test
void testPublishDomainExternalAndInBailiwickNameServer() throws Exception {
HostResource externalNameserver = persistResource(newHostResource("ns1.example.com"));
HostResource inBailiwickNameserver =
Host externalNameserver = persistResource(newHost("ns1.example.com"));
Host inBailiwickNameserver =
persistResource(
newHostResource("ns1.example.tld")
newHost("ns1.example.tld")
.asBuilder()
.setInetAddresses(
ImmutableSet.of(
@@ -342,9 +342,9 @@ public class DnsUpdateWriterTest {
@Test
void testPublishDomainDeleteOrphanGlues() throws Exception {
HostResource inBailiwickNameserver =
Host inBailiwickNameserver =
persistResource(
newHostResource("ns1.example.tld")
newHost("ns1.example.tld")
.asBuilder()
.setInetAddresses(
ImmutableSet.of(
@@ -401,7 +401,7 @@ public class DnsUpdateWriterTest {
@SuppressWarnings("AssertThrowsMultipleStatements")
@Test
void testPublishHostFails_whenDnsUpdateReturnsError() throws Exception {
HostResource host =
Host host =
persistActiveSubordinateHost("ns1.example.tld", persistActiveDomain("example.tld"))
.asBuilder()
.setInetAddresses(ImmutableSet.of(InetAddresses.forString("10.0.0.1")))

View File

@@ -20,11 +20,11 @@ import static google.registry.model.eppoutput.Result.Code.SUCCESS;
import static google.registry.testing.DatabaseHelper.createTld;
import static google.registry.testing.DatabaseHelper.createTlds;
import static google.registry.testing.EppMetricSubject.assertThat;
import static google.registry.testing.HostResourceSubject.assertAboutHosts;
import static google.registry.testing.HostSubject.assertAboutHosts;
import com.google.common.collect.ImmutableMap;
import google.registry.model.domain.Domain;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.testing.AppEngineExtension;
import org.joda.time.DateTime;
import org.junit.jupiter.api.Test;
@@ -210,8 +210,8 @@ class EppLifecycleHostTest extends EppTestCase {
DateTime timeAfterCreates = DateTime.parse("2000-06-01T00:06:00Z");
HostResource exampleBarFooTldHost =
loadByForeignKey(HostResource.class, "ns1.example.bar.foo.tld", timeAfterCreates).get();
Host exampleBarFooTldHost =
loadByForeignKey(Host.class, "ns1.example.bar.foo.tld", timeAfterCreates).get();
Domain exampleBarFooTldDomain =
loadByForeignKey(Domain.class, "example.bar.foo.tld", timeAfterCreates).get();
assertAboutHosts()
@@ -220,8 +220,8 @@ class EppLifecycleHostTest extends EppTestCase {
assertThat(exampleBarFooTldDomain.getSubordinateHosts())
.containsExactly("ns1.example.bar.foo.tld");
HostResource exampleFooTldHost =
loadByForeignKey(HostResource.class, "ns1.example.foo.tld", timeAfterCreates).get();
Host exampleFooTldHost =
loadByForeignKey(Host.class, "ns1.example.foo.tld", timeAfterCreates).get();
Domain exampleFooTldDomain =
loadByForeignKey(Domain.class, "example.foo.tld", timeAfterCreates).get();
assertAboutHosts()
@@ -229,8 +229,7 @@ class EppLifecycleHostTest extends EppTestCase {
.hasSuperordinateDomain(exampleFooTldDomain.createVKey());
assertThat(exampleFooTldDomain.getSubordinateHosts()).containsExactly("ns1.example.foo.tld");
HostResource exampleTldHost =
loadByForeignKey(HostResource.class, "ns1.example.tld", timeAfterCreates).get();
Host exampleTldHost = loadByForeignKey(Host.class, "ns1.example.tld", timeAfterCreates).get();
Domain exampleTldDomain = loadByForeignKey(Domain.class, "example.tld", timeAfterCreates).get();
assertAboutHosts().that(exampleTldHost).hasSuperordinateDomain(exampleTldDomain.createVKey());
assertThat(exampleTldDomain.getSubordinateHosts()).containsExactly("ns1.example.tld");

View File

@@ -14,6 +14,7 @@
package google.registry.flows;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
import static google.registry.testing.CertificateSamples.SAMPLE_CERT;
import static google.registry.testing.DatabaseHelper.loadRegistrar;
@@ -81,16 +82,23 @@ final class TlsCredentialsTest {
@Test
void test_missingIpAddress_doesntAllowAccess() {
TlsCredentials tls =
new TlsCredentials(false, Optional.of("certHash"), Optional.empty(), certificateChecker);
new TlsCredentials(
false, Optional.of("certHash"), Optional.of("127.0.0.1"), certificateChecker);
persistResource(
loadRegistrar("TheRegistrar")
.asBuilder()
.setClientCertificate(SAMPLE_CERT, clock.nowUtc())
.setIpAddressAllowList(ImmutableSet.of(CidrAddressBlock.create("3.5.8.13")))
.build());
assertThrows(
BadRegistrarIpAddressException.class,
() -> tls.validate(Registrar.loadByRegistrarId("TheRegistrar").get(), "password"));
BadRegistrarIpAddressException thrown =
assertThrows(
BadRegistrarIpAddressException.class,
() -> tls.validate(Registrar.loadByRegistrarId("TheRegistrar").get(), "password"));
assertThat(thrown)
.hasMessageThat()
.isEqualTo("Registrar IP address 127.0.0.1 is not in stored allow list");
}
@Test

View File

@@ -82,29 +82,21 @@ import google.registry.model.tld.Registry;
import google.registry.model.tld.Registry.TldState;
import google.registry.model.tld.label.ReservedList;
import google.registry.testing.DatabaseHelper;
import google.registry.testing.SetClockExtension;
import java.math.BigDecimal;
import org.joda.money.CurrencyUnit;
import org.joda.money.Money;
import org.joda.time.DateTime;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link DomainCheckFlow}. */
class DomainCheckFlowTest extends ResourceCheckFlowTestCase<DomainCheckFlow, Domain> {
@Order(value = Order.DEFAULT - 3)
@RegisterExtension
final SetClockExtension setClockExtension = new SetClockExtension(clock, "2009-01-01T10:00:00Z");
DomainCheckFlowTest() {
setEppInput("domain_check_one_tld.xml");
clock.setTo(DateTime.parse("2009-01-01T10:00:00Z"));
}
private ReservedList createReservedList() {
private static ReservedList createReservedList() {
persistResource(
new AllocationToken.Builder()
.setDomainName("anchor.tld")
@@ -951,10 +943,7 @@ class DomainCheckFlowTest extends ResourceCheckFlowTestCase<DomainCheckFlow, Dom
// This works because Money.getAmount(), used in the flow, returns a BigDecimal that is set to
// display the number of digits that is conventional for the given currency.
persistResource(
Registry.get("tld")
.asBuilder()
.setCreateBillingCost(Money.of(CurrencyUnit.USD, 11.1))
.build());
Registry.get("tld").asBuilder().setCreateBillingCost(Money.of(USD, 11.1)).build());
setEppInput("domain_check_fee_fractional.xml");
runFlowAssertResponse(loadFile("domain_check_fee_fractional_response.xml"));
}
@@ -1398,7 +1387,6 @@ class DomainCheckFlowTest extends ResourceCheckFlowTestCase<DomainCheckFlow, Dom
"domain_check_fee_date_v12.xml", "domain_check_eap_fee_response_date_v12.xml");
}
@Disabled
@Test
void testSuccess_feeCheck_multipleRanges() {
// TODO: If at some point we have more than one type of fees that are time dependent, populate

View File

@@ -41,13 +41,20 @@ import google.registry.flows.exceptions.TooManyResourceChecksException;
import google.registry.model.domain.Domain;
import google.registry.model.tld.Registry;
import google.registry.model.tld.Registry.TldState;
import google.registry.testing.TestCacheExtension;
import java.time.Duration;
import org.joda.money.Money;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link DomainClaimsCheckFlow}. */
public class DomainClaimsCheckFlowTest extends ResourceFlowTestCase<DomainClaimsCheckFlow, Domain> {
@RegisterExtension
public final TestCacheExtension testCacheExtension =
new TestCacheExtension.Builder().withClaimsListCache(Duration.ofHours(6)).build();
DomainClaimsCheckFlowTest() {
setEppInput("domain_check_claims.xml");
}

View File

@@ -43,7 +43,7 @@ import static google.registry.testing.DatabaseHelper.deleteTld;
import static google.registry.testing.DatabaseHelper.getHistoryEntries;
import static google.registry.testing.DatabaseHelper.loadRegistrar;
import static google.registry.testing.DatabaseHelper.newContactResource;
import static google.registry.testing.DatabaseHelper.newHostResource;
import static google.registry.testing.DatabaseHelper.newHost;
import static google.registry.testing.DatabaseHelper.persistActiveContact;
import static google.registry.testing.DatabaseHelper.persistActiveDomain;
import static google.registry.testing.DatabaseHelper.persistActiveHost;
@@ -1698,8 +1698,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
persistActiveHost("ns1.example.net");
persistActiveContact("jd1234");
persistActiveContact("sh8013");
persistResource(
newHostResource("ns2.example.net").asBuilder().addStatusValue(PENDING_DELETE).build());
persistResource(newHost("ns2.example.net").asBuilder().addStatusValue(PENDING_DELETE).build());
clock.advanceOneMilli();
LinkedResourceInPendingDeleteProhibitsOperationException thrown =
assertThrows(LinkedResourceInPendingDeleteProhibitsOperationException.class, this::runFlow);

View File

@@ -44,7 +44,7 @@ import static google.registry.testing.DatabaseHelper.loadByKey;
import static google.registry.testing.DatabaseHelper.loadByKeyIfPresent;
import static google.registry.testing.DatabaseHelper.loadByKeysIfPresent;
import static google.registry.testing.DatabaseHelper.loadRegistrar;
import static google.registry.testing.DatabaseHelper.newHostResource;
import static google.registry.testing.DatabaseHelper.newHost;
import static google.registry.testing.DatabaseHelper.persistActiveContact;
import static google.registry.testing.DatabaseHelper.persistActiveDomain;
import static google.registry.testing.DatabaseHelper.persistDeletedDomain;
@@ -88,7 +88,7 @@ import google.registry.model.domain.rgp.GracePeriodStatus;
import google.registry.model.eppcommon.ProtocolDefinition.ServiceExtension;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.eppcommon.Trid;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.model.poll.PendingActionNotificationResponse;
import google.registry.model.poll.PendingActionNotificationResponse.DomainPendingActionNotificationResponse;
import google.registry.model.poll.PollMessage;
@@ -732,7 +732,7 @@ class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow, Domain
setUpGracePeriods(
GracePeriod.forBillingEvent(GracePeriodStatus.ADD, domain.getRepoId(), graceBillingEvent));
// Add a nameserver.
HostResource host = persistResource(newHostResource("ns1.example.tld"));
Host host = persistResource(newHost("ns1.example.tld"));
persistResource(
loadByForeignKey(Domain.class, getUniqueIdFromCommand(), clock.nowUtc())
.get()
@@ -763,7 +763,7 @@ class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow, Domain
void testSuccess_deletedSubordinateDomain() throws Exception {
setUpSuccessfulTest();
persistResource(
newHostResource("ns1." + getUniqueIdFromCommand())
newHost("ns1." + getUniqueIdFromCommand())
.asBuilder()
.setSuperordinateDomain(reloadResourceByForeignKey().createVKey())
.setDeletionTime(clock.nowUtc().minusDays(1))
@@ -809,9 +809,9 @@ class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow, Domain
@Test
void testFailure_hasSubordinateHosts() throws Exception {
Domain domain = persistActiveDomain(getUniqueIdFromCommand());
HostResource subordinateHost =
Host subordinateHost =
persistResource(
newHostResource("ns1." + getUniqueIdFromCommand())
newHost("ns1." + getUniqueIdFromCommand())
.asBuilder()
.setSuperordinateDomain(reloadResourceByForeignKey().createVKey())
.build());

View File

@@ -48,9 +48,9 @@ import google.registry.flows.domain.DomainFlowUtils.CurrencyUnitMismatchExceptio
import google.registry.flows.domain.DomainFlowUtils.FeeChecksDontSupportPhasesException;
import google.registry.flows.domain.DomainFlowUtils.RestoresAreAlwaysForOneYearException;
import google.registry.flows.domain.DomainFlowUtils.TransfersAreAlwaysForOneYearException;
import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.Flag;
import google.registry.model.billing.BillingEvent.Reason;
import google.registry.model.billing.BillingEvent.Recurring;
import google.registry.model.billing.BillingEvent.RenewalPriceBehavior;
import google.registry.model.contact.ContactAuthInfo;
import google.registry.model.contact.ContactResource;
@@ -64,29 +64,22 @@ import google.registry.model.domain.rgp.GracePeriodStatus;
import google.registry.model.domain.secdns.DelegationSignerData;
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.model.reporting.HistoryEntry;
import google.registry.model.tld.Registry;
import google.registry.persistence.VKey;
import google.registry.testing.AppEngineExtension;
import google.registry.testing.DatabaseHelper;
import google.registry.testing.SetClockExtension;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import org.joda.money.Money;
import org.joda.time.DateTime;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link DomainInfoFlow}. */
class DomainInfoFlowTest extends ResourceFlowTestCase<DomainInfoFlow, Domain> {
@Order(value = Order.DEFAULT - 3)
@RegisterExtension
final SetClockExtension setClockExtension =
new SetClockExtension(clock, "2005-03-03T22:00:00.000Z");
/**
* The domain_info_fee.xml default substitutions common to most tests.
*
@@ -99,16 +92,19 @@ class DomainInfoFlowTest extends ResourceFlowTestCase<DomainInfoFlow, Domain> {
"CURRENCY", "USD",
"UNIT", "y");
private static final Pattern OK_PATTERN = Pattern.compile("\"ok\"");
private ContactResource registrant;
private ContactResource contact;
private HostResource host1;
private HostResource host2;
private HostResource host3;
private Host host1;
private Host host2;
private Host host3;
private Domain domain;
@BeforeEach
void setup() {
setEppInput("domain_info.xml");
clock.setTo(DateTime.parse("2005-03-03T22:00:00.000Z"));
sessionMetadata.setRegistrarId("NewRegistrar");
createTld("tld");
persistResource(
@@ -147,7 +143,7 @@ class DomainInfoFlowTest extends ResourceFlowTestCase<DomainInfoFlow, Domain> {
// Create a subordinate host that is not delegated to by anyone.
host3 =
persistResource(
new HostResource.Builder()
new Host.Builder()
.setHostName("ns2.example.tld")
.setRepoId("3FF-TLD")
.setSuperordinateDomain(domain.createVKey())
@@ -175,7 +171,7 @@ class DomainInfoFlowTest extends ResourceFlowTestCase<DomainInfoFlow, Domain> {
String expected =
loadFile(expectedXmlFilename, updateSubstitutions(substitutions, "ROID", "2FF-TLD"));
if (inactive) {
expected = expected.replaceAll("\"ok\"", "\"inactive\"");
expected = OK_PATTERN.matcher(expected).replaceAll("\"inactive\"");
}
runFlowAssertResponse(expected);
if (!expectHistoryAndBilling) {
@@ -379,9 +375,9 @@ class DomainInfoFlowTest extends ResourceFlowTestCase<DomainInfoFlow, Domain> {
.setModificationTime(clock.nowUtc())
.setRegistrarId(domain.getCreationRegistrarId())
.build());
BillingEvent.Recurring renewEvent =
Recurring renewEvent =
persistResource(
new BillingEvent.Recurring.Builder()
new Recurring.Builder()
.setReason(Reason.RENEW)
.setFlags(ImmutableSet.of(Flag.AUTO_RENEW))
.setTargetId(getUniqueIdFromCommand())
@@ -390,7 +386,7 @@ class DomainInfoFlowTest extends ResourceFlowTestCase<DomainInfoFlow, Domain> {
.setRecurrenceEndTime(END_OF_TIME)
.setDomainHistory(historyEntry)
.build());
VKey<BillingEvent.Recurring> recurringVKey = renewEvent.createVKey();
VKey<Recurring> recurringVKey = renewEvent.createVKey();
// Add an AUTO_RENEW grace period to the saved resource.
persistResource(
domain

View File

@@ -399,4 +399,128 @@ public class DomainPricingLogicTest {
registry, "standard.example", clock.nowUtc(), -1, null));
assertThat(thrown).hasMessageThat().isEqualTo("Number of years must be positive");
}
@Test
void testGetDomainTransferPrice_standardDomain_default_noBilling_defaultRenewalPrice()
throws EppException {
assertThat(
domainPricingLogic.getTransferPrice(registry, "standard.example", clock.nowUtc(), null))
.isEqualTo(
new FeesAndCredits.Builder()
.setCurrency(USD)
.addFeeOrCredit(Fee.create(Money.of(USD, 10).getAmount(), RENEW, false))
.build());
}
@Test
void testGetDomainTransferPrice_premiumDomain_default_noBilling_premiumRenewalPrice()
throws EppException {
assertThat(
domainPricingLogic.getTransferPrice(registry, "premium.example", clock.nowUtc(), null))
.isEqualTo(
new FeesAndCredits.Builder()
.setCurrency(USD)
.addFeeOrCredit(Fee.create(Money.of(USD, 100).getAmount(), RENEW, true))
.build());
}
@Test
void testGetDomainTransferPrice_standardDomain_default_defaultRenewalPrice() throws EppException {
assertThat(
domainPricingLogic.getTransferPrice(
registry,
"standard.example",
clock.nowUtc(),
persistDomainAndSetRecurringBillingEvent(
"standard.example", DEFAULT, Optional.empty())))
.isEqualTo(
new FeesAndCredits.Builder()
.setCurrency(USD)
.addFeeOrCredit(Fee.create(Money.of(USD, 10).getAmount(), RENEW, false))
.build());
}
@Test
void testGetDomainTransferPrice_premiumDomain_default_premiumRenewalPrice() throws EppException {
assertThat(
domainPricingLogic.getTransferPrice(
registry,
"premium.example",
clock.nowUtc(),
persistDomainAndSetRecurringBillingEvent(
"premium.example", DEFAULT, Optional.empty())))
.isEqualTo(
new FeesAndCredits.Builder()
.setCurrency(USD)
.addFeeOrCredit(Fee.create(Money.of(USD, 100).getAmount(), RENEW, true))
.build());
}
@Test
void testGetDomainTransferPrice_standardDomain_nonPremium_nonPremiumRenewalPrice()
throws EppException {
assertThat(
domainPricingLogic.getTransferPrice(
registry,
"standard.example",
clock.nowUtc(),
persistDomainAndSetRecurringBillingEvent(
"standard.example", NONPREMIUM, Optional.empty())))
.isEqualTo(
new FeesAndCredits.Builder()
.setCurrency(USD)
.addFeeOrCredit(Fee.create(Money.of(USD, 10).getAmount(), RENEW, false))
.build());
}
@Test
void testGetDomainTransferPrice_premiumDomain_nonPremium_nonPremiumRenewalPrice()
throws EppException {
assertThat(
domainPricingLogic.getTransferPrice(
registry,
"premium.example",
clock.nowUtc(),
persistDomainAndSetRecurringBillingEvent(
"premium.example", NONPREMIUM, Optional.empty())))
.isEqualTo(
new FeesAndCredits.Builder()
.setCurrency(USD)
.addFeeOrCredit(Fee.create(Money.of(USD, 10).getAmount(), RENEW, false))
.build());
}
@Test
void testGetDomainTransferPrice_standardDomain_specified_specifiedRenewalPrice()
throws EppException {
assertThat(
domainPricingLogic.getTransferPrice(
registry,
"standard.example",
clock.nowUtc(),
persistDomainAndSetRecurringBillingEvent(
"standard.example", SPECIFIED, Optional.of(Money.of(USD, 1.23)))))
.isEqualTo(
new FeesAndCredits.Builder()
.setCurrency(USD)
.addFeeOrCredit(Fee.create(Money.of(USD, 1.23).getAmount(), RENEW, false))
.build());
}
@Test
void testGetDomainTransferPrice_premiumDomain_specified_specifiedRenewalPrice()
throws EppException {
assertThat(
domainPricingLogic.getTransferPrice(
registry,
"premium.example",
clock.nowUtc(),
persistDomainAndSetRecurringBillingEvent(
"premium.example", SPECIFIED, Optional.of(Money.of(USD, 1.23)))))
.isEqualTo(
new FeesAndCredits.Builder()
.setCurrency(USD)
.addFeeOrCredit(Fee.create(Money.of(USD, 1.23).getAmount(), RENEW, false))
.build());
}
}

View File

@@ -29,7 +29,6 @@ import static google.registry.testing.DatabaseHelper.createTld;
import static google.registry.testing.DatabaseHelper.getOnlyHistoryEntryOfType;
import static google.registry.testing.DatabaseHelper.loadByKey;
import static google.registry.testing.DatabaseHelper.loadRegistrar;
import static google.registry.testing.DatabaseHelper.newDomain;
import static google.registry.testing.DatabaseHelper.persistActiveDomain;
import static google.registry.testing.DatabaseHelper.persistDeletedDomain;
import static google.registry.testing.DatabaseHelper.persistPremiumList;
@@ -95,16 +94,13 @@ import google.registry.model.reporting.HistoryEntry;
import google.registry.model.tld.Registry;
import google.registry.persistence.VKey;
import google.registry.testing.DatabaseHelper;
import google.registry.testing.SetClockExtension;
import java.util.Map;
import javax.annotation.Nullable;
import org.joda.money.Money;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link DomainRenewFlow}. */
class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain> {
@@ -126,13 +122,9 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain>
private final DateTime expirationTime = DateTime.parse("2000-04-03T22:00:00.0Z");
@Order(value = Order.DEFAULT - 3)
@RegisterExtension
final SetClockExtension setClockExtension =
new SetClockExtension(clock, expirationTime.minusMillis(20));
@BeforeEach
void initDomainTest() {
clock.setTo(expirationTime.minusMillis(20));
createTld("tld");
persistResource(
loadRegistrar("TheRegistrar")

View File

@@ -16,6 +16,8 @@ package google.registry.flows.domain;
import static com.google.common.collect.MoreCollectors.onlyElement;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.domain.token.AllocationToken.TokenType.SINGLE_USE;
import static google.registry.model.domain.token.AllocationToken.TokenType.UNLIMITED_USE;
import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.NET_ADDS_4_YR;
import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.TRANSFER_SUCCESSFUL;
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_CREATE;
@@ -27,6 +29,7 @@ import static google.registry.testing.DatabaseHelper.deleteTestDomain;
import static google.registry.testing.DatabaseHelper.getOnlyHistoryEntryOfType;
import static google.registry.testing.DatabaseHelper.getOnlyPollMessage;
import static google.registry.testing.DatabaseHelper.getPollMessages;
import static google.registry.testing.DatabaseHelper.loadByEntity;
import static google.registry.testing.DatabaseHelper.loadByKey;
import static google.registry.testing.DatabaseHelper.loadRegistrar;
import static google.registry.testing.DatabaseHelper.persistResource;
@@ -42,17 +45,25 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Ordering;
import com.google.common.collect.Streams;
import com.googlecode.objectify.Key;
import google.registry.flows.EppException;
import google.registry.flows.FlowUtils.NotLoggedInException;
import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException;
import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException;
import google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException;
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotInPromotionException;
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForDomainException;
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForRegistrarException;
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForTldException;
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AlreadyRedeemedAllocationTokenException;
import google.registry.flows.domain.token.AllocationTokenFlowUtils.InvalidAllocationTokenException;
import google.registry.flows.exceptions.NotPendingTransferException;
import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.OneTime;
import google.registry.model.billing.BillingEvent.Reason;
import google.registry.model.billing.BillingEvent.Recurring;
import google.registry.model.billing.BillingEvent.RenewalPriceBehavior;
import google.registry.model.contact.ContactAuthInfo;
import google.registry.model.domain.Domain;
import google.registry.model.domain.DomainAuthInfo;
@@ -61,6 +72,8 @@ import google.registry.model.domain.GracePeriod;
import google.registry.model.domain.Period;
import google.registry.model.domain.Period.Unit;
import google.registry.model.domain.rgp.GracePeriodStatus;
import google.registry.model.domain.token.AllocationToken;
import google.registry.model.domain.token.AllocationToken.TokenStatus;
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.eppcommon.Trid;
@@ -69,10 +82,14 @@ import google.registry.model.poll.PollMessage;
import google.registry.model.reporting.DomainTransactionRecord;
import google.registry.model.reporting.HistoryEntry;
import google.registry.model.tld.Registry;
import google.registry.model.tld.label.PremiumList;
import google.registry.model.tld.label.PremiumListDao;
import google.registry.model.transfer.DomainTransferData;
import google.registry.model.transfer.TransferResponse.DomainTransferResponse;
import google.registry.model.transfer.TransferStatus;
import google.registry.persistence.VKey;
import google.registry.testing.DatabaseHelper;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.stream.Stream;
import org.joda.money.Money;
@@ -415,6 +432,103 @@ class DomainTransferApproveFlowTest
.setRecurringEventKey(domain.getAutorenewBillingEvent()));
}
@Test
void testSuccess_nonpremiumPriceRenewalBehavior_carriesOver() throws Exception {
PremiumList pl =
PremiumListDao.save(
new PremiumList.Builder()
.setCurrency(USD)
.setName("tld")
.setLabelsToPrices(ImmutableMap.of("example", new BigDecimal("67.89")))
.build());
persistResource(Registry.get("tld").asBuilder().setPremiumList(pl).build());
setupDomainWithPendingTransfer("example", "tld");
domain = loadByEntity(domain);
persistResource(
loadByKey(domain.getAutorenewBillingEvent())
.asBuilder()
.setRenewalPriceBehavior(RenewalPriceBehavior.NONPREMIUM)
.build());
setEppInput("domain_transfer_approve_wildcard.xml", ImmutableMap.of("DOMAIN", "example.tld"));
DateTime now = clock.nowUtc();
runFlowAssertResponse(loadFile("domain_transfer_approve_response.xml"));
domain = reloadResourceByForeignKey();
DomainHistory acceptHistory =
getOnlyHistoryEntryOfType(domain, DOMAIN_TRANSFER_APPROVE, DomainHistory.class);
assertBillingEventsForResource(
domain,
new BillingEvent.OneTime.Builder()
.setBillingTime(now.plusDays(5))
.setEventTime(now)
.setRegistrarId("NewRegistrar")
.setCost(Money.of(USD, new BigDecimal("11.00")))
.setDomainHistory(acceptHistory)
.setReason(Reason.TRANSFER)
.setPeriodYears(1)
.setTargetId("example.tld")
.build(),
getGainingClientAutorenewEvent()
.asBuilder()
.setRenewalPriceBehavior(RenewalPriceBehavior.NONPREMIUM)
.setDomainHistory(acceptHistory)
.build(),
getLosingClientAutorenewEvent()
.asBuilder()
.setRecurrenceEndTime(now)
.setRenewalPriceBehavior(RenewalPriceBehavior.NONPREMIUM)
.build());
}
@Test
void testSuccess_specifiedPriceRenewalBehavior_carriesOver() throws Exception {
PremiumList pl =
PremiumListDao.save(
new PremiumList.Builder()
.setCurrency(USD)
.setName("tld")
.setLabelsToPrices(ImmutableMap.of("example", new BigDecimal("67.89")))
.build());
persistResource(Registry.get("tld").asBuilder().setPremiumList(pl).build());
setupDomainWithPendingTransfer("example", "tld");
domain = loadByEntity(domain);
persistResource(
loadByKey(domain.getAutorenewBillingEvent())
.asBuilder()
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
.setRenewalPrice(Money.of(USD, new BigDecimal("43.10")))
.build());
setEppInput("domain_transfer_approve_wildcard.xml", ImmutableMap.of("DOMAIN", "example.tld"));
DateTime now = clock.nowUtc();
runFlowAssertResponse(loadFile("domain_transfer_approve_response.xml"));
domain = reloadResourceByForeignKey();
DomainHistory acceptHistory =
getOnlyHistoryEntryOfType(domain, DOMAIN_TRANSFER_APPROVE, DomainHistory.class);
assertBillingEventsForResource(
domain,
new BillingEvent.OneTime.Builder()
.setBillingTime(now.plusDays(5))
.setEventTime(now)
.setRegistrarId("NewRegistrar")
.setCost(Money.of(USD, new BigDecimal("43.10")))
.setDomainHistory(acceptHistory)
.setReason(Reason.TRANSFER)
.setPeriodYears(1)
.setTargetId("example.tld")
.build(),
getGainingClientAutorenewEvent()
.asBuilder()
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
.setRenewalPrice(Money.of(USD, new BigDecimal("43.10")))
.setDomainHistory(acceptHistory)
.build(),
getLosingClientAutorenewEvent()
.asBuilder()
.setRecurrenceEndTime(now)
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
.setRenewalPrice(Money.of(USD, new BigDecimal("43.10")))
.build());
}
@Test
void testFailure_badContactPassword() {
// Change the contact's password so it does not match the password in the file.
@@ -673,4 +787,115 @@ class DomainTransferApproveFlowTest
domain.getRegistrationExpirationTime());
assertHistoryEntriesDoNotContainTransferBillingEventsOrGracePeriods();
}
@Test
void testSuccess_allocationToken() throws Exception {
persistResource(
new AllocationToken.Builder()
.setToken("abc123")
.setTokenType(SINGLE_USE)
.setDomainName("example.tld")
.build());
doSuccessfulTest(
"tld",
"domain_transfer_approve_allocation_token.xml",
"domain_transfer_approve_response.xml");
}
@Test
void testFailure_invalidAllocationToken() throws Exception {
setEppInput("domain_transfer_approve_allocation_token.xml");
EppException thrown = assertThrows(InvalidAllocationTokenException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
void testFailure_allocationTokenIsForDifferentName() throws Exception {
persistResource(
new AllocationToken.Builder()
.setToken("abc123")
.setTokenType(SINGLE_USE)
.setDomainName("otherdomain.tld")
.build());
setEppInput("domain_transfer_approve_allocation_token.xml");
EppException thrown =
assertThrows(AllocationTokenNotValidForDomainException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
void testFailure_allocationTokenNotActive() throws Exception {
persistResource(
new AllocationToken.Builder()
.setToken("abc123")
.setTokenType(UNLIMITED_USE)
.setDiscountFraction(0.5)
.setTokenStatusTransitions(
ImmutableSortedMap.<DateTime, TokenStatus>naturalOrder()
.put(START_OF_TIME, TokenStatus.NOT_STARTED)
.put(clock.nowUtc().plusDays(1), TokenStatus.VALID)
.put(clock.nowUtc().plusDays(60), TokenStatus.ENDED)
.build())
.build());
setEppInput("domain_transfer_approve_allocation_token.xml");
EppException thrown = assertThrows(AllocationTokenNotInPromotionException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
void testFailure_allocationTokenNotValidForRegistrar() throws Exception {
persistResource(
new AllocationToken.Builder()
.setToken("abc123")
.setTokenType(UNLIMITED_USE)
.setAllowedRegistrarIds(ImmutableSet.of("someClientId"))
.setDiscountFraction(0.5)
.setTokenStatusTransitions(
ImmutableSortedMap.<DateTime, TokenStatus>naturalOrder()
.put(START_OF_TIME, TokenStatus.NOT_STARTED)
.put(clock.nowUtc().minusDays(1), TokenStatus.VALID)
.put(clock.nowUtc().plusDays(1), TokenStatus.ENDED)
.build())
.build());
setEppInput("domain_transfer_approve_allocation_token.xml");
EppException thrown =
assertThrows(AllocationTokenNotValidForRegistrarException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
void testFailure_allocationTokenNotValidForTld() throws Exception {
persistResource(
new AllocationToken.Builder()
.setToken("abc123")
.setTokenType(UNLIMITED_USE)
.setAllowedTlds(ImmutableSet.of("example"))
.setDiscountFraction(0.5)
.setTokenStatusTransitions(
ImmutableSortedMap.<DateTime, TokenStatus>naturalOrder()
.put(START_OF_TIME, TokenStatus.NOT_STARTED)
.put(clock.nowUtc().minusDays(1), TokenStatus.VALID)
.put(clock.nowUtc().plusDays(1), TokenStatus.ENDED)
.build())
.build());
setEppInput("domain_transfer_approve_allocation_token.xml");
EppException thrown = assertThrows(AllocationTokenNotValidForTldException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
void testFailure_allocationTokenAlreadyRedeemed() throws Exception {
Domain domain = DatabaseHelper.newDomain("foo.tld");
Key<HistoryEntry> historyEntryKey = Key.create(Key.create(domain), HistoryEntry.class, 505L);
persistResource(
new AllocationToken.Builder()
.setToken("abc123")
.setTokenType(SINGLE_USE)
.setRedemptionHistoryEntry(HistoryEntry.createVKey(historyEntryKey))
.build());
setEppInput("domain_transfer_approve_allocation_token.xml");
EppException thrown =
assertThrows(AlreadyRedeemedAllocationTokenException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
}

View File

@@ -39,7 +39,7 @@ import google.registry.model.contact.ContactResource;
import google.registry.model.domain.Domain;
import google.registry.model.domain.DomainHistory;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.model.reporting.HistoryEntry;
import google.registry.model.tld.Registry;
import google.registry.model.transfer.TransferData;
@@ -73,7 +73,7 @@ abstract class DomainTransferFlowTestCase<F extends Flow, R extends EppResource>
protected ContactResource contact;
protected Domain domain;
HostResource subordinateHost;
Host subordinateHost;
private DomainHistory historyEntryDomainCreate;
DomainTransferFlowTestCase() {
@@ -111,7 +111,7 @@ abstract class DomainTransferFlowTestCase<F extends Flow, R extends EppResource>
REGISTRATION_EXPIRATION_TIME);
subordinateHost =
persistResource(
new HostResource.Builder()
new Host.Builder()
.setRepoId("2-".concat(Ascii.toUpperCase(tld)))
.setHostName("ns1." + label + "." + tld)
.setPersistedCurrentSponsorRegistrarId("TheRegistrar")

View File

@@ -21,6 +21,8 @@ import static com.google.common.truth.Truth8.assertThat;
import static google.registry.batch.AsyncTaskEnqueuer.PARAM_REQUESTED_TIME;
import static google.registry.batch.AsyncTaskEnqueuer.PARAM_RESOURCE_KEY;
import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_ACTIONS;
import static google.registry.model.domain.token.AllocationToken.TokenType.SINGLE_USE;
import static google.registry.model.domain.token.AllocationToken.TokenType.UNLIMITED_USE;
import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.TRANSFER_SUCCESSFUL;
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_CREATE;
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_TRANSFER_REQUEST;
@@ -28,11 +30,13 @@ import static google.registry.model.tld.Registry.TldState.QUIET_PERIOD;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.testing.DatabaseHelper.assertBillingEvents;
import static google.registry.testing.DatabaseHelper.assertBillingEventsEqual;
import static google.registry.testing.DatabaseHelper.assertBillingEventsForResource;
import static google.registry.testing.DatabaseHelper.assertPollMessagesEqual;
import static google.registry.testing.DatabaseHelper.createTld;
import static google.registry.testing.DatabaseHelper.getOnlyHistoryEntryOfType;
import static google.registry.testing.DatabaseHelper.getOnlyPollMessage;
import static google.registry.testing.DatabaseHelper.getPollMessages;
import static google.registry.testing.DatabaseHelper.loadByEntity;
import static google.registry.testing.DatabaseHelper.loadByKey;
import static google.registry.testing.DatabaseHelper.loadByKeys;
import static google.registry.testing.DatabaseHelper.loadRegistrar;
@@ -41,7 +45,7 @@ import static google.registry.testing.DatabaseHelper.persistResource;
import static google.registry.testing.DomainSubject.assertAboutDomains;
import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptions;
import static google.registry.testing.HistoryEntrySubject.assertAboutHistoryEntries;
import static google.registry.testing.HostResourceSubject.assertAboutHosts;
import static google.registry.testing.HostSubject.assertAboutHosts;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import static org.joda.money.CurrencyUnit.JPY;
import static org.joda.money.CurrencyUnit.USD;
@@ -57,6 +61,7 @@ import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.collect.Streams;
import com.googlecode.objectify.Key;
import google.registry.batch.ResaveEntityAction;
import google.registry.flows.EppException;
import google.registry.flows.EppRequestSource;
@@ -74,6 +79,12 @@ import google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException
import google.registry.flows.domain.DomainFlowUtils.PremiumNameBlockedException;
import google.registry.flows.domain.DomainFlowUtils.RegistrarMustBeActiveForThisOperationException;
import google.registry.flows.domain.DomainFlowUtils.UnsupportedFeeAttributeException;
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotInPromotionException;
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForDomainException;
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForRegistrarException;
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForTldException;
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AlreadyRedeemedAllocationTokenException;
import google.registry.flows.domain.token.AllocationTokenFlowUtils.InvalidAllocationTokenException;
import google.registry.flows.exceptions.AlreadyPendingTransferException;
import google.registry.flows.exceptions.InvalidTransferPeriodValueException;
import google.registry.flows.exceptions.MissingTransferRequestAuthInfoException;
@@ -83,6 +94,7 @@ import google.registry.flows.exceptions.TransferPeriodMustBeOneYearException;
import google.registry.flows.exceptions.TransferPeriodZeroAndFeeTransferExtensionException;
import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.Reason;
import google.registry.model.billing.BillingEvent.RenewalPriceBehavior;
import google.registry.model.contact.ContactAuthInfo;
import google.registry.model.domain.Domain;
import google.registry.model.domain.DomainAuthInfo;
@@ -91,6 +103,8 @@ import google.registry.model.domain.GracePeriod;
import google.registry.model.domain.Period;
import google.registry.model.domain.Period.Unit;
import google.registry.model.domain.rgp.GracePeriodStatus;
import google.registry.model.domain.token.AllocationToken;
import google.registry.model.domain.token.AllocationToken.TokenStatus;
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.eppcommon.Trid;
@@ -101,11 +115,15 @@ import google.registry.model.registrar.Registrar.State;
import google.registry.model.reporting.DomainTransactionRecord;
import google.registry.model.reporting.HistoryEntry;
import google.registry.model.tld.Registry;
import google.registry.model.tld.label.PremiumList;
import google.registry.model.tld.label.PremiumListDao;
import google.registry.model.transfer.DomainTransferData;
import google.registry.model.transfer.TransferResponse;
import google.registry.model.transfer.TransferStatus;
import google.registry.persistence.VKey;
import google.registry.testing.CloudTasksHelper.TaskMatcher;
import google.registry.testing.DatabaseHelper;
import java.math.BigDecimal;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Stream;
@@ -1202,6 +1220,117 @@ class DomainTransferRequestFlowTest
runTest("domain_transfer_request_fee.xml", UserPrivileges.SUPERUSER, RICH_DOMAIN_MAP);
}
@Test
void testSuccess_nonPremiumRenewalPrice_isReflectedInTransferCostAndCarriesOver()
throws Exception {
setupDomain("example", "tld");
PremiumList pl =
PremiumListDao.save(
new PremiumList.Builder()
.setCurrency(USD)
.setName("tld")
.setLabelsToPrices(ImmutableMap.of("example", new BigDecimal("67.89")))
.build());
persistResource(Registry.get("tld").asBuilder().setPremiumList(pl).build());
domain = loadByEntity(domain);
persistResource(
loadByKey(domain.getAutorenewBillingEvent())
.asBuilder()
.setRenewalPriceBehavior(RenewalPriceBehavior.NONPREMIUM)
.build());
DateTime now = clock.nowUtc();
// This ensures that the transfer has non-premium cost, as otherwise, the fee extension would be
// required to ack the premium price.
setEppInput("domain_transfer_request.xml");
eppLoader.replaceAll("JD1234-REP", contact.getRepoId());
runFlowAssertResponse(loadFile("domain_transfer_request_response.xml"));
domain = loadByEntity(domain);
DomainHistory requestHistory =
getOnlyHistoryEntryOfType(domain, DOMAIN_TRANSFER_REQUEST, DomainHistory.class);
// Check that the server approve billing recurrence (which will reify after 5 days if the
// transfer is not explicitly acked) maintains the non-premium behavior.
assertBillingEventsForResource(
domain,
new BillingEvent.OneTime.Builder()
.setBillingTime(now.plusDays(10)) // 5 day pending transfer + 5 day billing grace period
.setEventTime(now.plusDays(5))
.setRegistrarId("NewRegistrar")
.setCost(Money.of(USD, new BigDecimal("11.00")))
.setDomainHistory(requestHistory)
.setReason(Reason.TRANSFER)
.setPeriodYears(1)
.setTargetId("example.tld")
.build(),
getGainingClientAutorenewEvent()
.asBuilder()
.setRenewalPriceBehavior(RenewalPriceBehavior.NONPREMIUM)
.setDomainHistory(requestHistory)
.build(),
getLosingClientAutorenewEvent()
.asBuilder()
.setRecurrenceEndTime(now.plusDays(5))
.setRenewalPriceBehavior(RenewalPriceBehavior.NONPREMIUM)
.build());
}
@Test
void testSuccess_specifiedRenewalPrice_isReflectedInTransferCostAndCarriesOver()
throws Exception {
setupDomain("example", "tld");
PremiumList pl =
PremiumListDao.save(
new PremiumList.Builder()
.setCurrency(USD)
.setName("tld")
.setLabelsToPrices(ImmutableMap.of("example", new BigDecimal("67.89")))
.build());
persistResource(Registry.get("tld").asBuilder().setPremiumList(pl).build());
domain = loadByEntity(domain);
persistResource(
loadByKey(domain.getAutorenewBillingEvent())
.asBuilder()
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
.setRenewalPrice(Money.of(USD, new BigDecimal("18.79")))
.build());
DateTime now = clock.nowUtc();
setEppInput("domain_transfer_request.xml");
eppLoader.replaceAll("JD1234-REP", contact.getRepoId());
runFlowAssertResponse(loadFile("domain_transfer_request_response.xml"));
domain = loadByEntity(domain);
DomainHistory requestHistory =
getOnlyHistoryEntryOfType(domain, DOMAIN_TRANSFER_REQUEST, DomainHistory.class);
// Check that the server approve billing recurrence (which will reify after 5 days if the
// transfer is not explicitly acked) maintains the non-premium behavior.
assertBillingEventsForResource(
domain,
new BillingEvent.OneTime.Builder()
.setBillingTime(now.plusDays(10)) // 5 day pending transfer + 5 day billing grace period
.setEventTime(now.plusDays(5))
.setRegistrarId("NewRegistrar")
.setCost(Money.of(USD, new BigDecimal("18.79")))
.setDomainHistory(requestHistory)
.setReason(Reason.TRANSFER)
.setPeriodYears(1)
.setTargetId("example.tld")
.build(),
getGainingClientAutorenewEvent()
.asBuilder()
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
.setRenewalPrice(Money.of(USD, new BigDecimal("18.79")))
.setDomainHistory(requestHistory)
.build(),
getLosingClientAutorenewEvent()
.asBuilder()
.setRecurrenceEndTime(now.plusDays(5))
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
.setRenewalPrice(Money.of(USD, new BigDecimal("18.79")))
.build());
}
private void runWrongCurrencyTest(Map<String, String> substitutions) {
Map<String, String> fullSubstitutions = Maps.newHashMap();
fullSubstitutions.putAll(substitutions);
@@ -1560,4 +1689,120 @@ class DomainTransferRequestFlowTest
DomainTransactionRecord.create(
"tld", clock.nowUtc().plusDays(5), TRANSFER_SUCCESSFUL, 1));
}
@Test
void testSuccess_allocationToken() throws Exception {
setupDomain("example", "tld");
persistResource(
new AllocationToken.Builder()
.setToken("abc123")
.setTokenType(SINGLE_USE)
.setDomainName("example.tld")
.build());
doSuccessfulTest(
"domain_transfer_request_allocation_token.xml", "domain_transfer_request_response.xml");
}
@Test
void testFailure_invalidAllocationToken() throws Exception {
setupDomain("example", "tld");
setEppInput("domain_transfer_request_allocation_token.xml");
EppException thrown = assertThrows(InvalidAllocationTokenException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
void testFailure_allocationTokenIsForDifferentName() throws Exception {
setupDomain("example", "tld");
persistResource(
new AllocationToken.Builder()
.setToken("abc123")
.setTokenType(SINGLE_USE)
.setDomainName("otherdomain.tld")
.build());
setEppInput("domain_transfer_request_allocation_token.xml");
EppException thrown =
assertThrows(AllocationTokenNotValidForDomainException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
void testFailure_allocationTokenNotActive() throws Exception {
setupDomain("example", "tld");
persistResource(
new AllocationToken.Builder()
.setToken("abc123")
.setTokenType(UNLIMITED_USE)
.setDiscountFraction(0.5)
.setTokenStatusTransitions(
ImmutableSortedMap.<DateTime, TokenStatus>naturalOrder()
.put(START_OF_TIME, TokenStatus.NOT_STARTED)
.put(clock.nowUtc().plusDays(1), TokenStatus.VALID)
.put(clock.nowUtc().plusDays(60), TokenStatus.ENDED)
.build())
.build());
setEppInput("domain_transfer_request_allocation_token.xml");
EppException thrown = assertThrows(AllocationTokenNotInPromotionException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
void testFailure_allocationTokenNotValidForRegistrar() throws Exception {
setupDomain("example", "tld");
persistResource(
new AllocationToken.Builder()
.setToken("abc123")
.setTokenType(UNLIMITED_USE)
.setAllowedRegistrarIds(ImmutableSet.of("someClientId"))
.setDiscountFraction(0.5)
.setTokenStatusTransitions(
ImmutableSortedMap.<DateTime, TokenStatus>naturalOrder()
.put(START_OF_TIME, TokenStatus.NOT_STARTED)
.put(clock.nowUtc().minusDays(1), TokenStatus.VALID)
.put(clock.nowUtc().plusDays(1), TokenStatus.ENDED)
.build())
.build());
setEppInput("domain_transfer_request_allocation_token.xml");
EppException thrown =
assertThrows(AllocationTokenNotValidForRegistrarException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
void testFailure_allocationTokenNotValidForTld() throws Exception {
setupDomain("example", "tld");
persistResource(
new AllocationToken.Builder()
.setToken("abc123")
.setTokenType(UNLIMITED_USE)
.setAllowedTlds(ImmutableSet.of("example"))
.setDiscountFraction(0.5)
.setTokenStatusTransitions(
ImmutableSortedMap.<DateTime, TokenStatus>naturalOrder()
.put(START_OF_TIME, TokenStatus.NOT_STARTED)
.put(clock.nowUtc().minusDays(1), TokenStatus.VALID)
.put(clock.nowUtc().plusDays(1), TokenStatus.ENDED)
.build())
.build());
setEppInput("domain_transfer_request_allocation_token.xml");
EppException thrown = assertThrows(AllocationTokenNotValidForTldException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
void testFailure_allocationTokenAlreadyRedeemed() throws Exception {
setupDomain("example", "tld");
Domain domain = DatabaseHelper.newDomain("foo.tld");
Key<HistoryEntry> historyEntryKey = Key.create(Key.create(domain), HistoryEntry.class, 505L);
persistResource(
new AllocationToken.Builder()
.setToken("abc123")
.setTokenType(SINGLE_USE)
.setRedemptionHistoryEntry(HistoryEntry.createVKey(historyEntryKey))
.build());
setEppInput("domain_transfer_request_allocation_token.xml");
EppException thrown =
assertThrows(AlreadyRedeemedAllocationTokenException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
}

View File

@@ -99,7 +99,7 @@ import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.secdns.DelegationSignerData;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.eppcommon.Trid;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.model.poll.PendingActionNotificationResponse.DomainPendingActionNotificationResponse;
import google.registry.model.poll.PollMessage;
import google.registry.model.tld.Registry;
@@ -148,8 +148,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
}
private Domain persistDomainWithRegistrant() throws Exception {
HostResource host =
loadByForeignKey(HostResource.class, "ns1.example.foo", clock.nowUtc()).get();
Host host = loadByForeignKey(Host.class, "ns1.example.foo", clock.nowUtc()).get();
Domain domain =
persistResource(
DatabaseHelper.newDomain(getUniqueIdFromCommand())
@@ -174,8 +173,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
}
private Domain persistDomain() throws Exception {
HostResource host =
loadByForeignKey(HostResource.class, "ns1.example.foo", clock.nowUtc()).get();
Host host = loadByForeignKey(Host.class, "ns1.example.foo", clock.nowUtc()).get();
Domain domain =
persistResource(
DatabaseHelper.newDomain(getUniqueIdFromCommand())
@@ -289,12 +287,11 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
}
private void modifyDomainToHave13Nameservers() throws Exception {
ImmutableSet.Builder<VKey<HostResource>> nameservers = new ImmutableSet.Builder<>();
ImmutableSet.Builder<VKey<Host>> nameservers = new ImmutableSet.Builder<>();
for (int i = 1; i < 15; i++) {
if (i != 2) { // Skip 2 since that's the one that the tests will add.
nameservers.add(
loadByForeignKey(
HostResource.class, String.format("ns%d.example.foo", i), clock.nowUtc())
loadByForeignKey(Host.class, String.format("ns%d.example.foo", i), clock.nowUtc())
.get()
.createVKey());
}
@@ -318,9 +315,9 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
persistDomain();
setEppInput("domain_update_max_everything.xml");
// Create 26 hosts and 8 contacts. Start the domain with half of them.
ImmutableSet.Builder<VKey<HostResource>> nameservers = new ImmutableSet.Builder<>();
ImmutableSet.Builder<VKey<Host>> nameservers = new ImmutableSet.Builder<>();
for (int i = 0; i < 26; i++) {
HostResource host = persistActiveHost(String.format("max_test_%d.example.tld", i));
Host host = persistActiveHost(String.format("max_test_%d.example.tld", i));
if (i < 13) {
nameservers.add(host.createVKey());
}
@@ -394,7 +391,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
persistReferencedEntities();
Domain domain = persistDomain();
persistActiveSubordinateHost("ns1.example.tld", domain);
HostResource addedHost = persistActiveSubordinateHost("ns2.example.tld", domain);
Host addedHost = persistActiveSubordinateHost("ns2.example.tld", domain);
persistResource(
domain
.asBuilder()
@@ -402,7 +399,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
.addSubordinateHost("ns2.example.tld")
.setNameservers(
ImmutableSet.of(
loadByForeignKey(HostResource.class, "ns1.example.tld", clock.nowUtc())
loadByForeignKey(Host.class, "ns1.example.tld", clock.nowUtc())
.get()
.createVKey()))
.build());
@@ -412,9 +409,8 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
domain = reloadResourceByForeignKey();
assertThat(domain.getNameservers()).containsExactly(addedHost.createVKey());
assertThat(domain.getSubordinateHosts()).containsExactly("ns1.example.tld", "ns2.example.tld");
HostResource existingHost =
loadByForeignKey(HostResource.class, "ns1.example.tld", clock.nowUtc()).get();
addedHost = loadByForeignKey(HostResource.class, "ns2.example.tld", clock.nowUtc()).get();
Host existingHost = loadByForeignKey(Host.class, "ns1.example.tld", clock.nowUtc()).get();
addedHost = loadByForeignKey(Host.class, "ns2.example.tld", clock.nowUtc()).get();
assertThat(existingHost.getSuperordinateDomain()).isEqualTo(domain.createVKey());
assertThat(addedHost.getSuperordinateDomain()).isEqualTo(domain.createVKey());
}
@@ -1421,7 +1417,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
.asBuilder()
.setNameservers(
ImmutableSet.of(
loadByForeignKey(HostResource.class, "ns1.example.foo", clock.nowUtc())
loadByForeignKey(Host.class, "ns1.example.foo", clock.nowUtc())
.get()
.createVKey()))
.build());
@@ -1507,7 +1503,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
persistActiveContact("mak21");
persistActiveContact("sh8013");
persistResource(
loadByForeignKey(HostResource.class, "ns2.example.foo", clock.nowUtc())
loadByForeignKey(Host.class, "ns2.example.foo", clock.nowUtc())
.get()
.asBuilder()
.addStatusValue(StatusValue.PENDING_DELETE)
@@ -1562,15 +1558,11 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
.build());
assertThat(reloadResourceByForeignKey().getNameservers())
.doesNotContain(
loadByForeignKey(HostResource.class, "ns2.example.foo", clock.nowUtc())
.get()
.createVKey());
loadByForeignKey(Host.class, "ns2.example.foo", clock.nowUtc()).get().createVKey());
runFlow();
assertThat(reloadResourceByForeignKey().getNameservers())
.contains(
loadByForeignKey(HostResource.class, "ns2.example.foo", clock.nowUtc())
.get()
.createVKey());
loadByForeignKey(Host.class, "ns2.example.foo", clock.nowUtc()).get().createVKey());
}
@Test
@@ -1637,9 +1629,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
reloadResourceByForeignKey()
.asBuilder()
.addNameserver(
loadByForeignKey(HostResource.class, "ns2.example.foo", clock.nowUtc())
.get()
.createVKey())
loadByForeignKey(Host.class, "ns2.example.foo", clock.nowUtc()).get().createVKey())
.build());
persistResource(
Registry.get("tld")
@@ -1649,15 +1639,12 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
.build());
assertThat(reloadResourceByForeignKey().getNameservers())
.contains(
loadByForeignKey(HostResource.class, "ns1.example.foo", clock.nowUtc())
.get()
.createVKey());
loadByForeignKey(Host.class, "ns1.example.foo", clock.nowUtc()).get().createVKey());
clock.advanceOneMilli();
runFlow();
assertThat(reloadResourceByForeignKey().getNameservers())
.doesNotContain(
Key.create(
loadByForeignKey(HostResource.class, "ns1.example.foo", clock.nowUtc()).get()));
Key.create(loadByForeignKey(Host.class, "ns1.example.foo", clock.nowUtc()).get()));
}
@Test

View File

@@ -24,11 +24,11 @@ import google.registry.flows.EppException;
import google.registry.flows.FlowUtils.NotLoggedInException;
import google.registry.flows.ResourceCheckFlowTestCase;
import google.registry.flows.exceptions.TooManyResourceChecksException;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import org.junit.jupiter.api.Test;
/** Unit tests for {@link HostCheckFlow}. */
class HostCheckFlowTest extends ResourceCheckFlowTestCase<HostCheckFlow, HostResource> {
class HostCheckFlowTest extends ResourceCheckFlowTestCase<HostCheckFlow, Host> {
HostCheckFlowTest() {
setEppInput("host_check.xml");

View File

@@ -19,13 +19,13 @@ import static google.registry.model.EppResourceUtils.loadByForeignKey;
import static google.registry.testing.DatabaseHelper.assertNoBillingEvents;
import static google.registry.testing.DatabaseHelper.createTld;
import static google.registry.testing.DatabaseHelper.createTlds;
import static google.registry.testing.DatabaseHelper.newHostResource;
import static google.registry.testing.DatabaseHelper.newHost;
import static google.registry.testing.DatabaseHelper.persistActiveDomain;
import static google.registry.testing.DatabaseHelper.persistActiveHost;
import static google.registry.testing.DatabaseHelper.persistDeletedHost;
import static google.registry.testing.DatabaseHelper.persistResource;
import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptions;
import static google.registry.testing.HostResourceSubject.assertAboutHosts;
import static google.registry.testing.HostSubject.assertAboutHosts;
import static google.registry.testing.TaskQueueHelper.assertDnsTasksEnqueued;
import static google.registry.testing.TaskQueueHelper.assertNoDnsTasksEnqueued;
import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -51,14 +51,14 @@ import google.registry.flows.host.HostFlowUtils.SuperordinateDomainDoesNotExistE
import google.registry.flows.host.HostFlowUtils.SuperordinateDomainInPendingDeleteException;
import google.registry.model.domain.Domain;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.model.reporting.HistoryEntry;
import google.registry.testing.DatabaseHelper;
import org.joda.time.DateTime;
import org.junit.jupiter.api.Test;
/** Unit tests for {@link HostCreateFlow}. */
class HostCreateFlowTest extends ResourceFlowTestCase<HostCreateFlow, HostResource> {
class HostCreateFlowTest extends ResourceFlowTestCase<HostCreateFlow, Host> {
private void setEppHostCreateInput(String hostName, String hostAddrs) {
setEppInput(
@@ -83,7 +83,7 @@ class HostCreateFlowTest extends ResourceFlowTestCase<HostCreateFlow, HostResour
clock.advanceOneMilli();
assertTransactionalFlow(true);
runFlowAssertResponse(loadFile("host_create_response.xml"));
HostResource host = reloadResourceByForeignKey();
Host host = reloadResourceByForeignKey();
// Check that the host was created and persisted with a history entry.
assertAboutHosts()
.that(host)
@@ -124,7 +124,7 @@ class HostCreateFlowTest extends ResourceFlowTestCase<HostCreateFlow, HostResour
@Test
void testSuccess_internalNeverExisted() throws Exception {
doSuccessfulInternalTest("tld");
HostResource host = reloadResourceByForeignKey();
Host host = reloadResourceByForeignKey();
Domain superordinateDomain =
loadByForeignKey(Domain.class, "example.tld", clock.nowUtc()).get();
assertAboutHosts().that(host).hasSuperordinateDomain(superordinateDomain.createVKey());
@@ -153,7 +153,7 @@ class HostCreateFlowTest extends ResourceFlowTestCase<HostCreateFlow, HostResour
void testSuccess_internalExistedButWasDeleted() throws Exception {
persistDeletedHost(getUniqueIdFromCommand(), clock.nowUtc().minusDays(1));
doSuccessfulInternalTest("tld");
HostResource host = reloadResourceByForeignKey();
Host host = reloadResourceByForeignKey();
Domain superordinateDomain =
loadByForeignKey(Domain.class, "example.tld", clock.nowUtc()).get();
assertAboutHosts().that(host).hasSuperordinateDomain(superordinateDomain.createVKey());
@@ -223,7 +223,7 @@ class HostCreateFlowTest extends ResourceFlowTestCase<HostCreateFlow, HostResour
setEppHostCreateInput("ns1.example.tld", null);
String targetId = getUniqueIdFromCommand();
persistResource(
newHostResource(targetId)
newHost(targetId)
.asBuilder()
.setPersistedCurrentSponsorRegistrarId("NewRegistrar")
.build());

View File

@@ -19,12 +19,12 @@ import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_DELETE;
import static google.registry.testing.DatabaseHelper.assertNoBillingEvents;
import static google.registry.testing.DatabaseHelper.createTld;
import static google.registry.testing.DatabaseHelper.loadByKey;
import static google.registry.testing.DatabaseHelper.newHostResource;
import static google.registry.testing.DatabaseHelper.newHost;
import static google.registry.testing.DatabaseHelper.persistActiveHost;
import static google.registry.testing.DatabaseHelper.persistDeletedHost;
import static google.registry.testing.DatabaseHelper.persistResource;
import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptions;
import static google.registry.testing.HostResourceSubject.assertAboutHosts;
import static google.registry.testing.HostSubject.assertAboutHosts;
import static google.registry.testing.TaskQueueHelper.assertDnsTasksEnqueued;
import static google.registry.testing.TaskQueueHelper.assertNoDnsTasksEnqueued;
import static google.registry.testing.TaskQueueHelper.assertNoTasksEnqueued;
@@ -44,7 +44,7 @@ import google.registry.flows.host.HostFlowUtils.HostNameNotNormalizedException;
import google.registry.flows.host.HostFlowUtils.HostNameNotPunyCodedException;
import google.registry.model.domain.Domain;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.model.reporting.HistoryEntry.Type;
import google.registry.model.tld.Registry;
import google.registry.model.transfer.DomainTransferData;
@@ -55,7 +55,7 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
/** Unit tests for {@link HostDeleteFlow}. */
class HostDeleteFlowTest extends ResourceFlowTestCase<HostDeleteFlow, HostResource> {
class HostDeleteFlowTest extends ResourceFlowTestCase<HostDeleteFlow, Host> {
@BeforeEach
void initFlowTest() {
@@ -111,7 +111,7 @@ class HostDeleteFlowTest extends ResourceFlowTestCase<HostDeleteFlow, HostResour
private void doFailingStatusTest(StatusValue statusValue, Class<? extends Exception> exception) {
persistResource(
newHostResource("ns1.example.tld")
newHost("ns1.example.tld")
.asBuilder()
.setStatusValues(ImmutableSet.of(statusValue))
.build());
@@ -166,7 +166,7 @@ class HostDeleteFlowTest extends ResourceFlowTestCase<HostDeleteFlow, HostResour
.setPersistedCurrentSponsorRegistrarId("TheRegistrar")
.build());
persistResource(
newHostResource("ns1.example.tld")
newHost("ns1.example.tld")
.asBuilder()
.setPersistedCurrentSponsorRegistrarId("NewRegistrar") // Shouldn't hurt.
.setSuperordinateDomain(domain.createVKey())
@@ -187,7 +187,7 @@ class HostDeleteFlowTest extends ResourceFlowTestCase<HostDeleteFlow, HostResour
.setPersistedCurrentSponsorRegistrarId("NewRegistrar")
.build());
persistResource(
newHostResource("ns1.example.tld")
newHost("ns1.example.tld")
.asBuilder()
.setPersistedCurrentSponsorRegistrarId("TheRegistrar") // Shouldn't help.
.setSuperordinateDomain(domain.createVKey())
@@ -220,7 +220,7 @@ class HostDeleteFlowTest extends ResourceFlowTestCase<HostDeleteFlow, HostResour
.build())
.build());
persistResource(
newHostResource("ns1.example.tld")
newHost("ns1.example.tld")
.asBuilder()
.setPersistedCurrentSponsorRegistrarId("TheRegistrar") // Shouldn't hurt.
.setSuperordinateDomain(domain.createVKey())
@@ -254,7 +254,7 @@ class HostDeleteFlowTest extends ResourceFlowTestCase<HostDeleteFlow, HostResour
.build())
.build());
persistResource(
newHostResource("ns1.example.tld")
newHost("ns1.example.tld")
.asBuilder()
.setPersistedCurrentSponsorRegistrarId("NewRegistrar") // Shouldn't help.
.setSuperordinateDomain(domain.createVKey())
@@ -307,7 +307,7 @@ class HostDeleteFlowTest extends ResourceFlowTestCase<HostDeleteFlow, HostResour
private void assertSqlDeleteSuccess(boolean isSubordinate) throws Exception {
assertThat(reloadResourceByForeignKey()).isNull();
HostResource deletedHost = reloadResourceByForeignKey(clock.nowUtc().minusMillis(1));
Host deletedHost = reloadResourceByForeignKey(clock.nowUtc().minusMillis(1));
assertAboutHosts()
.that(deletedHost)
.isNotActiveAt(clock.nowUtc())

View File

@@ -35,7 +35,7 @@ import google.registry.flows.host.HostFlowUtils.HostNameNotNormalizedException;
import google.registry.flows.host.HostFlowUtils.HostNameNotPunyCodedException;
import google.registry.model.domain.Domain;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.host.HostResource;
import google.registry.model.host.Host;
import google.registry.testing.DatabaseHelper;
import javax.annotation.Nullable;
import org.joda.time.DateTime;
@@ -43,7 +43,7 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
/** Unit tests for {@link HostInfoFlow}. */
class HostInfoFlowTest extends ResourceFlowTestCase<HostInfoFlow, HostResource> {
class HostInfoFlowTest extends ResourceFlowTestCase<HostInfoFlow, Host> {
@BeforeEach
void initHostTest() {
@@ -51,9 +51,9 @@ class HostInfoFlowTest extends ResourceFlowTestCase<HostInfoFlow, HostResource>
setEppInput("host_info.xml", ImmutableMap.of("HOSTNAME", "ns1.example.tld"));
}
private HostResource persistHostResource() throws Exception {
private Host persistHost() throws Exception {
return persistResource(
new HostResource.Builder()
new Host.Builder()
.setHostName(getUniqueIdFromCommand())
.setRepoId("1FF-FOOBAR")
.setPersistedCurrentSponsorRegistrarId("my sponsor")
@@ -81,7 +81,7 @@ class HostInfoFlowTest extends ResourceFlowTestCase<HostInfoFlow, HostResource>
@Test
void testSuccess() throws Exception {
persistHostResource();
persistHost();
assertTransactionalFlow(false);
// Check that the persisted host info was returned.
runFlowAssertResponse(
@@ -94,11 +94,11 @@ class HostInfoFlowTest extends ResourceFlowTestCase<HostInfoFlow, HostResource>
@Test
void testSuccess_linked() throws Exception {
persistHostResource();
persistHost();
persistResource(
DatabaseHelper.newDomain("example.foobar")
.asBuilder()
.addNameserver(persistHostResource().createVKey())
.addNameserver(persistHost().createVKey())
.build());
assertTransactionalFlow(false);
// Check that the persisted host info was returned.
@@ -121,7 +121,7 @@ class HostInfoFlowTest extends ResourceFlowTestCase<HostInfoFlow, HostResource>
.setLastTransferTime(domainTransferTime)
.setPersistedCurrentSponsorRegistrarId("superclientid")
.build());
HostResource firstHost = persistHostResource();
Host firstHost = persistHost();
persistResource(
firstHost
.asBuilder()
@@ -166,8 +166,7 @@ class HostInfoFlowTest extends ResourceFlowTestCase<HostInfoFlow, HostResource>
@Test
void testFailure_existedButWasDeleted() throws Exception {
persistResource(
persistHostResource().asBuilder().setDeletionTime(clock.nowUtc().minusDays(1)).build());
persistResource(persistHost().asBuilder().setDeletionTime(clock.nowUtc().minusDays(1)).build());
ResourceDoesNotExistException thrown =
assertThrows(ResourceDoesNotExistException.class, this::runFlow);
assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand()));
@@ -197,7 +196,7 @@ class HostInfoFlowTest extends ResourceFlowTestCase<HostInfoFlow, HostResource>
@Test
void testIcannActivityReportField_getsLogged() throws Exception {
persistHostResource();
persistHost();
runFlow();
assertIcannReportingActivityFieldLogged("srs-host-info");
}

Some files were not shown because too many files have changed in this diff Show More