mirror of
https://github.com/google/nomulus
synced 2026-08-04 06:16:12 +00:00
Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
49ade014ab | ||
|
|
b8d901effe | ||
|
|
23520048dc | ||
|
|
37ed6c925c | ||
|
|
17a21f3326 | ||
|
|
f623da9948 | ||
|
|
ddc4a615db | ||
|
|
06a1fc0022 | ||
|
|
eec272b6ba | ||
|
|
3d5b52b853 |
@@ -29,7 +29,7 @@ import google.registry.config.RegistryEnvironment;
|
||||
import google.registry.flows.poll.PollFlowUtils;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.EppResourceUtils;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
@@ -43,8 +43,8 @@ import google.registry.util.Clock;
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Hard deletes load-test ContactResources, Hosts, their subordinate history entries, and the
|
||||
* associated ForeignKey and EppResourceIndex entities.
|
||||
* Hard deletes load-test Contacts, 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
|
||||
@@ -92,7 +92,7 @@ public class DeleteLoadTestDataAction implements Runnable {
|
||||
tm().transact(
|
||||
() -> {
|
||||
LOAD_TEST_REGISTRARS.forEach(this::deletePollMessages);
|
||||
tm().loadAllOfStream(ContactResource.class).forEach(this::deleteContact);
|
||||
tm().loadAllOfStream(Contact.class).forEach(this::deleteContact);
|
||||
tm().loadAllOfStream(Host.class).forEach(this::deleteHost);
|
||||
});
|
||||
}
|
||||
@@ -108,7 +108,7 @@ public class DeleteLoadTestDataAction implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteContact(ContactResource contact) {
|
||||
private void deleteContact(Contact contact) {
|
||||
if (!LOAD_TEST_REGISTRARS.contains(contact.getPersistedCurrentSponsorRegistrarId())) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ package google.registry.beam.common;
|
||||
import static com.google.common.base.Verify.verify;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.persistence.transaction.CriteriaQueryBuilder;
|
||||
import google.registry.persistence.transaction.JpaTransactionManager;
|
||||
import java.io.Serializable;
|
||||
@@ -46,8 +46,7 @@ public class JpaDemoPipeline implements Serializable {
|
||||
.apply(
|
||||
"Read contacts",
|
||||
RegistryJpaIO.read(
|
||||
() -> CriteriaQueryBuilder.create(ContactResource.class).build(),
|
||||
ContactResource::getRepoId))
|
||||
() -> CriteriaQueryBuilder.create(Contact.class).build(), Contact::getRepoId))
|
||||
.apply(
|
||||
"Count Contacts",
|
||||
ParDo.of(
|
||||
|
||||
@@ -45,8 +45,8 @@ import google.registry.config.CredentialModule;
|
||||
import google.registry.config.RegistryConfig.ConfigModule;
|
||||
import google.registry.gcs.GcsUtils;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
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;
|
||||
@@ -140,7 +140,7 @@ import org.joda.time.DateTime;
|
||||
* pairs of (contact/host repo ID: pending deposit) for all RDE pending deposits for further
|
||||
* processing.
|
||||
*
|
||||
* <h3>{@link ContactResource}</h3>
|
||||
* <h3>{@link Contact}</h3>
|
||||
*
|
||||
* We first join most recent contact histories, represented by (contact repo ID: contact history
|
||||
* revision ID) pairs, with referenced contacts, represented by (contact repo ID: pending deposit)
|
||||
@@ -150,13 +150,13 @@ import org.joda.time.DateTime;
|
||||
*
|
||||
* <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
|
||||
* contacts and obtain the (pending deposit: deposit fragment) pairs. For subordinate hosts, we need
|
||||
* to find the superordinate domain in order to properly handle pending transfer in the deposit as
|
||||
* well. So we first find the superordinate domain repo ID from the host and join the (superordinate
|
||||
* domain repo ID: (subordinate host repo ID: (pending deposit: revision ID))) pair with the (domain
|
||||
* repo ID: revision ID) pair obtained from the domain history query in order to map the host at
|
||||
* Similar to {@link Contact}, 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 contacts
|
||||
* and obtain the (pending deposit: deposit fragment) pairs. For subordinate hosts, we need to find
|
||||
* the superordinate domain in order to properly handle pending transfer in the deposit as well. So
|
||||
* we first find the superordinate domain repo ID from the host and join the (superordinate domain
|
||||
* repo ID: (subordinate host repo ID: (pending deposit: revision ID))) pair with the (domain repo
|
||||
* ID: revision ID) pair obtained from the domain history query in order to map the host at
|
||||
* watermark to the domain at watermark. We then proceed to create the (pending deposit: deposit
|
||||
* fragment) pair for subordinate hosts using the added domain information.
|
||||
*
|
||||
@@ -466,10 +466,10 @@ public class RdePipeline implements Serializable {
|
||||
private PCollectionTuple processDomainHistories(PCollection<KV<String, Long>> domainHistories) {
|
||||
Counter activeDomainCounter = Metrics.counter("RDE", "ActiveDomainBase");
|
||||
Counter domainFragmentCounter = Metrics.counter("RDE", "DomainFragment");
|
||||
Counter referencedContactCounter = Metrics.counter("RDE", "ReferencedContactResource");
|
||||
Counter referencedContactCounter = Metrics.counter("RDE", "ReferencedContact");
|
||||
Counter referencedHostCounter = Metrics.counter("RDE", "ReferencedHost");
|
||||
return domainHistories.apply(
|
||||
"Map DomainHistory to DepositFragment " + "and emit referenced ContactResource and Host",
|
||||
"Map DomainHistory to DepositFragment " + "and emit referenced Contact and Host",
|
||||
ParDo.of(
|
||||
new DoFn<KV<String, Long>, KV<PendingDeposit, DepositFragment>>() {
|
||||
@ProcessElement
|
||||
@@ -533,17 +533,17 @@ public class RdePipeline implements Serializable {
|
||||
PCollection<KV<String, PendingDeposit>> referencedContacts,
|
||||
PCollection<KV<String, Long>> contactHistories) {
|
||||
Counter contactFragmentCounter = Metrics.counter("RDE", "ContactFragment");
|
||||
return removeUnreferencedResource(referencedContacts, contactHistories, ContactResource.class)
|
||||
return removeUnreferencedResource(referencedContacts, contactHistories, Contact.class)
|
||||
.apply(
|
||||
"Map ContactResource to DepositFragment",
|
||||
"Map Contact to DepositFragment",
|
||||
FlatMapElements.into(
|
||||
kvs(
|
||||
TypeDescriptor.of(PendingDeposit.class),
|
||||
TypeDescriptor.of(DepositFragment.class)))
|
||||
.via(
|
||||
(KV<String, CoGbkResult> kv) -> {
|
||||
ContactResource contact =
|
||||
(ContactResource)
|
||||
Contact contact =
|
||||
(Contact)
|
||||
loadResourceByHistoryEntryId(
|
||||
ContactHistory.class,
|
||||
kv.getKey(),
|
||||
|
||||
@@ -22,7 +22,7 @@ import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.beam.common.RegistryJpaIO;
|
||||
import google.registry.beam.common.RegistryJpaIO.Read;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.host.Host;
|
||||
@@ -53,7 +53,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, Host.class);
|
||||
ImmutableSet.of(Contact.class, Domain.class, Host.class);
|
||||
|
||||
/**
|
||||
* There exist three possible situations where we know we'll want to project domains to the
|
||||
@@ -99,13 +99,13 @@ public class ResaveAllEppResourcesPipeline implements Serializable {
|
||||
|
||||
/** Projects to the current time and saves any contacts with expired transfers. */
|
||||
private void fastResaveContacts(Pipeline pipeline) {
|
||||
Read<ContactResource, ContactResource> read =
|
||||
Read<Contact, Contact> read =
|
||||
RegistryJpaIO.read(
|
||||
"FROM Contact WHERE transferData.transferStatus = 'PENDING' AND"
|
||||
+ " transferData.pendingTransferExpirationTime < current_timestamp()",
|
||||
ContactResource.class,
|
||||
Contact.class,
|
||||
c -> c);
|
||||
projectAndResaveResources(pipeline, ContactResource.class, read);
|
||||
projectAndResaveResources(pipeline, Contact.class, read);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
<datastore-indexes autoGenerate="false">
|
||||
<!-- For finding contact resources by registrar. -->
|
||||
<datastore-index kind="ContactResource" ancestor="false" source="manual">
|
||||
<datastore-index kind="Contact" ancestor="false" source="manual">
|
||||
<property name="currentSponsorClientId" direction="asc"/>
|
||||
<property name="deletionTime" direction="asc"/>
|
||||
<property name="searchName" direction="asc"/>
|
||||
@@ -91,7 +91,7 @@
|
||||
<property name="deletionTime" direction="asc"/>
|
||||
<property name="fullyQualifiedHostName" direction="asc"/>
|
||||
</datastore-index>
|
||||
<datastore-index kind="ContactResource" ancestor="false" source="manual">
|
||||
<datastore-index kind="Contact" ancestor="false" source="manual">
|
||||
<property name="deletionTime" direction="asc"/>
|
||||
<property name="searchName" direction="asc"/>
|
||||
</datastore-index>
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
<name>dns-publish</name>
|
||||
<rate>100/s</rate>
|
||||
<bucket-size>100</bucket-size>
|
||||
<!-- 30 sec backoff increasing linearly up to 10 minutes. -->
|
||||
<!-- 30 sec backoff increasing linearly up to 30 minutes. -->
|
||||
<retry-parameters>
|
||||
<min-backoff-seconds>30</min-backoff-seconds>
|
||||
<max-backoff-seconds>600</max-backoff-seconds>
|
||||
<max-backoff-seconds>1800</max-backoff-seconds>
|
||||
<max-doublings>0</max-doublings>
|
||||
</retry-parameters>
|
||||
</queue>
|
||||
|
||||
@@ -38,7 +38,7 @@ import google.registry.flows.exceptions.TooManyResourceChecksException;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.EppResource.ForeignKeyedEppResource;
|
||||
import google.registry.model.EppResource.ResourceWithTransferData;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.domain.Period;
|
||||
@@ -139,7 +139,7 @@ public final class ResourceFlowUtils {
|
||||
}
|
||||
|
||||
/** Check that the given AuthInfo is either missing or else is valid for the given resource. */
|
||||
public static void verifyOptionalAuthInfo(Optional<AuthInfo> authInfo, ContactResource contact)
|
||||
public static void verifyOptionalAuthInfo(Optional<AuthInfo> authInfo, Contact contact)
|
||||
throws EppException {
|
||||
if (authInfo.isPresent()) {
|
||||
verifyAuthInfo(authInfo.get(), contact);
|
||||
@@ -167,7 +167,7 @@ public final class ResourceFlowUtils {
|
||||
return;
|
||||
}
|
||||
// The roid should match one of the contacts.
|
||||
Optional<VKey<ContactResource>> foundContact =
|
||||
Optional<VKey<Contact>> foundContact =
|
||||
domain.getReferencedContacts().stream()
|
||||
.filter(key -> key.getSqlKey().equals(authRepoId))
|
||||
.findFirst();
|
||||
@@ -179,8 +179,7 @@ public final class ResourceFlowUtils {
|
||||
}
|
||||
|
||||
/** Check that the given {@link AuthInfo} is valid for the given contact. */
|
||||
public static void verifyAuthInfo(AuthInfo authInfo, ContactResource contact)
|
||||
throws EppException {
|
||||
public static void verifyAuthInfo(AuthInfo authInfo, Contact contact) throws EppException {
|
||||
String authRepoId = authInfo.getPw().getRepoId();
|
||||
String authPassword = authInfo.getPw().getValue();
|
||||
String contactPassword = contact.getAuthInfo().getPw().getValue();
|
||||
|
||||
@@ -26,8 +26,8 @@ import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.Flow;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.annotations.ReportingSpec;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactCommand.Check;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.eppinput.ResourceCommand;
|
||||
import google.registry.model.eppoutput.CheckData.ContactCheck;
|
||||
import google.registry.model.eppoutput.CheckData.ContactCheckData;
|
||||
@@ -62,7 +62,7 @@ public final class ContactCheckFlow implements Flow {
|
||||
ImmutableList<String> targetIds = ((Check) resourceCommand).getTargetIds();
|
||||
verifyTargetIdCount(targetIds, maxChecks);
|
||||
ImmutableSet<String> existingIds =
|
||||
checkResourcesExist(ContactResource.class, targetIds, clock.nowUtc());
|
||||
checkResourcesExist(Contact.class, targetIds, clock.nowUtc());
|
||||
ImmutableList.Builder<ContactCheck> checks = new ImmutableList.Builder<>();
|
||||
for (String id : targetIds) {
|
||||
boolean unused = !existingIds.contains(id);
|
||||
|
||||
@@ -33,9 +33,9 @@ import google.registry.flows.TransactionalFlow;
|
||||
import google.registry.flows.annotations.ReportingSpec;
|
||||
import google.registry.flows.exceptions.ResourceAlreadyExistsForThisClientException;
|
||||
import google.registry.flows.exceptions.ResourceCreateContentionException;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactCommand.Create;
|
||||
import google.registry.model.contact.ContactHistory;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.metadata.MetadataExtension;
|
||||
import google.registry.model.eppinput.ResourceCommand;
|
||||
import google.registry.model.eppoutput.CreateData.ContactCreateData;
|
||||
@@ -75,9 +75,9 @@ public final class ContactCreateFlow implements TransactionalFlow {
|
||||
extensionManager.validate();
|
||||
Create command = (Create) resourceCommand;
|
||||
DateTime now = tm().getTransactionTime();
|
||||
verifyResourceDoesNotExist(ContactResource.class, targetId, now, registrarId);
|
||||
ContactResource newContact =
|
||||
new ContactResource.Builder()
|
||||
verifyResourceDoesNotExist(Contact.class, targetId, now, registrarId);
|
||||
Contact newContact =
|
||||
new Contact.Builder()
|
||||
.setContactId(targetId)
|
||||
.setAuthInfo(command.getAuthInfo())
|
||||
.setCreationRegistrarId(registrarId)
|
||||
|
||||
@@ -35,8 +35,8 @@ 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.contact.Contact;
|
||||
import google.registry.model.contact.ContactHistory;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.metadata.MetadataExtension;
|
||||
import google.registry.model.eppcommon.AuthInfo;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
@@ -91,15 +91,15 @@ public final class ContactDeleteFlow implements TransactionalFlow {
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
extensionManager.validate();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
checkLinkedDomains(targetId, now, ContactResource.class);
|
||||
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
||||
checkLinkedDomains(targetId, now, Contact.class);
|
||||
Contact existingContact = loadAndVerifyExistence(Contact.class, targetId, now);
|
||||
verifyNoDisallowedStatuses(existingContact, DISALLOWED_STATUSES);
|
||||
verifyOptionalAuthInfo(authInfo, existingContact);
|
||||
if (!isSuperuser) {
|
||||
verifyResourceOwnership(registrarId, existingContact);
|
||||
}
|
||||
// Handle pending transfers on contact deletion.
|
||||
ContactResource newContact =
|
||||
Contact newContact =
|
||||
existingContact.getStatusValues().contains(StatusValue.PENDING_TRANSFER)
|
||||
? denyPendingTransfer(existingContact, SERVER_CANCELLED, now, registrarId)
|
||||
: existingContact;
|
||||
|
||||
@@ -24,10 +24,10 @@ import com.googlecode.objectify.Key;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.ParameterValuePolicyErrorException;
|
||||
import google.registry.flows.EppException.ParameterValueSyntaxErrorException;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactAddress;
|
||||
import google.registry.model.contact.ContactHistory;
|
||||
import google.registry.model.contact.ContactHistory.ContactHistoryId;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.PostalInfo;
|
||||
import google.registry.model.poll.PendingActionNotificationResponse.ContactPendingActionNotificationResponse;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
@@ -61,7 +61,7 @@ public class ContactFlowUtils {
|
||||
}
|
||||
|
||||
/** Check contact's state against server policy. */
|
||||
static void validateContactAgainstPolicy(ContactResource contact) throws EppException {
|
||||
static void validateContactAgainstPolicy(Contact contact) throws EppException {
|
||||
if (contact.getDisclose() != null && !contact.getDisclose().getFlag()) {
|
||||
throw new DeclineContactDisclosureFieldDisallowedPolicyException();
|
||||
}
|
||||
|
||||
@@ -27,8 +27,8 @@ import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.Superuser;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.annotations.ReportingSpec;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactInfoData;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.eppcommon.AuthInfo;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.eppoutput.EppResponse;
|
||||
@@ -69,7 +69,7 @@ public final class ContactInfoFlow implements Flow {
|
||||
DateTime now = clock.nowUtc();
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
extensionManager.validate(); // There are no legal extensions for this flow.
|
||||
ContactResource contact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
||||
Contact contact = loadAndVerifyExistence(Contact.class, targetId, now);
|
||||
if (!isSuperuser) {
|
||||
verifyResourceOwnership(registrarId, contact);
|
||||
}
|
||||
|
||||
@@ -33,8 +33,8 @@ import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.TransactionalFlow;
|
||||
import google.registry.flows.annotations.ReportingSpec;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactHistory;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.metadata.MetadataExtension;
|
||||
import google.registry.model.eppcommon.AuthInfo;
|
||||
import google.registry.model.eppinput.ResourceCommand;
|
||||
@@ -74,7 +74,7 @@ public final class ContactTransferApproveFlow implements TransactionalFlow {
|
||||
|
||||
/**
|
||||
* The logic in this flow, which handles client approvals, very closely parallels the logic in
|
||||
* {@link ContactResource#cloneProjectedAtTime} which handles implicit server approvals.
|
||||
* {@link Contact#cloneProjectedAtTime} which handles implicit server approvals.
|
||||
*/
|
||||
@Override
|
||||
public EppResponse run() throws EppException {
|
||||
@@ -82,11 +82,11 @@ public final class ContactTransferApproveFlow implements TransactionalFlow {
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
extensionManager.validate();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
||||
Contact existingContact = loadAndVerifyExistence(Contact.class, targetId, now);
|
||||
verifyOptionalAuthInfo(authInfo, existingContact);
|
||||
verifyHasPendingTransfer(existingContact);
|
||||
verifyResourceOwnership(registrarId, existingContact);
|
||||
ContactResource newContact =
|
||||
Contact newContact =
|
||||
approvePendingTransfer(existingContact, TransferStatus.CLIENT_APPROVED, now);
|
||||
ContactHistory contactHistory =
|
||||
historyBuilder.setType(CONTACT_TRANSFER_APPROVE).setContact(newContact).build();
|
||||
|
||||
@@ -33,8 +33,8 @@ import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.TransactionalFlow;
|
||||
import google.registry.flows.annotations.ReportingSpec;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactHistory;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.metadata.MetadataExtension;
|
||||
import google.registry.model.eppcommon.AuthInfo;
|
||||
import google.registry.model.eppinput.ResourceCommand;
|
||||
@@ -78,11 +78,11 @@ public final class ContactTransferCancelFlow implements TransactionalFlow {
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
extensionManager.validate();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
||||
Contact existingContact = loadAndVerifyExistence(Contact.class, targetId, now);
|
||||
verifyOptionalAuthInfo(authInfo, existingContact);
|
||||
verifyHasPendingTransfer(existingContact);
|
||||
verifyTransferInitiator(registrarId, existingContact);
|
||||
ContactResource newContact =
|
||||
Contact newContact =
|
||||
denyPendingTransfer(existingContact, TransferStatus.CLIENT_CANCELLED, now, registrarId);
|
||||
ContactHistory contactHistory =
|
||||
historyBuilder.setType(CONTACT_TRANSFER_CANCEL).setContact(newContact).build();
|
||||
|
||||
@@ -27,7 +27,7 @@ import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.annotations.ReportingSpec;
|
||||
import google.registry.flows.exceptions.NoTransferHistoryToQueryException;
|
||||
import google.registry.flows.exceptions.NotAuthorizedToViewTransferException;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.eppcommon.AuthInfo;
|
||||
import google.registry.model.eppoutput.EppResponse;
|
||||
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
|
||||
@@ -66,8 +66,7 @@ public final class ContactTransferQueryFlow implements Flow {
|
||||
public EppResponse run() throws EppException {
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
extensionManager.validate(); // There are no legal extensions for this flow.
|
||||
ContactResource contact =
|
||||
loadAndVerifyExistence(ContactResource.class, targetId, clock.nowUtc());
|
||||
Contact contact = loadAndVerifyExistence(Contact.class, targetId, clock.nowUtc());
|
||||
verifyOptionalAuthInfo(authInfo, contact);
|
||||
// Most of the fields on the transfer response are required, so there's no way to return valid
|
||||
// XML if the object has never been transferred (and hence the fields aren't populated).
|
||||
|
||||
@@ -33,8 +33,8 @@ import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.TransactionalFlow;
|
||||
import google.registry.flows.annotations.ReportingSpec;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactHistory;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.metadata.MetadataExtension;
|
||||
import google.registry.model.eppcommon.AuthInfo;
|
||||
import google.registry.model.eppoutput.EppResponse;
|
||||
@@ -76,11 +76,11 @@ public final class ContactTransferRejectFlow implements TransactionalFlow {
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
extensionManager.validate();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
||||
Contact existingContact = loadAndVerifyExistence(Contact.class, targetId, now);
|
||||
verifyOptionalAuthInfo(authInfo, existingContact);
|
||||
verifyHasPendingTransfer(existingContact);
|
||||
verifyResourceOwnership(registrarId, existingContact);
|
||||
ContactResource newContact =
|
||||
Contact newContact =
|
||||
denyPendingTransfer(existingContact, TransferStatus.CLIENT_REJECTED, now, registrarId);
|
||||
ContactHistory contactHistory =
|
||||
historyBuilder.setType(CONTACT_TRANSFER_REJECT).setContact(newContact).build();
|
||||
|
||||
@@ -38,8 +38,8 @@ import google.registry.flows.TransactionalFlow;
|
||||
import google.registry.flows.annotations.ReportingSpec;
|
||||
import google.registry.flows.exceptions.AlreadyPendingTransferException;
|
||||
import google.registry.flows.exceptions.ObjectAlreadySponsoredException;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactHistory;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.metadata.MetadataExtension;
|
||||
import google.registry.model.eppcommon.AuthInfo;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
@@ -96,7 +96,7 @@ public final class ContactTransferRequestFlow implements TransactionalFlow {
|
||||
validateRegistrarIsLoggedIn(gainingClientId);
|
||||
extensionManager.validate();
|
||||
DateTime now = tm().getTransactionTime();
|
||||
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
||||
Contact existingContact = loadAndVerifyExistence(Contact.class, targetId, now);
|
||||
verifyAuthInfoPresentForResourceTransfer(authInfo);
|
||||
verifyAuthInfo(authInfo.get(), existingContact);
|
||||
// Verify that the resource does not already have a pending transfer.
|
||||
@@ -146,10 +146,12 @@ public final class ContactTransferRequestFlow implements TransactionalFlow {
|
||||
.asBuilder()
|
||||
.setEventTime(now) // Unlike the serverApprove messages, this applies immediately.
|
||||
.build();
|
||||
ContactResource newContact = existingContact.asBuilder()
|
||||
.setTransferData(pendingTransferData)
|
||||
.addStatusValue(StatusValue.PENDING_TRANSFER)
|
||||
.build();
|
||||
Contact newContact =
|
||||
existingContact
|
||||
.asBuilder()
|
||||
.setTransferData(pendingTransferData)
|
||||
.addStatusValue(StatusValue.PENDING_TRANSFER)
|
||||
.build();
|
||||
tm().update(newContact);
|
||||
tm().insertAll(
|
||||
ImmutableSet.of(
|
||||
|
||||
@@ -36,10 +36,10 @@ import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.TransactionalFlow;
|
||||
import google.registry.flows.annotations.ReportingSpec;
|
||||
import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactCommand.Update;
|
||||
import google.registry.model.contact.ContactCommand.Update.Change;
|
||||
import google.registry.model.contact.ContactHistory;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.PostalInfo;
|
||||
import google.registry.model.domain.metadata.MetadataExtension;
|
||||
import google.registry.model.eppcommon.AuthInfo;
|
||||
@@ -94,7 +94,7 @@ public final class ContactUpdateFlow implements TransactionalFlow {
|
||||
extensionManager.validate();
|
||||
Update command = (Update) resourceCommand;
|
||||
DateTime now = tm().getTransactionTime();
|
||||
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
|
||||
Contact existingContact = loadAndVerifyExistence(Contact.class, targetId, now);
|
||||
verifyOptionalAuthInfo(authInfo, existingContact);
|
||||
ImmutableSet<StatusValue> statusToRemove = command.getInnerRemove().getStatusValues();
|
||||
ImmutableSet<StatusValue> statusesToAdd = command.getInnerAdd().getStatusValues();
|
||||
@@ -104,7 +104,7 @@ public final class ContactUpdateFlow implements TransactionalFlow {
|
||||
}
|
||||
verifyNoDisallowedStatuses(existingContact, DISALLOWED_STATUSES);
|
||||
checkSameValuesNotAddedAndRemoved(statusesToAdd, statusToRemove);
|
||||
ContactResource.Builder builder = existingContact.asBuilder();
|
||||
Contact.Builder builder = existingContact.asBuilder();
|
||||
Change change = command.getInnerChange();
|
||||
// The spec requires the following behaviors:
|
||||
// * If you update part of a postal info, the fields that you didn't update are unchanged.
|
||||
@@ -126,7 +126,7 @@ public final class ContactUpdateFlow implements TransactionalFlow {
|
||||
builder.setInternationalizedPostalInfo(null);
|
||||
}
|
||||
}
|
||||
ContactResource newContact =
|
||||
Contact newContact =
|
||||
builder
|
||||
.setLastEppUpdateTime(now)
|
||||
.setLastEppUpdateRegistrarId(registrarId)
|
||||
|
||||
@@ -79,7 +79,7 @@ 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.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.domain.DesignatedContact;
|
||||
import google.registry.model.domain.DesignatedContact.Type;
|
||||
import google.registry.model.domain.Domain;
|
||||
@@ -380,9 +380,7 @@ public class DomainFlowUtils {
|
||||
|
||||
/** Verify that no linked resources have disallowed statuses. */
|
||||
static void verifyNotInPendingDelete(
|
||||
Set<DesignatedContact> contacts,
|
||||
VKey<ContactResource> registrant,
|
||||
Set<VKey<Host>> nameservers)
|
||||
Set<DesignatedContact> contacts, VKey<Contact> registrant, Set<VKey<Host>> nameservers)
|
||||
throws EppException {
|
||||
ImmutableList.Builder<VKey<? extends EppResource>> keysToLoad = new ImmutableList.Builder<>();
|
||||
contacts.stream().map(DesignatedContact::getContactKey).forEach(keysToLoad::add);
|
||||
@@ -427,7 +425,7 @@ public class DomainFlowUtils {
|
||||
|
||||
static void validateNoDuplicateContacts(Set<DesignatedContact> contacts)
|
||||
throws ParameterValuePolicyErrorException {
|
||||
ImmutableMultimap<Type, VKey<ContactResource>> contactsByType =
|
||||
ImmutableMultimap<Type, VKey<Contact>> contactsByType =
|
||||
contacts.stream()
|
||||
.collect(
|
||||
toImmutableSetMultimap(
|
||||
@@ -436,15 +434,13 @@ public class DomainFlowUtils {
|
||||
// If any contact type has multiple contacts:
|
||||
if (contactsByType.asMap().values().stream().anyMatch(v -> v.size() > 1)) {
|
||||
// Find the duplicates.
|
||||
Map<Type, Collection<VKey<ContactResource>>> dupeKeysMap =
|
||||
Map<Type, Collection<VKey<Contact>>> dupeKeysMap =
|
||||
Maps.filterEntries(contactsByType.asMap(), e -> e.getValue().size() > 1);
|
||||
ImmutableList<VKey<ContactResource>> dupeKeys =
|
||||
ImmutableList<VKey<Contact>> dupeKeys =
|
||||
dupeKeysMap.values().stream().flatMap(Collection::stream).collect(toImmutableList());
|
||||
// Load the duplicates in one batch.
|
||||
Map<VKey<? extends ContactResource>, ContactResource> dupeContacts =
|
||||
tm().loadByKeys(dupeKeys);
|
||||
ImmutableMultimap.Builder<Type, VKey<ContactResource>> typesMap =
|
||||
new ImmutableMultimap.Builder<>();
|
||||
Map<VKey<? extends Contact>, Contact> dupeContacts = tm().loadByKeys(dupeKeys);
|
||||
ImmutableMultimap.Builder<Type, VKey<Contact>> typesMap = new ImmutableMultimap.Builder<>();
|
||||
dupeKeysMap.forEach(typesMap::putAll);
|
||||
// Create an error message showing the type and contact IDs of the duplicates.
|
||||
throw new DuplicateContactForRoleException(
|
||||
@@ -453,7 +449,7 @@ public class DomainFlowUtils {
|
||||
}
|
||||
|
||||
static void validateRequiredContactsPresent(
|
||||
@Nullable VKey<ContactResource> registrant, Set<DesignatedContact> contacts)
|
||||
@Nullable VKey<Contact> registrant, Set<DesignatedContact> contacts)
|
||||
throws RequiredParameterMissingException {
|
||||
if (registrant == null) {
|
||||
throw new MissingRegistrantException();
|
||||
|
||||
@@ -30,6 +30,7 @@ import google.registry.flows.EppException;
|
||||
import google.registry.flows.ExtensionManager;
|
||||
import google.registry.flows.Flow;
|
||||
import google.registry.flows.FlowModule.RegistrarId;
|
||||
import google.registry.flows.FlowModule.Superuser;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.annotations.ReportingSpec;
|
||||
import google.registry.flows.custom.DomainInfoFlowCustomLogic;
|
||||
@@ -42,6 +43,8 @@ import google.registry.model.domain.DomainCommand.Info.HostsRequest;
|
||||
import google.registry.model.domain.DomainInfoData;
|
||||
import google.registry.model.domain.fee06.FeeInfoCommandExtensionV06;
|
||||
import google.registry.model.domain.fee06.FeeInfoResponseExtensionV06;
|
||||
import google.registry.model.domain.packagetoken.PackageTokenExtension;
|
||||
import google.registry.model.domain.packagetoken.PackageTokenResponseExtension;
|
||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||
import google.registry.model.domain.rgp.RgpInfoExtension;
|
||||
import google.registry.model.eppcommon.AuthInfo;
|
||||
@@ -85,13 +88,14 @@ public final class DomainInfoFlow implements Flow {
|
||||
@Inject EppResponse.Builder responseBuilder;
|
||||
@Inject DomainInfoFlowCustomLogic flowCustomLogic;
|
||||
@Inject DomainPricingLogic pricingLogic;
|
||||
@Inject @Superuser boolean isSuperuser;
|
||||
|
||||
@Inject
|
||||
DomainInfoFlow() {}
|
||||
|
||||
@Override
|
||||
public EppResponse run() throws EppException {
|
||||
extensionManager.register(FeeInfoCommandExtensionV06.class);
|
||||
extensionManager.register(FeeInfoCommandExtensionV06.class, PackageTokenExtension.class);
|
||||
flowCustomLogic.beforeValidation();
|
||||
validateRegistrarIsLoggedIn(registrarId);
|
||||
extensionManager.validate();
|
||||
@@ -150,6 +154,15 @@ public final class DomainInfoFlow implements Flow {
|
||||
if (!gracePeriodStatuses.isEmpty()) {
|
||||
extensions.add(RgpInfoExtension.create(gracePeriodStatuses));
|
||||
}
|
||||
Optional<PackageTokenExtension> packageInfo =
|
||||
eppInput.getSingleExtension(PackageTokenExtension.class);
|
||||
if (packageInfo.isPresent()) {
|
||||
// Package info was requested.
|
||||
if (isSuperuser || registrarId.equals(domain.getCurrentSponsorRegistrarId())) {
|
||||
// Only show package info to owning registrar or superusers
|
||||
extensions.add(PackageTokenResponseExtension.create(domain.getCurrentPackageToken()));
|
||||
}
|
||||
}
|
||||
Optional<FeeInfoCommandExtensionV06> feeInfo =
|
||||
eppInput.getSingleExtension(FeeInfoCommandExtensionV06.class);
|
||||
if (feeInfo.isPresent()) { // Fee check was requested.
|
||||
|
||||
@@ -30,6 +30,8 @@ import static google.registry.flows.domain.DomainFlowUtils.validateFeeChallenge;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.validateRegistrationPeriod;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.verifyRegistrarIsActive;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears;
|
||||
import static google.registry.flows.domain.token.AllocationTokenFlowUtils.maybeApplyPackageRemovalToken;
|
||||
import static google.registry.flows.domain.token.AllocationTokenFlowUtils.verifyTokenAllowedOnDomain;
|
||||
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_RENEW;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.DateTimeUtils.leapSafeAddYears;
|
||||
@@ -119,6 +121,10 @@ import org.joda.time.Duration;
|
||||
* @error {@link DomainFlowUtils.UnsupportedFeeAttributeException}
|
||||
* @error {@link DomainRenewFlow.IncorrectCurrentExpirationDateException}
|
||||
* @error {@link
|
||||
* google.registry.flows.domain.token.AllocationTokenFlowUtils.MissingRemovePackageTokenOnPackageDomainException}
|
||||
* @error {@link
|
||||
* google.registry.flows.domain.token.AllocationTokenFlowUtils.RemovePackageTokenOnNonPackageDomainException}
|
||||
* @error {@link
|
||||
* google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForDomainException}
|
||||
* @error {@link
|
||||
* google.registry.flows.domain.token.AllocationTokenFlowUtils.InvalidAllocationTokenException}
|
||||
@@ -174,7 +180,11 @@ public final class DomainRenewFlow implements TransactionalFlow {
|
||||
registrarId,
|
||||
now,
|
||||
eppInput.getSingleExtension(AllocationTokenExtension.class));
|
||||
verifyRenewAllowed(authInfo, existingDomain, command);
|
||||
verifyRenewAllowed(authInfo, existingDomain, command, allocationToken);
|
||||
|
||||
// If client passed an applicable static token this updates the domain
|
||||
existingDomain = maybeApplyPackageRemovalToken(existingDomain, allocationToken);
|
||||
|
||||
int years = command.getPeriod().getValue();
|
||||
DateTime newExpirationTime =
|
||||
leapSafeAddYears(existingDomain.getRegistrationExpirationTime(), years); // Uncapped
|
||||
@@ -302,7 +312,11 @@ public final class DomainRenewFlow implements TransactionalFlow {
|
||||
.build();
|
||||
}
|
||||
|
||||
private void verifyRenewAllowed(Optional<AuthInfo> authInfo, Domain existingDomain, Renew command)
|
||||
private void verifyRenewAllowed(
|
||||
Optional<AuthInfo> authInfo,
|
||||
Domain existingDomain,
|
||||
Renew command,
|
||||
Optional<AllocationToken> allocationToken)
|
||||
throws EppException {
|
||||
verifyOptionalAuthInfo(authInfo, existingDomain);
|
||||
verifyNoDisallowedStatuses(existingDomain, RENEW_DISALLOWED_STATUSES);
|
||||
@@ -312,6 +326,8 @@ public final class DomainRenewFlow implements TransactionalFlow {
|
||||
checkHasBillingAccount(registrarId, existingDomain.getTld());
|
||||
}
|
||||
verifyUnitIsYears(command.getPeriod());
|
||||
// We only allow __REMOVE_PACKAGE__ token on promo package domains for now
|
||||
verifyTokenAllowedOnDomain(existingDomain, allocationToken);
|
||||
// If the date they specify doesn't match the expiration, fail. (This is an idempotence check).
|
||||
if (!command.getCurrentExpirationDate().equals(
|
||||
existingDomain.getRegistrationExpirationTime().toLocalDate())) {
|
||||
@@ -333,7 +349,11 @@ public final class DomainRenewFlow implements TransactionalFlow {
|
||||
.setPeriodYears(years)
|
||||
.setCost(renewCost)
|
||||
.setEventTime(now)
|
||||
.setAllocationToken(allocationToken.map(AllocationToken::createVKey).orElse(null))
|
||||
.setAllocationToken(
|
||||
allocationToken
|
||||
.filter(t -> AllocationToken.TokenBehavior.DEFAULT.equals(t.getTokenBehavior()))
|
||||
.map(AllocationToken::createVKey)
|
||||
.orElse(null))
|
||||
.setBillingTime(now.plus(Registry.get(tld).getRenewGracePeriodLength()))
|
||||
.setDomainHistoryId(
|
||||
new DomainHistoryId(domainHistoryKey.getParent().getName(), domainHistoryKey.getId()))
|
||||
|
||||
+93
-19
@@ -15,6 +15,7 @@
|
||||
package google.registry.flows.domain.token;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
@@ -26,9 +27,12 @@ import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.AssociationProhibitsOperationException;
|
||||
import google.registry.flows.EppException.AuthorizationErrorException;
|
||||
import google.registry.flows.EppException.StatusProhibitsOperationException;
|
||||
import google.registry.model.billing.BillingEvent.Recurring;
|
||||
import google.registry.model.billing.BillingEvent.RenewalPriceBehavior;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainCommand;
|
||||
import google.registry.model.domain.token.AllocationToken;
|
||||
import google.registry.model.domain.token.AllocationToken.TokenBehavior;
|
||||
import google.registry.model.domain.token.AllocationToken.TokenStatus;
|
||||
import google.registry.model.domain.token.AllocationToken.TokenType;
|
||||
import google.registry.model.domain.token.AllocationTokenExtension;
|
||||
@@ -109,23 +113,27 @@ public class AllocationTokenFlowUtils {
|
||||
private void validateToken(
|
||||
InternetDomainName domainName, AllocationToken token, String registrarId, DateTime now)
|
||||
throws EppException {
|
||||
if (!token.getAllowedRegistrarIds().isEmpty()
|
||||
&& !token.getAllowedRegistrarIds().contains(registrarId)) {
|
||||
throw new AllocationTokenNotValidForRegistrarException();
|
||||
}
|
||||
if (!token.getAllowedTlds().isEmpty()
|
||||
&& !token.getAllowedTlds().contains(domainName.parent().toString())) {
|
||||
throw new AllocationTokenNotValidForTldException();
|
||||
}
|
||||
if (token.getDomainName().isPresent()
|
||||
&& !token.getDomainName().get().equals(domainName.toString())) {
|
||||
throw new AllocationTokenNotValidForDomainException();
|
||||
}
|
||||
// Tokens without status transitions will just have a single-entry NOT_STARTED map, so only
|
||||
// check the status transitions map if it's non-trivial.
|
||||
if (token.getTokenStatusTransitions().size() > 1
|
||||
&& !TokenStatus.VALID.equals(token.getTokenStatusTransitions().getValueAtTime(now))) {
|
||||
throw new AllocationTokenNotInPromotionException();
|
||||
|
||||
// Only tokens with default behavior require validation
|
||||
if (TokenBehavior.DEFAULT.equals(token.getTokenBehavior())) {
|
||||
if (!token.getAllowedRegistrarIds().isEmpty()
|
||||
&& !token.getAllowedRegistrarIds().contains(registrarId)) {
|
||||
throw new AllocationTokenNotValidForRegistrarException();
|
||||
}
|
||||
if (!token.getAllowedTlds().isEmpty()
|
||||
&& !token.getAllowedTlds().contains(domainName.parent().toString())) {
|
||||
throw new AllocationTokenNotValidForTldException();
|
||||
}
|
||||
if (token.getDomainName().isPresent()
|
||||
&& !token.getDomainName().get().equals(domainName.toString())) {
|
||||
throw new AllocationTokenNotValidForDomainException();
|
||||
}
|
||||
// Tokens without status transitions will just have a single-entry NOT_STARTED map, so only
|
||||
// check the status transitions map if it's non-trivial.
|
||||
if (token.getTokenStatusTransitions().size() > 1
|
||||
&& !TokenStatus.VALID.equals(token.getTokenStatusTransitions().getValueAtTime(now))) {
|
||||
throw new AllocationTokenNotInPromotionException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,8 +145,15 @@ public class AllocationTokenFlowUtils {
|
||||
// See https://tools.ietf.org/html/draft-ietf-regext-allocation-token-04#section-2.1
|
||||
throw new InvalidAllocationTokenException();
|
||||
}
|
||||
Optional<AllocationToken> maybeTokenEntity =
|
||||
tm().transact(() -> tm().loadByKeyIfPresent(VKey.create(AllocationToken.class, token)));
|
||||
|
||||
Optional<AllocationToken> maybeTokenEntity = AllocationToken.maybeGetStaticTokenInstance(token);
|
||||
if (maybeTokenEntity.isPresent()) {
|
||||
return maybeTokenEntity.get();
|
||||
}
|
||||
|
||||
maybeTokenEntity =
|
||||
tm().transact(() -> tm().loadByKeyIfPresent(VKey.createSql(AllocationToken.class, token)));
|
||||
|
||||
if (!maybeTokenEntity.isPresent()) {
|
||||
throw new InvalidAllocationTokenException();
|
||||
}
|
||||
@@ -187,6 +202,49 @@ public class AllocationTokenFlowUtils {
|
||||
tokenCustomLogic.validateToken(existingDomain, tokenEntity, registry, registrarId, now));
|
||||
}
|
||||
|
||||
public static void verifyTokenAllowedOnDomain(
|
||||
Domain domain, Optional<AllocationToken> allocationToken) throws EppException {
|
||||
|
||||
boolean domainHasPackageToken = domain.getCurrentPackageToken().isPresent();
|
||||
boolean hasRemovePackageToken =
|
||||
allocationToken.isPresent()
|
||||
&& TokenBehavior.REMOVE_PACKAGE.equals(allocationToken.get().getTokenBehavior());
|
||||
|
||||
if (hasRemovePackageToken && !domainHasPackageToken) {
|
||||
throw new RemovePackageTokenOnNonPackageDomainException();
|
||||
} else if (!hasRemovePackageToken && domainHasPackageToken) {
|
||||
throw new MissingRemovePackageTokenOnPackageDomainException();
|
||||
}
|
||||
}
|
||||
|
||||
public static Domain maybeApplyPackageRemovalToken(
|
||||
Domain domain, Optional<AllocationToken> allocationToken) {
|
||||
if (!allocationToken.isPresent()
|
||||
|| !TokenBehavior.REMOVE_PACKAGE.equals(allocationToken.get().getTokenBehavior())) {
|
||||
return domain;
|
||||
}
|
||||
|
||||
Recurring newRecurringBillingEvent =
|
||||
tm().loadByKey(domain.getAutorenewBillingEvent())
|
||||
.asBuilder()
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.DEFAULT)
|
||||
.setRenewalPrice(null)
|
||||
.build();
|
||||
|
||||
// the Recurring billing event is reloaded later in the renew flow, so we synchronize changed
|
||||
// RecurringBillingEvent with storage manually
|
||||
tm().put(newRecurringBillingEvent);
|
||||
jpaTm().getEntityManager().flush();
|
||||
jpaTm().getEntityManager().clear();
|
||||
|
||||
// Remove current package token
|
||||
return domain
|
||||
.asBuilder()
|
||||
.setCurrentPackageToken(null)
|
||||
.setAutorenewBillingEvent(newRecurringBillingEvent.createVKey())
|
||||
.build();
|
||||
}
|
||||
|
||||
// Note: exception messages should be <= 32 characters long for domain check results
|
||||
|
||||
/** The allocation token is not currently valid. */
|
||||
@@ -234,4 +292,20 @@ public class AllocationTokenFlowUtils {
|
||||
super("The allocation token is invalid");
|
||||
}
|
||||
}
|
||||
|
||||
/** The __REMOVEPACKAGE__ token is missing on a renew package domain command */
|
||||
public static class MissingRemovePackageTokenOnPackageDomainException
|
||||
extends AssociationProhibitsOperationException {
|
||||
MissingRemovePackageTokenOnPackageDomainException() {
|
||||
super("Domains that are inside packages cannot be explicitly renewed");
|
||||
}
|
||||
}
|
||||
|
||||
/** The __REMOVEPACKAGE__ token is not allowed on non package domains */
|
||||
public static class RemovePackageTokenOnNonPackageDomainException
|
||||
extends AssociationProhibitsOperationException {
|
||||
RemovePackageTokenOnNonPackageDomainException() {
|
||||
super("__REMOVEPACKAGE__ token is not allowed on non package domains");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,20 +18,16 @@ import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.common.EntityGroupRoot;
|
||||
import google.registry.model.common.GaeUserIdConverter;
|
||||
import google.registry.model.contact.Contact;
|
||||
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.domain.token.AllocationToken;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.model.host.HostHistory;
|
||||
import google.registry.model.index.EppResourceIndex;
|
||||
import google.registry.model.index.EppResourceIndexBucket;
|
||||
import google.registry.model.index.ForeignKeyIndex;
|
||||
import google.registry.model.rde.RdeRevision;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.server.Lock;
|
||||
import google.registry.model.server.ServerSecret;
|
||||
|
||||
/** Sets of classes of the Objectify-registered entities in use throughout the model. */
|
||||
@@ -41,9 +37,8 @@ public final class EntityClasses {
|
||||
/** Set of entity classes. */
|
||||
public static final ImmutableSet<Class<? extends ImmutableObject>> ALL_CLASSES =
|
||||
ImmutableSet.of(
|
||||
AllocationToken.class,
|
||||
Contact.class,
|
||||
ContactHistory.class,
|
||||
ContactResource.class,
|
||||
Domain.class,
|
||||
DomainHistory.class,
|
||||
EntityGroupRoot.class,
|
||||
@@ -56,9 +51,6 @@ public final class EntityClasses {
|
||||
HistoryEntry.class,
|
||||
Host.class,
|
||||
HostHistory.class,
|
||||
Lock.class,
|
||||
RdeRevision.class,
|
||||
Registrar.class,
|
||||
ServerSecret.class);
|
||||
|
||||
private EntityClasses() {}
|
||||
|
||||
@@ -32,7 +32,7 @@ import google.registry.config.RegistryConfig;
|
||||
import google.registry.model.EppResource.BuilderWithTransferData;
|
||||
import google.registry.model.EppResource.ForeignKeyedEppResource;
|
||||
import google.registry.model.EppResource.ResourceWithTransferData;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.host.Host;
|
||||
@@ -345,10 +345,10 @@ 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(Host.class),
|
||||
"key must be either VKey<ContactResource> or VKey<Host>, but it is %s",
|
||||
key.getKind().equals(Contact.class) || key.getKind().equals(Host.class),
|
||||
"key must be either VKey<Contact> or VKey<Host>, but it is %s",
|
||||
key);
|
||||
boolean isContactKey = key.getKind().equals(ContactResource.class);
|
||||
boolean isContactKey = key.getKind().equals(Contact.class);
|
||||
if (tm().isOfy()) {
|
||||
com.googlecode.objectify.cmd.Query<Domain> query =
|
||||
auditedOfy()
|
||||
|
||||
@@ -257,7 +257,7 @@ public abstract class ImmutableObject implements Cloneable {
|
||||
return (Map<String, Object>) toMapRecursive(this);
|
||||
}
|
||||
|
||||
public VKey createVKey() {
|
||||
public VKey<? extends ImmutableObject> createVKey() {
|
||||
throw new UnsupportedOperationException("VKey creation is not supported for this entity");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import com.google.common.collect.Sets;
|
||||
import google.registry.model.EppResource.BuilderWithTransferData;
|
||||
import google.registry.model.EppResource.ForeignKeyedEppResource;
|
||||
import google.registry.model.EppResource.ResourceWithTransferData;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
@@ -60,7 +60,7 @@ public final class ResourceTransferUtils {
|
||||
EppResource eppResource, TransferData transferData) {
|
||||
assertIsContactOrDomain(eppResource);
|
||||
TransferResponse.Builder<? extends TransferResponse, ?> builder;
|
||||
if (eppResource instanceof ContactResource) {
|
||||
if (eppResource instanceof Contact) {
|
||||
builder = new ContactTransferResponse.Builder().setContactId(eppResource.getForeignKey());
|
||||
} else {
|
||||
DomainTransferData domainTransferData = (DomainTransferData) transferData;
|
||||
@@ -93,7 +93,7 @@ public final class ResourceTransferUtils {
|
||||
boolean actionResult,
|
||||
DateTime processedDate) {
|
||||
assertIsContactOrDomain(eppResource);
|
||||
return eppResource instanceof ContactResource
|
||||
return eppResource instanceof Contact
|
||||
? ContactPendingActionNotificationResponse.create(
|
||||
eppResource.getForeignKey(), actionResult, transferRequestTrid, processedDate)
|
||||
: DomainPendingActionNotificationResponse.create(
|
||||
@@ -101,7 +101,7 @@ public final class ResourceTransferUtils {
|
||||
}
|
||||
|
||||
private static void assertIsContactOrDomain(EppResource eppResource) {
|
||||
checkState(eppResource instanceof ContactResource || eppResource instanceof Domain);
|
||||
checkState(eppResource instanceof Contact || eppResource instanceof Domain);
|
||||
}
|
||||
|
||||
/** Update the relevant {@link ForeignKeyIndex} to cache the new deletion time. */
|
||||
|
||||
@@ -212,6 +212,9 @@ public abstract class BillingEvent extends ImmutableObject
|
||||
return nullToEmptyImmutableCopy(flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract VKey<? extends BillingEvent> createVKey();
|
||||
|
||||
/** Override Buildable.asBuilder() to give this method stronger typing. */
|
||||
@Override
|
||||
public abstract Builder<?, ?> asBuilder();
|
||||
|
||||
+19
-16
@@ -15,7 +15,6 @@
|
||||
package google.registry.model.contact;
|
||||
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import google.registry.model.EppResource.ForeignKeyedEppResource;
|
||||
import google.registry.model.annotations.ExternalMessagingName;
|
||||
import google.registry.model.annotations.ReportedOn;
|
||||
@@ -23,6 +22,10 @@ import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.WithStringVKey;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.Table;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/**
|
||||
@@ -32,35 +35,35 @@ import org.joda.time.DateTime;
|
||||
*/
|
||||
@ReportedOn
|
||||
@Entity
|
||||
@javax.persistence.Entity(name = "Contact")
|
||||
@javax.persistence.Table(
|
||||
@com.googlecode.objectify.annotation.Entity
|
||||
@Table(
|
||||
name = "Contact",
|
||||
indexes = {
|
||||
@javax.persistence.Index(columnList = "creationTime"),
|
||||
@javax.persistence.Index(columnList = "currentSponsorRegistrarId"),
|
||||
@javax.persistence.Index(columnList = "deletionTime"),
|
||||
@javax.persistence.Index(columnList = "contactId"),
|
||||
@javax.persistence.Index(columnList = "searchName")
|
||||
@Index(columnList = "creationTime"),
|
||||
@Index(columnList = "currentSponsorRegistrarId"),
|
||||
@Index(columnList = "deletionTime"),
|
||||
@Index(columnList = "contactId"),
|
||||
@Index(columnList = "searchName")
|
||||
})
|
||||
@ExternalMessagingName("contact")
|
||||
@WithStringVKey
|
||||
@Access(AccessType.FIELD)
|
||||
public class ContactResource extends ContactBase implements ForeignKeyedEppResource {
|
||||
public class Contact extends ContactBase implements ForeignKeyedEppResource {
|
||||
|
||||
@Override
|
||||
public VKey<ContactResource> createVKey() {
|
||||
return VKey.create(ContactResource.class, getRepoId(), Key.create(this));
|
||||
public VKey<Contact> createVKey() {
|
||||
return VKey.create(Contact.class, getRepoId(), Key.create(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
@javax.persistence.Id
|
||||
@Id
|
||||
@Access(AccessType.PROPERTY)
|
||||
public String getRepoId() {
|
||||
return super.getRepoId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContactResource cloneProjectedAtTime(DateTime now) {
|
||||
public Contact cloneProjectedAtTime(DateTime now) {
|
||||
return ContactBase.cloneContactProjectedAtTime(this, now);
|
||||
}
|
||||
|
||||
@@ -69,12 +72,12 @@ public class ContactResource extends ContactBase implements ForeignKeyedEppResou
|
||||
return new Builder(clone(this));
|
||||
}
|
||||
|
||||
/** A builder for constructing {@link ContactResource}, since it is immutable. */
|
||||
public static class Builder extends ContactBase.Builder<ContactResource, Builder> {
|
||||
/** A builder for constructing {@link Contact}, since it is immutable. */
|
||||
public static class Builder extends ContactBase.Builder<Contact, Builder> {
|
||||
|
||||
public Builder() {}
|
||||
|
||||
private Builder(ContactResource instance) {
|
||||
private Builder(Contact instance) {
|
||||
super(instance);
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ public class ContactBase extends EppResource implements ResourceWithTransferData
|
||||
|
||||
/**
|
||||
* Localized postal info for the contact. All contained values must be representable in the 7-bit
|
||||
* US-ASCII character set. Personal info; cleared by {@link ContactResource.Builder#wipeOut}.
|
||||
* US-ASCII character set. Personal info; cleared by {@link Contact.Builder#wipeOut}.
|
||||
*/
|
||||
@Ignore
|
||||
@Embedded
|
||||
@@ -95,7 +95,7 @@ public class ContactBase extends EppResource implements ResourceWithTransferData
|
||||
|
||||
/**
|
||||
* Internationalized postal info for the contact. Personal info; cleared by {@link
|
||||
* ContactResource.Builder#wipeOut}.
|
||||
* Contact.Builder#wipeOut}.
|
||||
*/
|
||||
@Ignore
|
||||
@Embedded
|
||||
@@ -124,11 +124,11 @@ public class ContactBase extends EppResource implements ResourceWithTransferData
|
||||
/**
|
||||
* Contact name used for name searches. This is set automatically to be the internationalized
|
||||
* postal name, or if null, the localized postal name, or if that is null as well, null. Personal
|
||||
* info; cleared by {@link ContactResource.Builder#wipeOut}.
|
||||
* info; cleared by {@link Contact.Builder#wipeOut}.
|
||||
*/
|
||||
@Index String searchName;
|
||||
|
||||
/** Contact’s voice number. Personal info; cleared by {@link ContactResource.Builder#wipeOut}. */
|
||||
/** Contact’s voice number. Personal info; cleared by {@link Contact.Builder#wipeOut}. */
|
||||
@IgnoreSave(IfNull.class)
|
||||
@Embedded
|
||||
@AttributeOverrides({
|
||||
@@ -137,7 +137,7 @@ public class ContactBase extends EppResource implements ResourceWithTransferData
|
||||
})
|
||||
ContactPhoneNumber voice;
|
||||
|
||||
/** Contact’s fax number. Personal info; cleared by {@link ContactResource.Builder#wipeOut}. */
|
||||
/** Contact’s fax number. Personal info; cleared by {@link Contact.Builder#wipeOut}. */
|
||||
@IgnoreSave(IfNull.class)
|
||||
@Embedded
|
||||
@AttributeOverrides({
|
||||
@@ -146,7 +146,7 @@ public class ContactBase extends EppResource implements ResourceWithTransferData
|
||||
})
|
||||
ContactPhoneNumber fax;
|
||||
|
||||
/** Contact’s email address. Personal info; cleared by {@link ContactResource.Builder#wipeOut}. */
|
||||
/** Contact’s email address. Personal info; cleared by {@link Contact.Builder#wipeOut}. */
|
||||
@IgnoreSave(IfNull.class)
|
||||
String email;
|
||||
|
||||
@@ -188,7 +188,7 @@ public class ContactBase extends EppResource implements ResourceWithTransferData
|
||||
public VKey<? extends ContactBase> createVKey() {
|
||||
throw new UnsupportedOperationException(
|
||||
"ContactBase is not an actual persisted entity you can create a key to;"
|
||||
+ " use ContactResource instead");
|
||||
+ " use Contact instead");
|
||||
}
|
||||
|
||||
@OnLoad
|
||||
@@ -292,7 +292,7 @@ public class ContactBase extends EppResource implements ResourceWithTransferData
|
||||
return new Builder<>(clone(this));
|
||||
}
|
||||
|
||||
/** A builder for constructing {@link ContactResource}, since it is immutable. */
|
||||
/** A builder for constructing {@link Contact}, since it is immutable. */
|
||||
public static class Builder<T extends ContactBase, B extends Builder<T, B>>
|
||||
extends EppResource.Builder<T, B> implements BuilderWithTransferData<ContactTransferData, B> {
|
||||
|
||||
|
||||
@@ -34,13 +34,13 @@ import javax.xml.bind.annotation.XmlType;
|
||||
import javax.xml.bind.annotation.adapters.CollapsedStringAdapter;
|
||||
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
|
||||
/** A collection of {@link ContactResource} commands. */
|
||||
/** A collection of {@link Contact} commands. */
|
||||
public class ContactCommand {
|
||||
|
||||
/** The fields on "chgType" from <a href="http://tools.ietf.org/html/rfc5733">RFC5733</a>. */
|
||||
@XmlTransient
|
||||
public static class ContactCreateOrChange extends ImmutableObject
|
||||
implements ResourceCreateOrChange<ContactResource.Builder> {
|
||||
implements ResourceCreateOrChange<Contact.Builder> {
|
||||
|
||||
/** Postal info for the contact. */
|
||||
List<PostalInfo> postalInfo;
|
||||
@@ -111,13 +111,13 @@ public class ContactCommand {
|
||||
}
|
||||
|
||||
/**
|
||||
* A create command for a {@link ContactResource}, mapping "createType" from <a
|
||||
* A create command for a {@link Contact}, mapping "createType" from <a
|
||||
* href="http://tools.ietf.org/html/rfc5733">RFC5733</a>}.
|
||||
*/
|
||||
@XmlType(propOrder = {"contactId", "postalInfo", "voice", "fax", "email", "authInfo", "disclose"})
|
||||
@XmlRootElement
|
||||
public static class Create extends ContactCreateOrChange
|
||||
implements SingleResourceCommand, ResourceCreateOrChange<ContactResource.Builder> {
|
||||
implements SingleResourceCommand, ResourceCreateOrChange<Contact.Builder> {
|
||||
/**
|
||||
* Unique identifier for this contact.
|
||||
*
|
||||
@@ -139,29 +139,29 @@ public class ContactCommand {
|
||||
}
|
||||
}
|
||||
|
||||
/** A delete command for a {@link ContactResource}. */
|
||||
/** A delete command for a {@link Contact}. */
|
||||
@XmlRootElement
|
||||
public static class Delete extends AbstractSingleResourceCommand {}
|
||||
|
||||
/** An info request for a {@link ContactResource}. */
|
||||
/** An info request for a {@link Contact}. */
|
||||
@XmlRootElement
|
||||
@XmlType(propOrder = {"targetId", "authInfo"})
|
||||
public static class Info extends AbstractContactAuthCommand {}
|
||||
|
||||
/** A check request for {@link ContactResource}. */
|
||||
/** A check request for {@link Contact}. */
|
||||
@XmlRootElement
|
||||
public static class Check extends ResourceCheck {}
|
||||
|
||||
/** A transfer operation for a {@link ContactResource}. */
|
||||
/** A transfer operation for a {@link Contact}. */
|
||||
@XmlRootElement
|
||||
@XmlType(propOrder = {"targetId", "authInfo"})
|
||||
public static class Transfer extends AbstractContactAuthCommand {}
|
||||
|
||||
/** An update to a {@link ContactResource}. */
|
||||
/** An update to a {@link Contact}. */
|
||||
@XmlRootElement
|
||||
@XmlType(propOrder = {"targetId", "innerAdd", "innerRemove", "innerChange"})
|
||||
public static class Update
|
||||
extends ResourceUpdate<Update.AddRemove, ContactResource.Builder, Update.Change> {
|
||||
extends ResourceUpdate<Update.AddRemove, Contact.Builder, Update.Change> {
|
||||
|
||||
@XmlElement(name = "chg")
|
||||
protected Change innerChange;
|
||||
|
||||
@@ -58,7 +58,7 @@ import javax.persistence.PostLoad;
|
||||
@IdClass(ContactHistoryId.class)
|
||||
public class ContactHistory extends HistoryEntry implements UnsafeSerializable {
|
||||
|
||||
// Store ContactBase instead of ContactResource so we don't pick up its @Id
|
||||
// Store ContactBase instead of Contact so we don't pick up its @Id
|
||||
// Nullable for the sake of pre-Registry-3.0 history objects
|
||||
@DoNotCompare @Nullable ContactBase contactBase;
|
||||
|
||||
@@ -73,7 +73,7 @@ public class ContactHistory extends HistoryEntry implements UnsafeSerializable {
|
||||
/** This method is private because it is only used by Hibernate. */
|
||||
@SuppressWarnings("unused")
|
||||
private void setContactRepoId(String contactRepoId) {
|
||||
parent = Key.create(ContactResource.class, contactRepoId);
|
||||
parent = Key.create(Contact.class, contactRepoId);
|
||||
}
|
||||
|
||||
@Id
|
||||
@@ -98,9 +98,9 @@ public class ContactHistory extends HistoryEntry implements UnsafeSerializable {
|
||||
return Optional.ofNullable(contactBase);
|
||||
}
|
||||
|
||||
/** The key to the {@link ContactResource} this is based off of. */
|
||||
public VKey<ContactResource> getParentVKey() {
|
||||
return VKey.create(ContactResource.class, getContactRepoId());
|
||||
/** The key to the {@link Contact} this is based off of. */
|
||||
public VKey<Contact> getParentVKey() {
|
||||
return VKey.create(Contact.class, getContactRepoId());
|
||||
}
|
||||
|
||||
/** Creates a {@link VKey} instance for this entity. */
|
||||
@@ -112,8 +112,7 @@ public class ContactHistory extends HistoryEntry implements UnsafeSerializable {
|
||||
|
||||
@Override
|
||||
public Optional<? extends EppResource> getResourceAtPointInTime() {
|
||||
return getContactBase()
|
||||
.map(contactBase -> new ContactResource.Builder().copyFrom(contactBase).build());
|
||||
return getContactBase().map(contactBase -> new Contact.Builder().copyFrom(contactBase).build());
|
||||
}
|
||||
|
||||
@PostLoad
|
||||
@@ -210,7 +209,7 @@ public class ContactHistory extends HistoryEntry implements UnsafeSerializable {
|
||||
}
|
||||
|
||||
public Builder setContactRepoId(String contactRepoId) {
|
||||
getInstance().parent = Key.create(ContactResource.class, contactRepoId);
|
||||
getInstance().parent = Key.create(Contact.class, contactRepoId);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,11 +21,11 @@ import javax.persistence.Embeddable;
|
||||
/**
|
||||
* EPP Contact Phone Number
|
||||
*
|
||||
* <p>This class is embedded inside a {@link ContactResource} hold the phone number of an EPP
|
||||
* contact. The fields are all defined in the parent class {@link PhoneNumber}, but the subclass is
|
||||
* still necessary to pick up the contact namespace.
|
||||
* <p>This class is embedded inside a {@link Contact} hold the phone number of an EPP contact. The
|
||||
* fields are all defined in the parent class {@link PhoneNumber}, but the subclass is still
|
||||
* necessary to pick up the contact namespace.
|
||||
*
|
||||
* @see ContactResource
|
||||
* @see Contact
|
||||
*/
|
||||
@Embed
|
||||
@Embeddable
|
||||
|
||||
@@ -22,7 +22,7 @@ import com.googlecode.objectify.annotation.Ignore;
|
||||
import com.googlecode.objectify.annotation.Index;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.persistence.VKey;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.xml.bind.annotation.XmlEnumValue;
|
||||
@@ -64,7 +64,7 @@ public class DesignatedContact extends ImmutableObject implements UnsafeSerializ
|
||||
REGISTRANT
|
||||
}
|
||||
|
||||
public static DesignatedContact create(Type type, VKey<ContactResource> contact) {
|
||||
public static DesignatedContact create(Type type, VKey<Contact> contact) {
|
||||
DesignatedContact instance = new DesignatedContact();
|
||||
instance.type = type;
|
||||
instance.contactVKey = checkArgumentNotNull(contact, "Must specify contact key");
|
||||
@@ -74,14 +74,14 @@ public class DesignatedContact extends ImmutableObject implements UnsafeSerializ
|
||||
|
||||
Type type;
|
||||
|
||||
@Index Key<ContactResource> contact;
|
||||
@Ignore VKey<ContactResource> contactVKey;
|
||||
@Index Key<Contact> contact;
|
||||
@Ignore VKey<Contact> contactVKey;
|
||||
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public VKey<ContactResource> getContactKey() {
|
||||
public VKey<Contact> getContactKey() {
|
||||
return contactVKey;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ import google.registry.model.EppResource;
|
||||
import google.registry.model.EppResource.ResourceWithTransferData;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.common.EntityGroupRoot;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.domain.launch.LaunchNotice;
|
||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||
import google.registry.model.domain.secdns.DelegationSignerData;
|
||||
@@ -132,11 +132,11 @@ public class DomainBase extends EppResource
|
||||
@EmptySetToNull @Index @Transient Set<VKey<Host>> nsHosts;
|
||||
|
||||
/** Contacts. */
|
||||
VKey<ContactResource> adminContact;
|
||||
VKey<Contact> adminContact;
|
||||
|
||||
VKey<ContactResource> billingContact;
|
||||
VKey<ContactResource> techContact;
|
||||
VKey<ContactResource> registrantContact;
|
||||
VKey<Contact> billingContact;
|
||||
VKey<Contact> techContact;
|
||||
VKey<Contact> registrantContact;
|
||||
|
||||
/** Authorization info (aka transfer secret) of the domain. */
|
||||
@Embedded
|
||||
@@ -277,7 +277,7 @@ public class DomainBase extends EppResource
|
||||
@Ignore DateTime dnsRefreshRequestTime;
|
||||
|
||||
/** The {@link AllocationToken} for the package this domain is currently a part of. */
|
||||
@Nullable VKey<AllocationToken> currentPackageToken;
|
||||
@Ignore @Nullable VKey<AllocationToken> currentPackageToken;
|
||||
|
||||
/**
|
||||
* Returns the DNS refresh request time iff this domain's DNS needs refreshing, otherwise absent.
|
||||
@@ -602,19 +602,19 @@ public class DomainBase extends EppResource
|
||||
}
|
||||
|
||||
/** A key to the registrant who registered this domain. */
|
||||
public VKey<ContactResource> getRegistrant() {
|
||||
public VKey<Contact> getRegistrant() {
|
||||
return registrantContact;
|
||||
}
|
||||
|
||||
public VKey<ContactResource> getAdminContact() {
|
||||
public VKey<Contact> getAdminContact() {
|
||||
return adminContact;
|
||||
}
|
||||
|
||||
public VKey<ContactResource> getBillingContact() {
|
||||
public VKey<Contact> getBillingContact() {
|
||||
return billingContact;
|
||||
}
|
||||
|
||||
public VKey<ContactResource> getTechContact() {
|
||||
public VKey<Contact> getTechContact() {
|
||||
return techContact;
|
||||
}
|
||||
|
||||
@@ -628,7 +628,7 @@ public class DomainBase extends EppResource
|
||||
}
|
||||
|
||||
/** Returns all referenced contacts from this domain. */
|
||||
public ImmutableSet<VKey<ContactResource>> getReferencedContacts() {
|
||||
public ImmutableSet<VKey<Contact>> getReferencedContacts() {
|
||||
return nullToEmptyImmutableCopy(getAllContacts(true)).stream()
|
||||
.map(DesignatedContact::getContactKey)
|
||||
.filter(Objects::nonNull)
|
||||
@@ -771,7 +771,7 @@ public class DomainBase extends EppResource
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setRegistrant(VKey<ContactResource> registrant) {
|
||||
public B setRegistrant(VKey<Contact> registrant) {
|
||||
// Set the registrant field specifically.
|
||||
getInstance().registrantContact = registrant;
|
||||
return thisCastToDerived();
|
||||
|
||||
@@ -32,7 +32,7 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.eppinput.ResourceCommand.AbstractSingleResourceCommand;
|
||||
import google.registry.model.eppinput.ResourceCommand.ResourceCheck;
|
||||
import google.registry.model.eppinput.ResourceCommand.ResourceCreateOrChange;
|
||||
@@ -80,7 +80,7 @@ public class DomainCommand {
|
||||
String registrantContactId;
|
||||
|
||||
/** A resolved key to the registrant who registered this domain. */
|
||||
@XmlTransient VKey<ContactResource> registrant;
|
||||
@XmlTransient VKey<Contact> registrant;
|
||||
|
||||
/** Authorization info (aka transfer secret) of the domain. */
|
||||
DomainAuthInfo authInfo;
|
||||
@@ -90,7 +90,7 @@ public class DomainCommand {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public VKey<ContactResource> getRegistrant() {
|
||||
public VKey<Contact> getRegistrant() {
|
||||
return registrant;
|
||||
}
|
||||
|
||||
@@ -391,7 +391,7 @@ public class DomainCommand {
|
||||
? null
|
||||
: getOnlyElement(
|
||||
loadByForeignKeysCached(
|
||||
ImmutableSet.of(clone.registrantContactId), ContactResource.class, now)
|
||||
ImmutableSet.of(clone.registrantContactId), Contact.class, now)
|
||||
.values());
|
||||
return clone;
|
||||
}
|
||||
@@ -431,8 +431,8 @@ public class DomainCommand {
|
||||
for (ForeignKeyedDesignatedContact contact : contacts) {
|
||||
foreignKeys.add(contact.contactId);
|
||||
}
|
||||
ImmutableMap<String, VKey<ContactResource>> loadedContacts =
|
||||
loadByForeignKeysCached(foreignKeys.build(), ContactResource.class, now);
|
||||
ImmutableMap<String, VKey<Contact>> loadedContacts =
|
||||
loadByForeignKeysCached(foreignKeys.build(), Contact.class, now);
|
||||
ImmutableSet.Builder<DesignatedContact> linkedContacts = new ImmutableSet.Builder<>();
|
||||
for (ForeignKeyedDesignatedContact contact : contacts) {
|
||||
linkedContacts.add(
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
// 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.domain.packagetoken;
|
||||
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.eppinput.EppInput.CommandExtension;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/** A package token extension that may be present on EPP domain commands. */
|
||||
@XmlRootElement(name = "info")
|
||||
public class PackageTokenExtension extends ImmutableObject implements CommandExtension {}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
// 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.domain.packagetoken;
|
||||
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.domain.token.AllocationToken;
|
||||
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.xml.TrimWhitespaceAdapter;
|
||||
import java.util.Optional;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
|
||||
/**
|
||||
* An XML data object that represents a package token extension that may be present on the response
|
||||
* to EPP domain info commands.
|
||||
*/
|
||||
@XmlRootElement(name = "packageData")
|
||||
public class PackageTokenResponseExtension extends ImmutableObject implements ResponseExtension {
|
||||
|
||||
/** Token string of the PACKAGE token the name belongs to. */
|
||||
@XmlJavaTypeAdapter(TrimWhitespaceAdapter.class)
|
||||
String token;
|
||||
|
||||
public static PackageTokenResponseExtension create(Optional<VKey<AllocationToken>> tokenKey) {
|
||||
PackageTokenResponseExtension instance = new PackageTokenResponseExtension();
|
||||
instance.token = "";
|
||||
if (tokenKey.isPresent()) {
|
||||
instance.token = tokenKey.get().getSqlKey().toString();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// 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.
|
||||
|
||||
@XmlSchema(
|
||||
namespace = "urn:google:params:xml:ns:packageToken-1.0",
|
||||
xmlns =
|
||||
@XmlNs(prefix = "packageToken", namespaceURI = "urn:google:params:xml:ns:packageToken-1.0"),
|
||||
elementFormDefault = XmlNsForm.QUALIFIED)
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
package google.registry.model.domain.packagetoken;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlNs;
|
||||
import javax.xml.bind.annotation.XmlNsForm;
|
||||
import javax.xml.bind.annotation.XmlSchema;
|
||||
@@ -26,22 +26,16 @@ import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.common.collect.Range;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import com.googlecode.objectify.annotation.Index;
|
||||
import com.googlecode.objectify.annotation.OnLoad;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.domain.DomainFlowUtils;
|
||||
import google.registry.model.BackupGroupRoot;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.CreateAutoTimestamp;
|
||||
import google.registry.model.annotations.ReportedOn;
|
||||
import google.registry.model.billing.BillingEvent.RenewalPriceBehavior;
|
||||
import google.registry.model.common.TimedTransitionProperty;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
@@ -54,31 +48,31 @@ import javax.annotation.Nullable;
|
||||
import javax.persistence.AttributeOverride;
|
||||
import javax.persistence.AttributeOverrides;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.Table;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** An entity representing an allocation token. */
|
||||
@ReportedOn
|
||||
@Entity
|
||||
@WithStringVKey
|
||||
@javax.persistence.Entity
|
||||
@WithStringVKey(compositeKey = true)
|
||||
@Table(
|
||||
indexes = {
|
||||
@javax.persistence.Index(
|
||||
columnList = "token",
|
||||
name = "allocation_token_token_idx",
|
||||
unique = true),
|
||||
@javax.persistence.Index(
|
||||
columnList = "domainName",
|
||||
name = "allocation_token_domain_name_idx"),
|
||||
@javax.persistence.Index(columnList = "tokenType"),
|
||||
@javax.persistence.Index(columnList = "redemption_domain_repo_id")
|
||||
@Index(columnList = "token", name = "allocation_token_token_idx", unique = true),
|
||||
@Index(columnList = "domainName", name = "allocation_token_domain_name_idx"),
|
||||
@Index(columnList = "tokenType"),
|
||||
@Index(columnList = "redemption_domain_repo_id")
|
||||
})
|
||||
public class AllocationToken extends BackupGroupRoot implements Buildable {
|
||||
|
||||
private static final long serialVersionUID = -3954475393220876903L;
|
||||
private static final String REMOVE_PACKAGE = "__REMOVEPACKAGE__";
|
||||
|
||||
private static final ImmutableMap<String, TokenBehavior> STATIC_TOKEN_BEHAVIORS =
|
||||
ImmutableMap.of(REMOVE_PACKAGE, TokenBehavior.REMOVE_PACKAGE);
|
||||
|
||||
// Promotions should only move forward, and ENDED / CANCELLED are terminal states.
|
||||
private static final ImmutableMultimap<TokenStatus, TokenStatus> VALID_TOKEN_STATUS_TRANSITIONS =
|
||||
@@ -87,6 +81,18 @@ public class AllocationToken extends BackupGroupRoot implements Buildable {
|
||||
.putAll(VALID, ENDED, CANCELLED)
|
||||
.build();
|
||||
|
||||
private static final ImmutableMap<String, AllocationToken> BEHAVIORAL_TOKENS =
|
||||
ImmutableMap.of(
|
||||
REMOVE_PACKAGE,
|
||||
new AllocationToken.Builder()
|
||||
.setTokenType(TokenType.UNLIMITED_USE)
|
||||
.setToken(REMOVE_PACKAGE)
|
||||
.build());
|
||||
|
||||
public static Optional<AllocationToken> maybeGetStaticTokenInstance(String name) {
|
||||
return Optional.ofNullable(BEHAVIORAL_TOKENS.get(name));
|
||||
}
|
||||
|
||||
/** Any special behavior that should be used when registering domains using this token. */
|
||||
public enum RegistrationBehavior {
|
||||
/** No special behavior */
|
||||
@@ -110,7 +116,21 @@ public class AllocationToken extends BackupGroupRoot implements Buildable {
|
||||
public enum TokenType {
|
||||
PACKAGE,
|
||||
SINGLE_USE,
|
||||
UNLIMITED_USE
|
||||
UNLIMITED_USE,
|
||||
}
|
||||
|
||||
/**
|
||||
* System behaves differently based on a token it gets inside a command. This enumerates different
|
||||
* types of behaviors we support.
|
||||
*/
|
||||
public enum TokenBehavior {
|
||||
/** No special behavior */
|
||||
DEFAULT,
|
||||
/**
|
||||
* REMOVE_PACKAGE triggers domain removal from promotional package, bypasses DEFAULT token
|
||||
* validations.
|
||||
*/
|
||||
REMOVE_PACKAGE
|
||||
}
|
||||
|
||||
/** The status of this token with regard to any potential promotion. */
|
||||
@@ -126,11 +146,10 @@ public class AllocationToken extends BackupGroupRoot implements Buildable {
|
||||
}
|
||||
|
||||
/** The allocation token string. */
|
||||
@javax.persistence.Id @Id String token;
|
||||
@Id String token;
|
||||
|
||||
/** The key of the history entry for which the token was used. Null if not yet used. */
|
||||
@Nullable
|
||||
@Index
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(name = "repoId", column = @Column(name = "redemption_domain_repo_id")),
|
||||
@AttributeOverride(
|
||||
@@ -140,10 +159,10 @@ public class AllocationToken extends BackupGroupRoot implements Buildable {
|
||||
DomainHistoryVKey redemptionHistoryEntry;
|
||||
|
||||
/** The fully-qualified domain name that this token is limited to, if any. */
|
||||
@Nullable @Index String domainName;
|
||||
@Nullable String domainName;
|
||||
|
||||
/** When this token was created. */
|
||||
@Ignore CreateAutoTimestamp creationTime = CreateAutoTimestamp.create(null);
|
||||
CreateAutoTimestamp creationTime = CreateAutoTimestamp.create(null);
|
||||
|
||||
/** Allowed registrar client IDs for this token, or null if all registrars are allowed. */
|
||||
@Column(name = "allowedRegistrarIds")
|
||||
@@ -172,21 +191,12 @@ public class AllocationToken extends BackupGroupRoot implements Buildable {
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "renewalPriceBehavior", nullable = false)
|
||||
@Ignore
|
||||
RenewalPriceBehavior renewalPriceBehavior = RenewalPriceBehavior.DEFAULT;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(nullable = false)
|
||||
RegistrationBehavior registrationBehavior = RegistrationBehavior.DEFAULT;
|
||||
|
||||
// TODO: Remove onLoad once all allocation tokens are migrated to have a discountYears of 1.
|
||||
@OnLoad
|
||||
void onLoad() {
|
||||
if (discountYears == 0) {
|
||||
discountYears = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Promotional token validity periods.
|
||||
*
|
||||
@@ -255,9 +265,17 @@ public class AllocationToken extends BackupGroupRoot implements Buildable {
|
||||
return registrationBehavior;
|
||||
}
|
||||
|
||||
public TokenBehavior getTokenBehavior() {
|
||||
return STATIC_TOKEN_BEHAVIORS.getOrDefault(token, TokenBehavior.DEFAULT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VKey<AllocationToken> createVKey() {
|
||||
return VKey.create(AllocationToken.class, getToken(), Key.create(this));
|
||||
if (!AllocationToken.TokenBehavior.DEFAULT.equals(getTokenBehavior())) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("%s tokens are not stored in the database", getTokenBehavior()));
|
||||
}
|
||||
return VKey.createSql(AllocationToken.class, getToken());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -291,7 +309,8 @@ public class AllocationToken extends BackupGroupRoot implements Buildable {
|
||||
"Redemption history entry can only be specified for SINGLE_USE tokens");
|
||||
checkArgument(
|
||||
getInstance().tokenType != TokenType.PACKAGE
|
||||
|| getInstance().allowedClientIds.size() == 1,
|
||||
|| (getInstance().allowedClientIds != null
|
||||
&& getInstance().allowedClientIds.size() == 1),
|
||||
"PACKAGE tokens must have exactly one allowed client registrar");
|
||||
checkArgument(
|
||||
getInstance().discountFraction > 0 || !getInstance().discountPremiums,
|
||||
|
||||
@@ -31,25 +31,27 @@ import java.io.ByteArrayOutputStream;
|
||||
public class EppXmlTransformer {
|
||||
|
||||
// Hardcoded XML schemas, ordered with respect to dependency.
|
||||
private static final ImmutableList<String> SCHEMAS = ImmutableList.of(
|
||||
"eppcom.xsd",
|
||||
"epp.xsd",
|
||||
"contact.xsd",
|
||||
"host.xsd",
|
||||
"domain.xsd",
|
||||
"rgp.xsd",
|
||||
"secdns.xsd",
|
||||
"fee06.xsd",
|
||||
"fee11.xsd",
|
||||
"fee12.xsd",
|
||||
"metadata.xsd",
|
||||
"mark.xsd",
|
||||
"dsig.xsd",
|
||||
"smd.xsd",
|
||||
"launch.xsd",
|
||||
"allocate.xsd",
|
||||
"superuser.xsd",
|
||||
"allocationToken-1.0.xsd");
|
||||
private static final ImmutableList<String> SCHEMAS =
|
||||
ImmutableList.of(
|
||||
"eppcom.xsd",
|
||||
"epp.xsd",
|
||||
"contact.xsd",
|
||||
"host.xsd",
|
||||
"domain.xsd",
|
||||
"rgp.xsd",
|
||||
"secdns.xsd",
|
||||
"fee06.xsd",
|
||||
"fee11.xsd",
|
||||
"fee12.xsd",
|
||||
"metadata.xsd",
|
||||
"mark.xsd",
|
||||
"dsig.xsd",
|
||||
"smd.xsd",
|
||||
"launch.xsd",
|
||||
"allocate.xsd",
|
||||
"superuser.xsd",
|
||||
"allocationToken-1.0.xsd",
|
||||
"packageToken.xsd");
|
||||
|
||||
private static final XmlTransformer INPUT_TRANSFORMER =
|
||||
new XmlTransformer(SCHEMAS, EppInput.class);
|
||||
|
||||
@@ -20,8 +20,8 @@ import static com.google.common.base.Strings.nullToEmpty;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
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;
|
||||
@@ -130,12 +130,12 @@ public enum StatusValue implements EppEnum {
|
||||
/** Enum to help clearly list which resource types a status value is allowed to be present on. */
|
||||
private enum AllowedOn {
|
||||
ALL(
|
||||
Contact.class,
|
||||
ContactBase.class,
|
||||
ContactResource.class,
|
||||
DomainBase.class,
|
||||
Domain.class,
|
||||
HostBase.class,
|
||||
Host.class),
|
||||
DomainBase.class,
|
||||
Host.class,
|
||||
HostBase.class),
|
||||
NONE,
|
||||
DOMAINS(DomainBase.class, Domain.class);
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ import google.registry.model.domain.launch.LaunchDeleteExtension;
|
||||
import google.registry.model.domain.launch.LaunchInfoExtension;
|
||||
import google.registry.model.domain.launch.LaunchUpdateExtension;
|
||||
import google.registry.model.domain.metadata.MetadataExtension;
|
||||
import google.registry.model.domain.packagetoken.PackageTokenExtension;
|
||||
import google.registry.model.domain.rgp.RgpUpdateExtension;
|
||||
import google.registry.model.domain.secdns.SecDnsCreateExtension;
|
||||
import google.registry.model.domain.secdns.SecDnsUpdateExtension;
|
||||
@@ -362,6 +363,7 @@ public class EppInput extends ImmutableObject {
|
||||
// Other extensions
|
||||
@XmlElementRef(type = AllocationTokenExtension.class),
|
||||
@XmlElementRef(type = MetadataExtension.class),
|
||||
@XmlElementRef(type = PackageTokenExtension.class),
|
||||
@XmlElementRef(type = RgpUpdateExtension.class),
|
||||
@XmlElementRef(type = SecDnsCreateExtension.class),
|
||||
@XmlElementRef(type = SecDnsUpdateExtension.class)
|
||||
|
||||
@@ -43,6 +43,7 @@ import google.registry.model.domain.fee12.FeeRenewResponseExtensionV12;
|
||||
import google.registry.model.domain.fee12.FeeTransferResponseExtensionV12;
|
||||
import google.registry.model.domain.fee12.FeeUpdateResponseExtensionV12;
|
||||
import google.registry.model.domain.launch.LaunchCheckResponseExtension;
|
||||
import google.registry.model.domain.packagetoken.PackageTokenResponseExtension;
|
||||
import google.registry.model.domain.rgp.RgpInfoExtension;
|
||||
import google.registry.model.domain.secdns.SecDnsInfoExtension;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
@@ -121,28 +122,30 @@ public class EppResponse extends ImmutableObject implements ResponseOrGreeting {
|
||||
|
||||
/** Zero or more response extensions. */
|
||||
@XmlElementRefs({
|
||||
@XmlElementRef(type = FeeCheckResponseExtensionV06.class),
|
||||
@XmlElementRef(type = FeeInfoResponseExtensionV06.class),
|
||||
@XmlElementRef(type = FeeCreateResponseExtensionV06.class),
|
||||
@XmlElementRef(type = FeeDeleteResponseExtensionV06.class),
|
||||
@XmlElementRef(type = FeeRenewResponseExtensionV06.class),
|
||||
@XmlElementRef(type = FeeTransferResponseExtensionV06.class),
|
||||
@XmlElementRef(type = FeeUpdateResponseExtensionV06.class),
|
||||
@XmlElementRef(type = FeeCheckResponseExtensionV11.class),
|
||||
@XmlElementRef(type = FeeCreateResponseExtensionV11.class),
|
||||
@XmlElementRef(type = FeeDeleteResponseExtensionV11.class),
|
||||
@XmlElementRef(type = FeeRenewResponseExtensionV11.class),
|
||||
@XmlElementRef(type = FeeTransferResponseExtensionV11.class),
|
||||
@XmlElementRef(type = FeeUpdateResponseExtensionV11.class),
|
||||
@XmlElementRef(type = FeeCheckResponseExtensionV12.class),
|
||||
@XmlElementRef(type = FeeCreateResponseExtensionV12.class),
|
||||
@XmlElementRef(type = FeeDeleteResponseExtensionV12.class),
|
||||
@XmlElementRef(type = FeeRenewResponseExtensionV12.class),
|
||||
@XmlElementRef(type = FeeTransferResponseExtensionV12.class),
|
||||
@XmlElementRef(type = FeeUpdateResponseExtensionV12.class),
|
||||
@XmlElementRef(type = LaunchCheckResponseExtension.class),
|
||||
@XmlElementRef(type = RgpInfoExtension.class),
|
||||
@XmlElementRef(type = SecDnsInfoExtension.class) })
|
||||
@XmlElementRef(type = FeeCheckResponseExtensionV06.class),
|
||||
@XmlElementRef(type = FeeInfoResponseExtensionV06.class),
|
||||
@XmlElementRef(type = FeeCreateResponseExtensionV06.class),
|
||||
@XmlElementRef(type = FeeDeleteResponseExtensionV06.class),
|
||||
@XmlElementRef(type = FeeRenewResponseExtensionV06.class),
|
||||
@XmlElementRef(type = FeeTransferResponseExtensionV06.class),
|
||||
@XmlElementRef(type = FeeUpdateResponseExtensionV06.class),
|
||||
@XmlElementRef(type = FeeCheckResponseExtensionV11.class),
|
||||
@XmlElementRef(type = FeeCreateResponseExtensionV11.class),
|
||||
@XmlElementRef(type = FeeDeleteResponseExtensionV11.class),
|
||||
@XmlElementRef(type = FeeRenewResponseExtensionV11.class),
|
||||
@XmlElementRef(type = FeeTransferResponseExtensionV11.class),
|
||||
@XmlElementRef(type = FeeUpdateResponseExtensionV11.class),
|
||||
@XmlElementRef(type = FeeCheckResponseExtensionV12.class),
|
||||
@XmlElementRef(type = FeeCreateResponseExtensionV12.class),
|
||||
@XmlElementRef(type = FeeDeleteResponseExtensionV12.class),
|
||||
@XmlElementRef(type = FeeRenewResponseExtensionV12.class),
|
||||
@XmlElementRef(type = FeeTransferResponseExtensionV12.class),
|
||||
@XmlElementRef(type = FeeUpdateResponseExtensionV12.class),
|
||||
@XmlElementRef(type = LaunchCheckResponseExtension.class),
|
||||
@XmlElementRef(type = PackageTokenResponseExtension.class),
|
||||
@XmlElementRef(type = RgpInfoExtension.class),
|
||||
@XmlElementRef(type = SecDnsInfoExtension.class)
|
||||
})
|
||||
@XmlElementWrapper(name = "extension")
|
||||
ImmutableList<? extends ResponseExtension> extensions;
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ import google.registry.model.CacheUtils.AppEngineEnvironmentCacheLoader;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.annotations.DeleteAfterMigration;
|
||||
import google.registry.model.annotations.ReportedOn;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.persistence.VKey;
|
||||
@@ -70,10 +70,10 @@ import org.joda.time.DateTime;
|
||||
@DeleteAfterMigration
|
||||
public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroupRoot {
|
||||
|
||||
/** The {@link ForeignKeyIndex} type for {@link ContactResource} entities. */
|
||||
/** The {@link ForeignKeyIndex} type for {@link Contact} entities. */
|
||||
@ReportedOn
|
||||
@Entity
|
||||
public static class ForeignKeyContactIndex extends ForeignKeyIndex<ContactResource> {}
|
||||
public static class ForeignKeyContactIndex extends ForeignKeyIndex<Contact> {}
|
||||
|
||||
/** The {@link ForeignKeyIndex} type for {@link Domain} entities. */
|
||||
@ReportedOn
|
||||
@@ -89,14 +89,14 @@ public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroup
|
||||
Class<? extends EppResource>, Class<? extends ForeignKeyIndex<?>>>
|
||||
RESOURCE_CLASS_TO_FKI_CLASS =
|
||||
ImmutableBiMap.of(
|
||||
ContactResource.class, ForeignKeyContactIndex.class,
|
||||
Contact.class, ForeignKeyContactIndex.class,
|
||||
Domain.class, ForeignKeyDomainIndex.class,
|
||||
Host.class, ForeignKeyHostIndex.class);
|
||||
|
||||
private static final ImmutableMap<Class<? extends EppResource>, String>
|
||||
RESOURCE_CLASS_TO_FKI_PROPERTY =
|
||||
ImmutableMap.of(
|
||||
ContactResource.class, "contactId",
|
||||
Contact.class, "contactId",
|
||||
Domain.class, "fullyQualifiedDomainName",
|
||||
Host.class, "fullyQualifiedHostName");
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
*
|
||||
* <p>All first class entities are represented as a resource class - {@link
|
||||
* google.registry.model.domain.Domain}, {@link google.registry.model.host.Host}, {@link
|
||||
* google.registry.model.contact.ContactResource}, and {@link
|
||||
* google.registry.model.contact.Contact}, 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"
|
||||
* class- {@link google.registry.model.domain.DomainCommand}, {@link
|
||||
|
||||
@@ -26,9 +26,9 @@ import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.model.annotations.ExternalMessagingName;
|
||||
import google.registry.model.annotations.OfyIdAllocation;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactHistory;
|
||||
import google.registry.model.contact.ContactHistory.ContactHistoryId;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.domain.DomainHistory.DomainHistoryId;
|
||||
@@ -95,7 +95,7 @@ public abstract class PollMessage extends ImmutableObject
|
||||
/** Indicates the type of entity the poll message is for. */
|
||||
public enum Type {
|
||||
DOMAIN(1L, Domain.class),
|
||||
CONTACT(2L, ContactResource.class),
|
||||
CONTACT(2L, Contact.class),
|
||||
HOST(3L, Host.class);
|
||||
|
||||
private final long id;
|
||||
@@ -179,7 +179,7 @@ public abstract class PollMessage extends ImmutableObject
|
||||
/**
|
||||
* Returns the contact repo id.
|
||||
*
|
||||
* <p>This may only be used on a ContactResource poll event.
|
||||
* <p>This may only be used on a {@link Contact} poll event.
|
||||
*/
|
||||
public String getContactRepoId() {
|
||||
checkArgument(getType() == Type.CONTACT);
|
||||
@@ -215,6 +215,9 @@ public abstract class PollMessage extends ImmutableObject
|
||||
return domainRepoId != null ? Type.DOMAIN : contactRepoId != null ? Type.CONTACT : Type.HOST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract VKey<? extends PollMessage> createVKey();
|
||||
|
||||
public abstract ImmutableList<ResponseData> getResponseData();
|
||||
|
||||
/** Override Buildable.asBuilder() to give this method stronger typing. */
|
||||
|
||||
@@ -19,10 +19,6 @@ import static google.registry.model.rde.RdeNamingUtils.makePartialName;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
|
||||
import com.google.common.base.VerifyException;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import google.registry.model.BackupGroupRoot;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.rde.RdeRevision.RdeRevisionId;
|
||||
@@ -32,10 +28,11 @@ import java.io.Serializable;
|
||||
import java.util.Optional;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Convert;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.Transient;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.LocalDate;
|
||||
|
||||
@@ -47,18 +44,14 @@ import org.joda.time.LocalDate;
|
||||
* flag is included in the generated XML.
|
||||
*/
|
||||
@Entity
|
||||
@javax.persistence.Entity
|
||||
@IdClass(RdeRevisionId.class)
|
||||
public final class RdeRevision extends BackupGroupRoot {
|
||||
|
||||
/** String triplet of tld, date, and mode, e.g. {@code soy_2015-09-01_full}. */
|
||||
@Id @Transient String id;
|
||||
@Id String tld;
|
||||
|
||||
@javax.persistence.Id @Ignore String tld;
|
||||
@Id LocalDate date;
|
||||
|
||||
@javax.persistence.Id @Ignore LocalDate date;
|
||||
|
||||
@javax.persistence.Id @Ignore RdeMode mode;
|
||||
@Id RdeMode mode;
|
||||
|
||||
/**
|
||||
* Number of last revision successfully staged to GCS.
|
||||
@@ -71,10 +64,8 @@ public final class RdeRevision extends BackupGroupRoot {
|
||||
/** Hibernate requires an empty constructor. */
|
||||
private RdeRevision() {}
|
||||
|
||||
public static RdeRevision create(
|
||||
String id, String tld, LocalDate date, RdeMode mode, int revision) {
|
||||
public static RdeRevision create(String tld, LocalDate date, RdeMode mode, int revision) {
|
||||
RdeRevision instance = new RdeRevision();
|
||||
instance.id = id;
|
||||
instance.tld = tld;
|
||||
instance.date = date;
|
||||
instance.mode = mode;
|
||||
@@ -92,12 +83,9 @@ public final class RdeRevision extends BackupGroupRoot {
|
||||
* @return {@code 0} for first deposit generation and {@code >0} for resends
|
||||
*/
|
||||
public static int getNextRevision(String tld, DateTime date, RdeMode mode) {
|
||||
String id = makePartialName(tld, date, mode);
|
||||
RdeRevisionId sqlKey = RdeRevisionId.create(tld, date.toLocalDate(), mode);
|
||||
Key<RdeRevision> ofyKey = Key.create(RdeRevision.class, id);
|
||||
Optional<RdeRevision> revisionOptional =
|
||||
tm().transact(
|
||||
() -> tm().loadByKeyIfPresent(VKey.create(RdeRevision.class, sqlKey, ofyKey)));
|
||||
tm().transact(() -> tm().loadByKeyIfPresent(VKey.createSql(RdeRevision.class, sqlKey)));
|
||||
return revisionOptional.map(rdeRevision -> rdeRevision.revision + 1).orElse(0);
|
||||
}
|
||||
|
||||
@@ -121,12 +109,10 @@ public final class RdeRevision extends BackupGroupRoot {
|
||||
*/
|
||||
public static void saveRevision(String tld, DateTime date, RdeMode mode, int revision) {
|
||||
checkArgument(revision >= 0, "Negative revision: %s", revision);
|
||||
String triplet = makePartialName(tld, date, mode);
|
||||
tm().assertInTransaction();
|
||||
RdeRevisionId sqlKey = RdeRevisionId.create(tld, date.toLocalDate(), mode);
|
||||
Key<RdeRevision> ofyKey = Key.create(RdeRevision.class, triplet);
|
||||
Optional<RdeRevision> revisionOptional =
|
||||
tm().loadByKeyIfPresent(VKey.create(RdeRevision.class, sqlKey, ofyKey));
|
||||
tm().loadByKeyIfPresent(VKey.createSql(RdeRevision.class, sqlKey));
|
||||
if (revision == 0) {
|
||||
revisionOptional.ifPresent(
|
||||
rdeRevision -> {
|
||||
@@ -139,7 +125,7 @@ public final class RdeRevision extends BackupGroupRoot {
|
||||
checkArgument(
|
||||
revisionOptional.isPresent(),
|
||||
"Couldn't find existing RDE revision %s when trying to save new revision %s",
|
||||
triplet,
|
||||
makePartialName(tld, date, mode),
|
||||
revision);
|
||||
checkArgument(
|
||||
revisionOptional.get().revision == revision - 1,
|
||||
@@ -147,7 +133,7 @@ public final class RdeRevision extends BackupGroupRoot {
|
||||
revision - 1,
|
||||
revisionOptional.get());
|
||||
}
|
||||
RdeRevision object = RdeRevision.create(triplet, tld, date.toLocalDate(), mode, revision);
|
||||
RdeRevision object = create(tld, date.toLocalDate(), mode, revision);
|
||||
tm().put(object);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,8 +26,6 @@ import static com.google.common.collect.Sets.immutableEnumSet;
|
||||
import static com.google.common.io.BaseEncoding.base64;
|
||||
import static google.registry.config.RegistryConfig.getDefaultRegistrarWhoisServer;
|
||||
import static google.registry.model.CacheUtils.memoizeWithShortExpiration;
|
||||
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
|
||||
import static google.registry.model.ofy.ObjectifyService.auditedOfy;
|
||||
import static google.registry.model.tld.Registries.assertTldsExist;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
@@ -44,7 +42,6 @@ import static java.util.function.Predicate.isEqual;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
@@ -55,12 +52,6 @@ import com.google.common.collect.Range;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.re2j.Pattern;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import com.googlecode.objectify.annotation.Index;
|
||||
import com.googlecode.objectify.annotation.Parent;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.CreateAutoTimestamp;
|
||||
import google.registry.model.ImmutableObject;
|
||||
@@ -68,9 +59,6 @@ import google.registry.model.JsonMapBuilder;
|
||||
import google.registry.model.Jsonifiable;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.model.UpdateAutoTimestamp;
|
||||
import google.registry.model.annotations.InCrossTld;
|
||||
import google.registry.model.annotations.ReportedOn;
|
||||
import google.registry.model.common.EntityGroupRoot;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.model.tld.Registry.TldType;
|
||||
import google.registry.persistence.VKey;
|
||||
@@ -83,6 +71,7 @@ import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.mail.internet.AddressException;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
@@ -90,25 +79,22 @@ import javax.persistence.AttributeOverride;
|
||||
import javax.persistence.AttributeOverrides;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Transient;
|
||||
import org.joda.money.CurrencyUnit;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** Information about a registrar. */
|
||||
@ReportedOn
|
||||
@Entity
|
||||
@javax.persistence.Entity
|
||||
@Table(
|
||||
indexes = {
|
||||
@javax.persistence.Index(columnList = "registrarName", name = "registrar_name_idx"),
|
||||
@javax.persistence.Index(
|
||||
columnList = "ianaIdentifier",
|
||||
name = "registrar_iana_identifier_idx"),
|
||||
@Index(columnList = "registrarName", name = "registrar_name_idx"),
|
||||
@Index(columnList = "ianaIdentifier", name = "registrar_iana_identifier_idx"),
|
||||
})
|
||||
@InCrossTld
|
||||
public class Registrar extends ImmutableObject
|
||||
implements Buildable, Jsonifiable, UnsafeSerializable {
|
||||
|
||||
@@ -197,7 +183,7 @@ public class Registrar extends ImmutableObject
|
||||
|
||||
/** The states in which a {@link Registrar} is considered {@link #isLive live}. */
|
||||
private static final ImmutableSet<State> LIVE_STATES =
|
||||
Sets.immutableEnumSet(State.ACTIVE, State.SUSPENDED);
|
||||
immutableEnumSet(State.ACTIVE, State.SUSPENDED);
|
||||
|
||||
/**
|
||||
* The types for which a {@link Registrar} should be included in WHOIS and RDAP output. We exclude
|
||||
@@ -213,18 +199,9 @@ public class Registrar extends ImmutableObject
|
||||
private static final Comparator<RegistrarPoc> CONTACT_EMAIL_COMPARATOR =
|
||||
comparing(RegistrarPoc::getEmailAddress, String::compareTo);
|
||||
|
||||
/**
|
||||
* A caching {@link Supplier} of a registrarId to {@link Registrar} map.
|
||||
*
|
||||
* <p>The supplier's get() method enters a transactionless context briefly to avoid enrolling the
|
||||
* query inside an unrelated client-affecting transaction.
|
||||
*/
|
||||
/** A caching {@link Supplier} of a registrarId to {@link Registrar} map. */
|
||||
private static final Supplier<ImmutableMap<String, Registrar>> CACHE_BY_REGISTRAR_ID =
|
||||
memoizeWithShortExpiration(
|
||||
() ->
|
||||
tm().doTransactionless(() -> Maps.uniqueIndex(loadAll(), Registrar::getRegistrarId)));
|
||||
|
||||
@Parent @Transient Key<EntityGroupRoot> parent = getCrossTldKey();
|
||||
memoizeWithShortExpiration(() -> Maps.uniqueIndex(loadAll(), Registrar::getRegistrarId));
|
||||
|
||||
/**
|
||||
* Unique registrar client id. Must conform to "clIDType" as defined in RFC5730.
|
||||
@@ -233,7 +210,6 @@ public class Registrar extends ImmutableObject
|
||||
* <p>TODO(b/177567432): Rename this field to registrarId.
|
||||
*/
|
||||
@Id
|
||||
@javax.persistence.Id
|
||||
@Column(name = "registrarId", nullable = false)
|
||||
String clientIdentifier;
|
||||
|
||||
@@ -248,7 +224,6 @@ public class Registrar extends ImmutableObject
|
||||
* @see <a href="http://www.icann.org/registrar-reports/accredited-list.html">ICANN-Accredited
|
||||
* Registrars</a>
|
||||
*/
|
||||
@Index
|
||||
@Column(nullable = false)
|
||||
String registrarName;
|
||||
|
||||
@@ -313,7 +288,6 @@ public class Registrar extends ImmutableObject
|
||||
* Localized {@link RegistrarAddress} for this registrar. Contents can be represented in
|
||||
* unrestricted UTF-8.
|
||||
*/
|
||||
@Ignore
|
||||
@Embedded
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(
|
||||
@@ -338,7 +312,6 @@ public class Registrar extends ImmutableObject
|
||||
* Internationalized {@link RegistrarAddress} for this registrar. All contained values must be
|
||||
* representable in the 7-bit US-ASCII character set.
|
||||
*/
|
||||
@Ignore
|
||||
@Embedded
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(name = "streetLine1", column = @Column(name = "i18n_address_street_line1")),
|
||||
@@ -367,14 +340,14 @@ public class Registrar extends ImmutableObject
|
||||
*
|
||||
* <ul>
|
||||
* <li>8 is used for Testing Registrar.
|
||||
* <li>9997 is used by ICAAN for SLA monitoring.
|
||||
* <li>9997 is used by ICANN for SLA monitoring.
|
||||
* <li>9999 is used for cases when the registry operator acts as registrar.
|
||||
* </ul>
|
||||
*
|
||||
* @see <a href="http://www.iana.org/assignments/registrar-ids/registrar-ids.txt">Registrar
|
||||
* IDs</a>
|
||||
*/
|
||||
@Index @Nullable Long ianaIdentifier;
|
||||
@Nullable Long ianaIdentifier;
|
||||
|
||||
/** Purchase Order number used for invoices in external billing system, if applicable. */
|
||||
@Nullable String poNumber;
|
||||
@@ -395,7 +368,7 @@ public class Registrar extends ImmutableObject
|
||||
/**
|
||||
* ICANN referral email address.
|
||||
*
|
||||
* <p>This value is specified in the initial registrar contact. It can't be edited in the web GUI
|
||||
* <p>This value is specified in the initial registrar contact. It can't be edited in the web GUI,
|
||||
* and it must be specified when the registrar account is created.
|
||||
*/
|
||||
String icannReferralEmail;
|
||||
@@ -406,10 +379,10 @@ public class Registrar extends ImmutableObject
|
||||
// Metadata.
|
||||
|
||||
/** The time when this registrar was created. */
|
||||
@Ignore CreateAutoTimestamp creationTime = CreateAutoTimestamp.create(null);
|
||||
CreateAutoTimestamp creationTime = CreateAutoTimestamp.create(null);
|
||||
|
||||
/** An automatically managed last-saved timestamp. */
|
||||
@Ignore UpdateAutoTimestamp lastUpdateTime = UpdateAutoTimestamp.create(null);
|
||||
UpdateAutoTimestamp lastUpdateTime = UpdateAutoTimestamp.create(null);
|
||||
|
||||
/** The time that the certificate was last updated. */
|
||||
DateTime lastCertificateUpdateTime;
|
||||
@@ -610,18 +583,13 @@ public class Registrar extends ImmutableObject
|
||||
}
|
||||
|
||||
private Iterable<RegistrarPoc> getContactsIterable() {
|
||||
if (tm().isOfy()) {
|
||||
return auditedOfy().load().type(RegistrarPoc.class).ancestor(Registrar.this);
|
||||
} else {
|
||||
return tm().transact(
|
||||
() ->
|
||||
jpaTm()
|
||||
.query(
|
||||
"FROM RegistrarPoc WHERE registrarId = :registrarId", RegistrarPoc.class)
|
||||
.setParameter("registrarId", clientIdentifier)
|
||||
.getResultStream()
|
||||
.collect(toImmutableList()));
|
||||
}
|
||||
return tm().transact(
|
||||
() ->
|
||||
jpaTm()
|
||||
.query("FROM RegistrarPoc WHERE registrarId = :registrarId", RegistrarPoc.class)
|
||||
.setParameter("registrarId", clientIdentifier)
|
||||
.getResultStream()
|
||||
.collect(toImmutableList()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -687,18 +655,13 @@ public class Registrar extends ImmutableObject
|
||||
/** Creates a {@link VKey} for this instance. */
|
||||
@Override
|
||||
public VKey<Registrar> createVKey() {
|
||||
return createVKey(Key.create(this));
|
||||
return createVKey(clientIdentifier);
|
||||
}
|
||||
|
||||
/** Creates a {@link VKey} for the given {@code registrarId}. */
|
||||
public static VKey<Registrar> createVKey(String registrarId) {
|
||||
checkArgumentNotNull(registrarId, "registrarId must be specified");
|
||||
return createVKey(Key.create(getCrossTldKey(), Registrar.class, registrarId));
|
||||
}
|
||||
|
||||
/** Creates a {@link VKey} instance from a {@link Key} instance. */
|
||||
public static VKey<Registrar> createVKey(Key<Registrar> key) {
|
||||
return VKey.create(Registrar.class, key.getName(), key);
|
||||
return VKey.createSql(Registrar.class, registrarId);
|
||||
}
|
||||
|
||||
/** A builder for constructing {@link Registrar}, since it is immutable. */
|
||||
@@ -774,7 +737,7 @@ public class Registrar extends ImmutableObject
|
||||
Set<VKey<Registry>> missingTldKeys =
|
||||
Sets.difference(
|
||||
newTldKeys, tm().transact(() -> tm().loadByKeysIfPresent(newTldKeys)).keySet());
|
||||
checkArgument(missingTldKeys.isEmpty(), "Trying to set nonexisting TLDs: %s", missingTldKeys);
|
||||
checkArgument(missingTldKeys.isEmpty(), "Trying to set nonexistent TLDs: %s", missingTldKeys);
|
||||
getInstance().allowedTlds = ImmutableSortedSet.copyOf(allowedTlds);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -34,10 +34,10 @@ import google.registry.model.EppResource;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.model.annotations.ReportedOn;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactBase;
|
||||
import google.registry.model.contact.ContactHistory;
|
||||
import google.registry.model.contact.ContactHistory.ContactHistoryId;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
@@ -392,7 +392,7 @@ public class HistoryEntry extends ImmutableObject implements Buildable, UnsafeSe
|
||||
} else if (parentKind.equals(getKind(Host.class))) {
|
||||
resultEntity =
|
||||
new HostHistory.Builder().copyFrom(this).setHostRepoId(parent.getName()).build();
|
||||
} else if (parentKind.equals(getKind(ContactResource.class))) {
|
||||
} else if (parentKind.equals(getKind(Contact.class))) {
|
||||
resultEntity =
|
||||
new ContactHistory.Builder().copyFrom(this).setContactRepoId(parent.getName()).build();
|
||||
} else {
|
||||
@@ -418,7 +418,7 @@ public class HistoryEntry extends ImmutableObject implements Buildable, UnsafeSe
|
||||
HostHistory.class,
|
||||
new HostHistoryId(repoId, id),
|
||||
Key.create(parent, HostHistory.class, id));
|
||||
} else if (parentKind.equals(getKind(ContactResource.class))) {
|
||||
} else if (parentKind.equals(getKind(Contact.class))) {
|
||||
return VKey.create(
|
||||
ContactHistory.class,
|
||||
new ContactHistoryId(repoId, id),
|
||||
|
||||
@@ -25,8 +25,8 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Streams;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
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;
|
||||
@@ -51,7 +51,7 @@ public class HistoryEntryDao {
|
||||
public static ImmutableMap<Class<? extends EppResource>, Class<? extends HistoryEntry>>
|
||||
RESOURCE_TYPES_TO_HISTORY_TYPES =
|
||||
ImmutableMap.of(
|
||||
ContactResource.class,
|
||||
Contact.class,
|
||||
ContactHistory.class,
|
||||
Domain.class,
|
||||
DomainHistory.class,
|
||||
|
||||
@@ -16,7 +16,6 @@ package google.registry.model.server;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.DateTimeUtils.isAtOrAfter;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
@@ -24,15 +23,8 @@ import com.google.auto.value.AutoValue;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.annotations.NotBackedUp;
|
||||
import google.registry.model.annotations.NotBackedUp.Reason;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.transaction.JpaTransactionManager;
|
||||
import google.registry.persistence.transaction.TransactionManager;
|
||||
import google.registry.util.RequestStatusChecker;
|
||||
import google.registry.util.RequestStatusCheckerImpl;
|
||||
import java.io.Serializable;
|
||||
@@ -40,6 +32,8 @@ import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.PostLoad;
|
||||
import javax.persistence.Table;
|
||||
@@ -57,8 +51,6 @@ import org.joda.time.Duration;
|
||||
* safe calls that automatically lock and unlock, see LockHandler.
|
||||
*/
|
||||
@Entity
|
||||
@NotBackedUp(reason = Reason.TRANSIENT)
|
||||
@javax.persistence.Entity
|
||||
@Table
|
||||
@IdClass(Lock.LockId.class)
|
||||
public class Lock extends ImmutableObject implements Serializable {
|
||||
@@ -109,14 +101,13 @@ public class Lock extends ImmutableObject implements Serializable {
|
||||
|
||||
/** The resource name used to create the lock. */
|
||||
@Column(nullable = false)
|
||||
@javax.persistence.Id
|
||||
@Id
|
||||
String resourceName;
|
||||
|
||||
/** The tld used to create the lock, or GLOBAL if it's cross-TLD. */
|
||||
// TODO(b/177567432): rename to "scope" post-Datastore
|
||||
@Column(nullable = false, name = "scope")
|
||||
@javax.persistence.Id
|
||||
String tld;
|
||||
@Column(nullable = false)
|
||||
@Id
|
||||
String scope;
|
||||
|
||||
public DateTime getExpirationTime() {
|
||||
return expirationTime;
|
||||
@@ -124,7 +115,7 @@ public class Lock extends ImmutableObject implements Serializable {
|
||||
|
||||
@PostLoad
|
||||
void postLoad() {
|
||||
lockId = makeLockId(resourceName, tld);
|
||||
lockId = makeLockId(resourceName, scope);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,7 +137,7 @@ public class Lock extends ImmutableObject implements Serializable {
|
||||
instance.expirationTime = acquiredTime.plus(leaseLength);
|
||||
instance.acquiredTime = acquiredTime;
|
||||
instance.resourceName = resourceName;
|
||||
instance.tld = scope;
|
||||
instance.scope = scope;
|
||||
return instance;
|
||||
}
|
||||
|
||||
@@ -157,8 +148,13 @@ public class Lock extends ImmutableObject implements Serializable {
|
||||
@AutoValue
|
||||
abstract static class AcquireResult {
|
||||
public abstract DateTime transactionTime();
|
||||
public abstract @Nullable Lock existingLock();
|
||||
public abstract @Nullable Lock newLock();
|
||||
|
||||
@Nullable
|
||||
public abstract Lock existingLock();
|
||||
|
||||
@Nullable
|
||||
public abstract Lock newLock();
|
||||
|
||||
public abstract LockState lockState();
|
||||
|
||||
public static AcquireResult create(
|
||||
@@ -213,64 +209,18 @@ public class Lock extends ImmutableObject implements Serializable {
|
||||
Duration leaseLength,
|
||||
RequestStatusChecker requestStatusChecker,
|
||||
boolean checkThreadRunning) {
|
||||
return acquireWithTransactionManager(
|
||||
resourceName, tld, leaseLength, requestStatusChecker, checkThreadRunning, tm());
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to acquire a lock in SQL. Returns absent if it can't be acquired.
|
||||
*
|
||||
* <p>This method exists so that Beam pipelines can acquire / load / release locks.
|
||||
*/
|
||||
public static Optional<Lock> acquireSql(
|
||||
String resourceName,
|
||||
@Nullable String tld,
|
||||
Duration leaseLength,
|
||||
RequestStatusChecker requestStatusChecker,
|
||||
boolean checkThreadRunning) {
|
||||
return acquireWithTransactionManager(
|
||||
resourceName, tld, leaseLength, requestStatusChecker, checkThreadRunning, jpaTm());
|
||||
}
|
||||
|
||||
/** Release the lock. */
|
||||
public void release() {
|
||||
releaseWithTransactionManager(tm());
|
||||
}
|
||||
|
||||
/**
|
||||
* Release the lock from SQL.
|
||||
*
|
||||
* <p>This method exists so that Beam pipelines can acquire / load / release locks.
|
||||
*/
|
||||
public void releaseSql() {
|
||||
releaseWithTransactionManager(jpaTm());
|
||||
}
|
||||
|
||||
/** Try to acquire a lock. Returns absent if it can't be acquired. */
|
||||
private static Optional<Lock> acquireWithTransactionManager(
|
||||
String resourceName,
|
||||
@Nullable String tld,
|
||||
Duration leaseLength,
|
||||
RequestStatusChecker requestStatusChecker,
|
||||
boolean checkThreadRunning,
|
||||
TransactionManager transactionManager) {
|
||||
String scope = (tld != null) ? tld : GLOBAL;
|
||||
String lockId = makeLockId(resourceName, scope);
|
||||
String scope = tld != null ? tld : GLOBAL;
|
||||
// It's important to use transactNew rather than transact, because a Lock can be used to control
|
||||
// access to resources like GCS that can't be transactionally rolled back. Therefore, the lock
|
||||
// must be definitively acquired before it is used, even when called inside another transaction.
|
||||
Supplier<AcquireResult> lockAcquirer =
|
||||
() -> {
|
||||
DateTime now = transactionManager.getTransactionTime();
|
||||
DateTime now = jpaTm().getTransactionTime();
|
||||
|
||||
// Checking if an unexpired lock still exists - if so, the lock can't be acquired.
|
||||
Lock lock =
|
||||
transactionManager
|
||||
.loadByKeyIfPresent(
|
||||
VKey.create(
|
||||
Lock.class,
|
||||
new LockId(resourceName, scope),
|
||||
Key.create(Lock.class, lockId)))
|
||||
jpaTm()
|
||||
.loadByKeyIfPresent(VKey.createSql(Lock.class, new LockId(resourceName, scope)))
|
||||
.orElse(null);
|
||||
if (lock != null) {
|
||||
logger.atInfo().log(
|
||||
@@ -292,15 +242,11 @@ public class Lock extends ImmutableObject implements Serializable {
|
||||
create(resourceName, scope, requestStatusChecker.getLogId(), now, leaseLength);
|
||||
// Locks are not parented under an EntityGroupRoot (so as to avoid write
|
||||
// contention) and don't need to be backed up.
|
||||
transactionManager.put(newLock);
|
||||
jpaTm().put(newLock);
|
||||
|
||||
return AcquireResult.create(now, lock, newLock, lockState);
|
||||
};
|
||||
// In ofy, backup is determined per-action, but in SQL it's determined per-transaction
|
||||
AcquireResult acquireResult =
|
||||
transactionManager.isOfy()
|
||||
? transactionManager.transactNew(lockAcquirer)
|
||||
: ((JpaTransactionManager) transactionManager).transactWithoutBackup(lockAcquirer);
|
||||
AcquireResult acquireResult = jpaTm().transactWithoutBackup(lockAcquirer);
|
||||
|
||||
logAcquireResult(acquireResult);
|
||||
lockMetrics.recordAcquire(resourceName, scope, acquireResult.lockState());
|
||||
@@ -308,62 +254,51 @@ public class Lock extends ImmutableObject implements Serializable {
|
||||
}
|
||||
|
||||
/** Release the lock. */
|
||||
private void releaseWithTransactionManager(TransactionManager transactionManager) {
|
||||
public void release() {
|
||||
// Just use the default clock because we aren't actually doing anything that will use the clock.
|
||||
Supplier<Void> lockReleaser =
|
||||
() -> {
|
||||
// To release a lock, check that no one else has already obtained it and if not
|
||||
// delete it. If the lock in Datastore was different then this lock is gone already;
|
||||
// delete it. If the lock in the database was different, then this lock is gone already;
|
||||
// this can happen if release() is called around the expiration time and the lock
|
||||
// expires underneath us.
|
||||
VKey<Lock> key =
|
||||
VKey.create(
|
||||
Lock.class, new LockId(resourceName, tld), Key.create(Lock.class, lockId));
|
||||
Lock loadedLock = transactionManager.loadByKeyIfPresent(key).orElse(null);
|
||||
if (Lock.this.equals(loadedLock)) {
|
||||
VKey<Lock> key = VKey.createSql(Lock.class, new LockId(resourceName, scope));
|
||||
Lock loadedLock = jpaTm().loadByKeyIfPresent(key).orElse(null);
|
||||
if (equals(loadedLock)) {
|
||||
// Use deleteIgnoringReadOnly() so that we don't create a commit log entry for deleting
|
||||
// the lock.
|
||||
logger.atInfo().log("Deleting lock: %s", lockId);
|
||||
transactionManager.delete(key);
|
||||
jpaTm().delete(key);
|
||||
|
||||
lockMetrics.recordRelease(
|
||||
resourceName,
|
||||
tld,
|
||||
new Duration(acquiredTime, transactionManager.getTransactionTime()));
|
||||
resourceName, scope, new Duration(acquiredTime, jpaTm().getTransactionTime()));
|
||||
} else {
|
||||
logger.atSevere().log(
|
||||
"The lock we acquired was transferred to someone else before we"
|
||||
+ " released it! Did action take longer than lease length?"
|
||||
+ " Our lock: %s, current lock: %s",
|
||||
Lock.this, loadedLock);
|
||||
this, loadedLock);
|
||||
logger.atInfo().log(
|
||||
"Not deleting lock: %s - someone else has it: %s", lockId, loadedLock);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
// In ofy, backup is determined per-action, but in SQL it's determined per-transaction
|
||||
if (transactionManager.isOfy()) {
|
||||
transactionManager.transact(lockReleaser);
|
||||
} else {
|
||||
((JpaTransactionManager) transactionManager).transactWithoutBackup(lockReleaser);
|
||||
}
|
||||
jpaTm().transactWithoutBackup(lockReleaser);
|
||||
}
|
||||
|
||||
static class LockId extends ImmutableObject implements Serializable {
|
||||
|
||||
String resourceName;
|
||||
|
||||
// TODO(b/177567432): rename to "scope" post-Datastore
|
||||
@Column(name = "scope")
|
||||
String tld;
|
||||
String scope;
|
||||
|
||||
// Required for Hibernate
|
||||
@SuppressWarnings("unused")
|
||||
private LockId() {}
|
||||
|
||||
LockId(String resourceName, String tld) {
|
||||
LockId(String resourceName, String scope) {
|
||||
this.resourceName = checkArgumentNotNull(resourceName, "The resource name cannot be null");
|
||||
this.tld = checkArgumentNotNull(tld, "Scope of a lock cannot be null");
|
||||
this.scope = checkArgumentNotNull(scope, "Scope of a lock cannot be null");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ public class EppHistoryVKeyTranslatorFactory
|
||||
// one dedicated VKey class, e.g. DomainHistoryVKey, for each such kind of entity, and we need
|
||||
// a way to map the raw Datastore key to its VKey class. So, we use the kind path as the key of
|
||||
// the map, and the kind path is created by concatenating all the kind strings in a raw Datastore
|
||||
// key, e.g. the map key for ContactPollMessageVKey is "ContactResource/HistoryEntry/PollMessage".
|
||||
// key, e.g. the map key for ContactPollMessageVKey is "Contact/HistoryEntry/PollMessage".
|
||||
@VisibleForTesting
|
||||
static final ImmutableMap<String, Class<? extends EppHistoryVKey>> kindPathToVKeyClass =
|
||||
ImmutableSet.of(DomainHistoryVKey.class).stream()
|
||||
|
||||
@@ -38,8 +38,8 @@ import javax.persistence.MappedSuperclass;
|
||||
*/
|
||||
@MappedSuperclass
|
||||
@Access(AccessType.FIELD)
|
||||
public abstract class EppHistoryVKey<K, E extends EppResource> extends ImmutableObject
|
||||
implements Serializable {
|
||||
public abstract class EppHistoryVKey<K extends ImmutableObject, E extends EppResource>
|
||||
extends ImmutableObject implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -3906580677709539818L;
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ import static google.registry.request.Action.Method.HEAD;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.primitives.Longs;
|
||||
import com.google.re2j.Pattern;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.rdap.RdapJsonFormatter.OutputDataType;
|
||||
@@ -69,14 +69,14 @@ public class RdapEntityAction extends RdapActionBase {
|
||||
// RDAP Technical Implementation Guide 2.3.1 - MUST support contact entity lookup using the
|
||||
// handle
|
||||
if (ROID_PATTERN.matcher(pathSearchString).matches()) {
|
||||
VKey<ContactResource> contactVKey = VKey.create(ContactResource.class, pathSearchString);
|
||||
Optional<ContactResource> contactResource =
|
||||
VKey<Contact> contactVKey = VKey.create(Contact.class, pathSearchString);
|
||||
Optional<Contact> contact =
|
||||
replicaJpaTm().transact(() -> replicaJpaTm().loadByKeyIfPresent(contactVKey));
|
||||
// As per Andy Newton on the regext mailing list, contacts by themselves have no role, since
|
||||
// they are global, and might have different roles for different domains.
|
||||
if (contactResource.isPresent() && isAuthorized(contactResource.get())) {
|
||||
if (contact.isPresent() && isAuthorized(contact.get())) {
|
||||
return rdapJsonFormatter.createRdapContactEntity(
|
||||
contactResource.get(), ImmutableSet.of(), OutputDataType.FULL);
|
||||
contact.get(), ImmutableSet.of(), OutputDataType.FULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ import com.google.common.collect.Streams;
|
||||
import com.google.common.primitives.Booleans;
|
||||
import com.google.common.primitives.Longs;
|
||||
import com.googlecode.objectify.cmd.Query;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.persistence.transaction.CriteriaQueryBuilder;
|
||||
@@ -253,7 +253,7 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
|
||||
// see any names anyway. Also, if a registrar cursor is present, we have already moved past the
|
||||
// contacts, and don't need to fetch them this time. We can skip contacts if subtype is
|
||||
// REGISTRARS.
|
||||
RdapResultSet<ContactResource> resultSet;
|
||||
RdapResultSet<Contact> resultSet;
|
||||
if (subtype == Subtype.REGISTRARS) {
|
||||
resultSet = RdapResultSet.create(ImmutableList.of());
|
||||
} else {
|
||||
@@ -262,9 +262,9 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
|
||||
resultSet = RdapResultSet.create(ImmutableList.of());
|
||||
} else {
|
||||
if (tm().isOfy()) {
|
||||
Query<ContactResource> query =
|
||||
Query<Contact> query =
|
||||
queryItems(
|
||||
ContactResource.class,
|
||||
Contact.class,
|
||||
"searchName",
|
||||
partialStringQuery,
|
||||
cursorQueryString, // if we get here and there's a cursor, it must be a contact
|
||||
@@ -279,9 +279,9 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
|
||||
replicaJpaTm()
|
||||
.transact(
|
||||
() -> {
|
||||
CriteriaQueryBuilder<ContactResource> builder =
|
||||
CriteriaQueryBuilder<Contact> builder =
|
||||
queryItemsSql(
|
||||
ContactResource.class,
|
||||
Contact.class,
|
||||
"searchName",
|
||||
partialStringQuery,
|
||||
cursorQueryString,
|
||||
@@ -319,21 +319,20 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
|
||||
}
|
||||
// Handle queries without a wildcard (and not including deleted) -- load by ID.
|
||||
if (!partialStringQuery.getHasWildcard() && !shouldIncludeDeleted()) {
|
||||
ImmutableList<ContactResource> contactResourceList;
|
||||
ImmutableList<Contact> contactList;
|
||||
if (subtype == Subtype.REGISTRARS) {
|
||||
contactResourceList = ImmutableList.of();
|
||||
contactList = ImmutableList.of();
|
||||
} else {
|
||||
Optional<ContactResource> contactResource =
|
||||
Optional<Contact> contact =
|
||||
replicaJpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
replicaJpaTm()
|
||||
.loadByKeyIfPresent(
|
||||
VKey.create(
|
||||
ContactResource.class, partialStringQuery.getInitialString())));
|
||||
contactResourceList =
|
||||
(contactResource.isPresent() && shouldBeVisible(contactResource.get()))
|
||||
? ImmutableList.of(contactResource.get())
|
||||
VKey.create(Contact.class, partialStringQuery.getInitialString())));
|
||||
contactList =
|
||||
(contact.isPresent() && shouldBeVisible(contact.get()))
|
||||
? ImmutableList.of(contact.get())
|
||||
: ImmutableList.of();
|
||||
}
|
||||
ImmutableList<Registrar> registrarList;
|
||||
@@ -343,9 +342,9 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
|
||||
registrarList = getMatchingRegistrars(partialStringQuery.getInitialString());
|
||||
}
|
||||
return makeSearchResults(
|
||||
contactResourceList,
|
||||
contactList,
|
||||
IncompletenessWarningType.COMPLETE,
|
||||
contactResourceList.size(),
|
||||
contactList.size(),
|
||||
registrarList,
|
||||
QueryType.HANDLE);
|
||||
// Handle queries with a wildcard (or including deleted), but no suffix. Because the handle
|
||||
@@ -383,7 +382,7 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
|
||||
// get excluded due to permissioning. Any cursor present must be a contact cursor, because we
|
||||
// would never return a registrar for this search.
|
||||
int querySizeLimit = getStandardQuerySizeLimit();
|
||||
RdapResultSet<ContactResource> contactResultSet;
|
||||
RdapResultSet<Contact> contactResultSet;
|
||||
if (subtype == Subtype.REGISTRARS) {
|
||||
contactResultSet = RdapResultSet.create(ImmutableList.of());
|
||||
} else {
|
||||
@@ -391,7 +390,7 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
|
||||
contactResultSet =
|
||||
getMatchingResources(
|
||||
queryItemsByKey(
|
||||
ContactResource.class,
|
||||
Contact.class,
|
||||
partialStringQuery,
|
||||
cursorQueryString,
|
||||
getDeletedItemHandling(),
|
||||
@@ -405,7 +404,7 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
|
||||
() ->
|
||||
getMatchingResourcesSql(
|
||||
queryItemsByKeySql(
|
||||
ContactResource.class,
|
||||
Contact.class,
|
||||
partialStringQuery,
|
||||
cursorQueryString,
|
||||
getDeletedItemHandling()),
|
||||
@@ -436,7 +435,7 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
|
||||
* properties of the {@link RdapResultSet} structure and passes them as separate arguments.
|
||||
*/
|
||||
private EntitySearchResponse makeSearchResults(
|
||||
RdapResultSet<ContactResource> resultSet, List<Registrar> registrars, QueryType queryType) {
|
||||
RdapResultSet<Contact> resultSet, List<Registrar> registrars, QueryType queryType) {
|
||||
return makeSearchResults(
|
||||
resultSet.resources(),
|
||||
resultSet.incompletenessWarningType(),
|
||||
@@ -461,7 +460,7 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
|
||||
* @return an {@link RdapSearchResults} object
|
||||
*/
|
||||
private EntitySearchResponse makeSearchResults(
|
||||
List<ContactResource> contacts,
|
||||
List<Contact> contacts,
|
||||
IncompletenessWarningType incompletenessWarningType,
|
||||
int numContactsRetrieved,
|
||||
List<Registrar> registrars,
|
||||
@@ -485,7 +484,7 @@ public class RdapEntitySearchAction extends RdapSearchActionBase {
|
||||
EntitySearchResponse.builder()
|
||||
.setIncompletenessWarningType(incompletenessWarningType);
|
||||
Optional<String> newCursor = Optional.empty();
|
||||
for (ContactResource contact : Iterables.limit(contacts, rdapResultSetMaxSize)) {
|
||||
for (Contact contact : Iterables.limit(contacts, rdapResultSetMaxSize)) {
|
||||
// As per Andy Newton on the regext mailing list, contacts by themselves have no role, since
|
||||
// they are global, and might have different roles for different domains.
|
||||
builder
|
||||
|
||||
@@ -39,9 +39,9 @@ import com.google.common.net.InetAddresses;
|
||||
import com.google.gson.JsonArray;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactAddress;
|
||||
import google.registry.model.contact.ContactPhoneNumber;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.PostalInfo;
|
||||
import google.registry.model.domain.DesignatedContact;
|
||||
import google.registry.model.domain.DesignatedContact.Type;
|
||||
@@ -363,7 +363,7 @@ public class RdapJsonFormatter {
|
||||
ImmutableSet.copyOf(
|
||||
replicaJpaTm().loadByKeys(domain.getNameservers()).values()));
|
||||
// Load the registrant and other contacts and add them to the data.
|
||||
ImmutableMap<VKey<? extends ContactResource>, ContactResource> loadedContacts =
|
||||
ImmutableMap<VKey<? extends Contact>, Contact> loadedContacts =
|
||||
replicaJpaTm()
|
||||
.transact(() -> replicaJpaTm().loadByKeysIfPresent(domain.getReferencedContacts()));
|
||||
// RDAP Response Profile 2.7.3, A domain MUST have the REGISTRANT, ADMIN, TECH roles and MAY
|
||||
@@ -373,7 +373,7 @@ public class RdapJsonFormatter {
|
||||
// fields we don't want to show (as opposed to not having contacts at all) because of GDPR etc.
|
||||
//
|
||||
// the GDPR redaction is handled in createRdapContactEntity
|
||||
ImmutableSetMultimap<VKey<ContactResource>, Type> contactsToRoles =
|
||||
ImmutableSetMultimap<VKey<Contact>, Type> contactsToRoles =
|
||||
Streams.concat(
|
||||
domain.getContacts().stream(),
|
||||
Stream.of(DesignatedContact.create(Type.REGISTRANT, domain.getRegistrant())))
|
||||
@@ -382,7 +382,7 @@ public class RdapJsonFormatter {
|
||||
toImmutableSetMultimap(
|
||||
DesignatedContact::getContactKey, DesignatedContact::getType));
|
||||
|
||||
for (VKey<ContactResource> contactKey : contactsToRoles.keySet()) {
|
||||
for (VKey<Contact> contactKey : contactsToRoles.keySet()) {
|
||||
Set<RdapEntity.Role> roles =
|
||||
contactsToRoles.get(contactKey).stream()
|
||||
.map(RdapJsonFormatter::convertContactTypeToRdapRole)
|
||||
@@ -495,16 +495,14 @@ public class RdapJsonFormatter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JSON object for a {@link ContactResource} and associated contact type.
|
||||
* Creates a JSON object for a {@link Contact} and associated contact type.
|
||||
*
|
||||
* @param contactResource the contact resource object from which the JSON object should be created
|
||||
* @param contact the contact resource object from which the JSON object should be created
|
||||
* @param roles the roles of this contact
|
||||
* @param outputDataType whether to generate full or summary data
|
||||
*/
|
||||
RdapContactEntity createRdapContactEntity(
|
||||
ContactResource contactResource,
|
||||
Iterable<RdapEntity.Role> roles,
|
||||
OutputDataType outputDataType) {
|
||||
Contact contact, Iterable<RdapEntity.Role> roles, OutputDataType outputDataType) {
|
||||
RdapContactEntity.Builder contactBuilder = RdapContactEntity.builder();
|
||||
|
||||
// RDAP Response Profile 2.7.1, 2.7.3 - we MUST have the contacts. 2.7.4 discusses censoring of
|
||||
@@ -512,12 +510,12 @@ public class RdapJsonFormatter {
|
||||
//
|
||||
// 2.8 allows for unredacted output for authorized people.
|
||||
boolean isAuthorized =
|
||||
rdapAuthorization.isAuthorizedForRegistrar(contactResource.getCurrentSponsorRegistrarId());
|
||||
rdapAuthorization.isAuthorizedForRegistrar(contact.getCurrentSponsorRegistrarId());
|
||||
|
||||
// ROID needs to be redacted if we aren't authorized, so we can't have a self-link for
|
||||
// unauthorized users
|
||||
if (isAuthorized) {
|
||||
contactBuilder.linksBuilder().add(makeSelfLink("entity", contactResource.getRepoId()));
|
||||
contactBuilder.linksBuilder().add(makeSelfLink("entity", contact.getRepoId()));
|
||||
}
|
||||
|
||||
// Only show the "summary data remark" if the user is authorized to see this data - because
|
||||
@@ -544,10 +542,10 @@ public class RdapJsonFormatter {
|
||||
.remarksBuilder()
|
||||
.add(RdapIcannStandardInformation.CONTACT_PERSONAL_DATA_HIDDEN_DATA_REMARK);
|
||||
// to make sure we don't accidentally display data we shouldn't - we replace the
|
||||
// contactResource with a safe resource. Then we can add any information we need (e.g. the
|
||||
// contact with a safe resource. Then we can add any information we need (e.g. the
|
||||
// Organization / state / country of the registrant), although we currently don't do that.
|
||||
contactResource =
|
||||
new ContactResource.Builder()
|
||||
contact =
|
||||
new Contact.Builder()
|
||||
.setRepoId(CONTACT_REDACTED_VALUE)
|
||||
.setVoiceNumber(
|
||||
new ContactPhoneNumber.Builder().setPhoneNumber(CONTACT_REDACTED_VALUE).build())
|
||||
@@ -572,7 +570,7 @@ public class RdapJsonFormatter {
|
||||
|
||||
// RDAP Response Profile 2.7.3 - we MUST provide a handle set with the ROID, subject to the
|
||||
// redaction above.
|
||||
contactBuilder.setHandle(contactResource.getRepoId());
|
||||
contactBuilder.setHandle(contact.getRepoId());
|
||||
|
||||
// RDAP Response Profile doesn't mention status for contacts, so we only show it if we're both
|
||||
// FULL and Authorized.
|
||||
@@ -581,11 +579,11 @@ public class RdapJsonFormatter {
|
||||
.statusBuilder()
|
||||
.addAll(
|
||||
makeStatusValueList(
|
||||
isLinked(contactResource.createVKey(), getRequestTime())
|
||||
? union(contactResource.getStatusValues(), StatusValue.LINKED)
|
||||
: contactResource.getStatusValues(),
|
||||
isLinked(contact.createVKey(), getRequestTime())
|
||||
? union(contact.getStatusValues(), StatusValue.LINKED)
|
||||
: contact.getStatusValues(),
|
||||
false,
|
||||
contactResource.getDeletionTime().isBefore(getRequestTime())));
|
||||
contact.getDeletionTime().isBefore(getRequestTime())));
|
||||
}
|
||||
|
||||
contactBuilder.rolesBuilder().addAll(roles);
|
||||
@@ -596,9 +594,9 @@ public class RdapJsonFormatter {
|
||||
// RDAP Response Profile 2.7.3 - we MUST have FN, ADR, TEL, EMAIL.
|
||||
//
|
||||
// Note that 2.7.5 also says the EMAIL must be omitted, so we'll omit it
|
||||
PostalInfo postalInfo = contactResource.getInternationalizedPostalInfo();
|
||||
PostalInfo postalInfo = contact.getInternationalizedPostalInfo();
|
||||
if (postalInfo == null) {
|
||||
postalInfo = contactResource.getLocalizedPostalInfo();
|
||||
postalInfo = contact.getLocalizedPostalInfo();
|
||||
}
|
||||
if (postalInfo != null) {
|
||||
if (postalInfo.getName() != null) {
|
||||
@@ -609,11 +607,11 @@ public class RdapJsonFormatter {
|
||||
}
|
||||
addVCardAddressEntry(vcardBuilder, postalInfo.getAddress());
|
||||
}
|
||||
ContactPhoneNumber voicePhoneNumber = contactResource.getVoiceNumber();
|
||||
ContactPhoneNumber voicePhoneNumber = contact.getVoiceNumber();
|
||||
if (voicePhoneNumber != null) {
|
||||
vcardBuilder.add(makePhoneEntry(PHONE_TYPE_VOICE, makePhoneString(voicePhoneNumber)));
|
||||
}
|
||||
ContactPhoneNumber faxPhoneNumber = contactResource.getFaxNumber();
|
||||
ContactPhoneNumber faxPhoneNumber = contact.getFaxNumber();
|
||||
if (faxPhoneNumber != null) {
|
||||
vcardBuilder.add(makePhoneEntry(PHONE_TYPE_FAX, makePhoneString(faxPhoneNumber)));
|
||||
}
|
||||
@@ -641,7 +639,7 @@ public class RdapJsonFormatter {
|
||||
// We also only add it for authorized users because millisecond times can fingerprint a user
|
||||
// just as much as the handle can.
|
||||
if (outputDataType == OutputDataType.FULL && isAuthorized) {
|
||||
contactBuilder.eventsBuilder().addAll(makeOptionalEvents(contactResource));
|
||||
contactBuilder.eventsBuilder().addAll(makeOptionalEvents(contact));
|
||||
}
|
||||
return contactBuilder.build();
|
||||
}
|
||||
|
||||
+8
-8
@@ -16,9 +16,9 @@ package google.registry.rde;
|
||||
|
||||
import static google.registry.util.XmlEnumUtils.enumToXml;
|
||||
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactAddress;
|
||||
import google.registry.model.contact.ContactPhoneNumber;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Disclose;
|
||||
import google.registry.model.contact.Disclose.PostalInfoChoice;
|
||||
import google.registry.model.contact.PostalInfo;
|
||||
@@ -39,16 +39,16 @@ import google.registry.xjc.rdecontact.XjcRdeContactTransferDataType;
|
||||
import javax.annotation.CheckForNull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/** Utility class that turns {@link ContactResource} as {@link XjcRdeContactElement}. */
|
||||
final class ContactResourceToXjcConverter {
|
||||
/** Utility class that turns {@link Contact} as {@link XjcRdeContactElement}. */
|
||||
final class ContactToXjcConverter {
|
||||
|
||||
/** Converts {@link ContactResource} to {@link XjcRdeContactElement}. */
|
||||
static XjcRdeContactElement convert(ContactResource host) {
|
||||
/** Converts {@link Contact} to {@link XjcRdeContactElement}. */
|
||||
static XjcRdeContactElement convert(Contact host) {
|
||||
return new XjcRdeContactElement(convertContact(host));
|
||||
}
|
||||
|
||||
/** Converts {@link ContactResource} to {@link XjcRdeContact}. */
|
||||
static XjcRdeContact convertContact(ContactResource model) {
|
||||
/** Converts {@link Contact} to {@link XjcRdeContact}. */
|
||||
static XjcRdeContact convertContact(Contact model) {
|
||||
XjcRdeContact bean = new XjcRdeContact();
|
||||
bean.setRoid(model.getRepoId());
|
||||
for (StatusValue status : model.getStatusValues()) {
|
||||
@@ -188,5 +188,5 @@ final class ContactResourceToXjcConverter {
|
||||
return bean;
|
||||
}
|
||||
|
||||
private ContactResourceToXjcConverter() {}
|
||||
private ContactToXjcConverter() {}
|
||||
}
|
||||
@@ -21,7 +21,7 @@ import com.google.common.base.Ascii;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.domain.DesignatedContact;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||
@@ -168,11 +168,11 @@ final class DomainToXjcConverter {
|
||||
// o An OPTIONAL <registrant> element that contain the identifier for
|
||||
// the human or organizational social information object associated
|
||||
// as the holder of the domain name object.
|
||||
VKey<ContactResource> registrant = model.getRegistrant();
|
||||
VKey<Contact> registrant = model.getRegistrant();
|
||||
if (registrant == null) {
|
||||
logger.atWarning().log("Domain %s has no registrant contact.", domainName);
|
||||
} else {
|
||||
ContactResource registrantContact = tm().transact(() -> tm().loadByKey(registrant));
|
||||
Contact registrantContact = tm().transact(() -> tm().loadByKey(registrant));
|
||||
checkState(
|
||||
registrantContact != null,
|
||||
"Registrant contact %s on domain %s does not exist",
|
||||
@@ -304,7 +304,7 @@ final class DomainToXjcConverter {
|
||||
"Contact key for type %s is null on domain %s",
|
||||
model.getType(),
|
||||
domainName);
|
||||
ContactResource contact = tm().transact(() -> tm().loadByKey(model.getContactKey()));
|
||||
Contact contact = tm().transact(() -> tm().loadByKey(model.getContactKey()));
|
||||
checkState(
|
||||
contact != null,
|
||||
"Contact %s on domain %s does not exist",
|
||||
|
||||
@@ -20,7 +20,7 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.model.rde.RdeMode;
|
||||
@@ -66,8 +66,8 @@ public class RdeFragmenter {
|
||||
result = Optional.of(marshaller.marshalDomain((Domain) resource, mode));
|
||||
cache.put(WatermarkModePair.create(watermark, mode), result);
|
||||
return result;
|
||||
} else if (resource instanceof ContactResource) {
|
||||
result = Optional.of(marshaller.marshalContact((ContactResource) resource));
|
||||
} else if (resource instanceof Contact) {
|
||||
result = Optional.of(marshaller.marshalContact((Contact) resource));
|
||||
cache.put(WatermarkModePair.create(watermark, RdeMode.FULL), result);
|
||||
cache.put(WatermarkModePair.create(watermark, RdeMode.THIN), result);
|
||||
return result;
|
||||
|
||||
@@ -20,7 +20,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.model.rde.RdeMode;
|
||||
@@ -117,10 +117,10 @@ public final class RdeMarshaller implements Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
/** Turns {@link ContactResource} object into an XML fragment. */
|
||||
public DepositFragment marshalContact(ContactResource contact) {
|
||||
return marshalResource(RdeResourceType.CONTACT, contact,
|
||||
ContactResourceToXjcConverter.convert(contact));
|
||||
/** Turns {@link Contact} object into an XML fragment. */
|
||||
public DepositFragment marshalContact(Contact contact) {
|
||||
return marshalResource(
|
||||
RdeResourceType.CONTACT, contact, ContactToXjcConverter.convert(contact));
|
||||
}
|
||||
|
||||
/** Turns {@link Domain} object into an XML fragment. */
|
||||
|
||||
@@ -45,7 +45,7 @@ import google.registry.gcs.GcsUtils;
|
||||
import google.registry.keyring.api.KeyModule.Key;
|
||||
import google.registry.model.common.Cursor;
|
||||
import google.registry.model.common.Cursor.CursorType;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.model.index.EppResourceIndex;
|
||||
@@ -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 Host}s that are referenced by an included {@link
|
||||
* Domain} will be included in the corresponding pending deposit.
|
||||
* <p>Only {@link Contact}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.
|
||||
|
||||
@@ -38,26 +38,5 @@ public interface LockHandler extends Serializable {
|
||||
* @return true if all locks were acquired and the callable was run; false otherwise.
|
||||
*/
|
||||
boolean executeWithLocks(
|
||||
final Callable<Void> callable,
|
||||
@Nullable String tld,
|
||||
Duration leaseLength,
|
||||
String... lockNames);
|
||||
|
||||
/**
|
||||
* Acquire one or more locks using only Cloud SQL and execute a Void {@link Callable}.
|
||||
*
|
||||
* <p>Runs on a thread that will be killed if it doesn't complete before the lease expires.
|
||||
*
|
||||
* <p>Note that locks are specific either to a given tld or to the entire system (in which case
|
||||
* tld should be passed as null).
|
||||
*
|
||||
* <p>This method exists so that Beam pipelines can acquire / load / release locks.
|
||||
*
|
||||
* @return true if all locks were acquired and the callable was run; false otherwise.
|
||||
*/
|
||||
boolean executeWithSqlLocks(
|
||||
final Callable<Void> callable,
|
||||
@Nullable String tld,
|
||||
Duration leaseLength,
|
||||
String... lockNames);
|
||||
Callable<Void> callable, @Nullable String tld, Duration leaseLength, String... lockNames);
|
||||
}
|
||||
|
||||
@@ -76,27 +76,6 @@ public class LockHandlerImpl implements LockHandler {
|
||||
return executeWithLockAcquirer(callable, tld, leaseLength, this::acquire, lockNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquire one or more locks using only Cloud SQL and execute a Void {@link Callable}.
|
||||
*
|
||||
* <p>Thread will be killed if it doesn't complete before the lease expires.
|
||||
*
|
||||
* <p>Note that locks are specific either to a given tld or to the entire system (in which case
|
||||
* tld should be passed as null).
|
||||
*
|
||||
* <p>This method exists so that Beam pipelines can acquire / load / release locks.
|
||||
*
|
||||
* @return whether all locks were acquired and the callable was run.
|
||||
*/
|
||||
@Override
|
||||
public boolean executeWithSqlLocks(
|
||||
final Callable<Void> callable,
|
||||
@Nullable String tld,
|
||||
Duration leaseLength,
|
||||
String... lockNames) {
|
||||
return executeWithLockAcquirer(callable, tld, leaseLength, this::acquireSql, lockNames);
|
||||
}
|
||||
|
||||
private boolean executeWithLockAcquirer(
|
||||
final Callable<Void> callable,
|
||||
@Nullable String tld,
|
||||
@@ -138,11 +117,6 @@ public class LockHandlerImpl implements LockHandler {
|
||||
return Lock.acquire(lockName, tld, leaseLength, requestStatusChecker, true);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
Optional<Lock> acquireSql(String lockName, @Nullable String tld, Duration leaseLength) {
|
||||
return Lock.acquireSql(lockName, tld, leaseLength, requestStatusChecker, true);
|
||||
}
|
||||
|
||||
private interface LockAcquirer {
|
||||
Optional<Lock> acquireLock(String lockName, @Nullable String tld, Duration leaseLength);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import static com.google.common.base.Preconditions.checkState;
|
||||
import com.google.common.base.Ascii;
|
||||
import com.google.common.base.Strings;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.model.index.ForeignKeyIndex;
|
||||
@@ -31,7 +31,7 @@ class CommandUtilities {
|
||||
|
||||
/** A useful parameter enum for commands that operate on {@link EppResource} objects. */
|
||||
public enum ResourceType {
|
||||
CONTACT(ContactResource.class),
|
||||
CONTACT(Contact.class),
|
||||
HOST(Host.class),
|
||||
DOMAIN(Domain.class);
|
||||
|
||||
|
||||
@@ -314,7 +314,7 @@ class GenerateAllocationTokensCommand implements CommandWithRemoteApi {
|
||||
private ImmutableSet<String> getExistingTokenStrings(ImmutableSet<String> candidates) {
|
||||
ImmutableSet<VKey<AllocationToken>> existingTokenKeys =
|
||||
candidates.stream()
|
||||
.map(input -> VKey.create(AllocationToken.class, input))
|
||||
.map(input -> VKey.createSql(AllocationToken.class, input))
|
||||
.collect(toImmutableSet());
|
||||
return tm().transact(
|
||||
() ->
|
||||
|
||||
@@ -47,7 +47,7 @@ final class GetAllocationTokenCommand implements CommandWithRemoteApi {
|
||||
for (List<String> tokens : Lists.partition(mainParameters, BATCH_SIZE)) {
|
||||
ImmutableList<VKey<AllocationToken>> tokenKeys =
|
||||
tokens.stream()
|
||||
.map(t -> VKey.create(AllocationToken.class, t))
|
||||
.map(t -> VKey.createSql(AllocationToken.class, t))
|
||||
.collect(toImmutableList());
|
||||
tm().transact(
|
||||
() ->
|
||||
|
||||
@@ -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.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import java.util.List;
|
||||
|
||||
/** Command to show one or more contacts. */
|
||||
@@ -34,7 +34,7 @@ final class GetContactCommand extends GetEppResourceCommand {
|
||||
public void runAndPrint() {
|
||||
for (String contactId : mainParameters) {
|
||||
printResource(
|
||||
"Contact", contactId, loadByForeignKey(ContactResource.class, contactId, readTimestamp));
|
||||
"Contact", contactId, loadByForeignKey(Contact.class, contactId, readTimestamp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ abstract class UpdateOrDeleteAllocationTokensCommand extends ConfirmingCommand
|
||||
if (tokens != null) {
|
||||
ImmutableSet<VKey<AllocationToken>> keys =
|
||||
tokens.stream()
|
||||
.map(token -> VKey.create(AllocationToken.class, token))
|
||||
.map(token -> VKey.createSql(AllocationToken.class, token))
|
||||
.collect(toImmutableSet());
|
||||
ImmutableSet<VKey<AllocationToken>> nonexistentKeys =
|
||||
tm().transact(
|
||||
|
||||
@@ -15,13 +15,13 @@
|
||||
package google.registry.tools.params;
|
||||
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.domain.Domain;
|
||||
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),
|
||||
CONTACT(Contact.class),
|
||||
DOMAIN(Domain.class),
|
||||
HOST(Host.class);
|
||||
|
||||
|
||||
@@ -23,8 +23,8 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactPhoneNumber;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.PostalInfo;
|
||||
import google.registry.model.domain.DesignatedContact;
|
||||
import google.registry.model.domain.DesignatedContact.Type;
|
||||
@@ -124,7 +124,7 @@ final class DomainWhoisResponse extends WhoisResponseImpl {
|
||||
}
|
||||
|
||||
/** Returns the contact of the given type. */
|
||||
private Optional<VKey<ContactResource>> getContactReference(Type type) {
|
||||
private Optional<VKey<Contact>> getContactReference(Type type) {
|
||||
Optional<DesignatedContact> contactOfType =
|
||||
domain.getContacts().stream().filter(d -> d.getType() == type).findFirst();
|
||||
return contactOfType.map(DesignatedContact::getContactKey);
|
||||
@@ -145,15 +145,15 @@ final class DomainWhoisResponse extends WhoisResponseImpl {
|
||||
|
||||
/** Emit the contact entry of the given type. */
|
||||
DomainEmitter emitContact(
|
||||
String contactType, Optional<VKey<ContactResource>> contact, boolean preferUnicode) {
|
||||
String contactType, Optional<VKey<Contact>> contact, boolean preferUnicode) {
|
||||
if (!contact.isPresent()) {
|
||||
return this;
|
||||
}
|
||||
// If we refer to a contact that doesn't exist, that's a bug. It means referential integrity
|
||||
// has somehow been broken. We skip the rest of this contact, but log it to hopefully bring it
|
||||
// someone's attention.
|
||||
ContactResource contactResource = EppResource.loadCached(contact.get());
|
||||
if (contactResource == null) {
|
||||
Contact contact1 = EppResource.loadCached(contact.get());
|
||||
if (contact1 == null) {
|
||||
logger.atSevere().log(
|
||||
"(BUG) Broken reference found from domain %s to contact %s.",
|
||||
domain.getDomainName(), contact);
|
||||
@@ -162,11 +162,10 @@ final class DomainWhoisResponse extends WhoisResponseImpl {
|
||||
PostalInfo postalInfo =
|
||||
chooseByUnicodePreference(
|
||||
preferUnicode,
|
||||
contactResource.getLocalizedPostalInfo(),
|
||||
contactResource.getInternationalizedPostalInfo());
|
||||
contact1.getLocalizedPostalInfo(),
|
||||
contact1.getInternationalizedPostalInfo());
|
||||
// ICANN Consistent Labeling & Display policy requires that this be the ROID.
|
||||
emitField(
|
||||
ImmutableList.of("Registry", contactType, "ID"), contactResource.getRepoId(), fullOutput);
|
||||
emitField(ImmutableList.of("Registry", contactType, "ID"), contact1.getRepoId(), fullOutput);
|
||||
if (postalInfo != null) {
|
||||
emitFieldIfDefined(ImmutableList.of(contactType, "Name"), postalInfo.getName(), fullOutput);
|
||||
emitFieldIfDefined(
|
||||
@@ -175,10 +174,9 @@ final class DomainWhoisResponse extends WhoisResponseImpl {
|
||||
fullOutput || contactType.equals("Registrant"));
|
||||
emitAddress(contactType, postalInfo.getAddress(), fullOutput);
|
||||
}
|
||||
emitPhone(contactType, "Phone", contactResource.getVoiceNumber());
|
||||
emitPhone(contactType, "Fax", contactResource.getFaxNumber());
|
||||
String emailFieldContent =
|
||||
fullOutput ? contactResource.getEmailAddress() : whoisRedactedEmailText;
|
||||
emitPhone(contactType, "Phone", contact1.getVoiceNumber());
|
||||
emitPhone(contactType, "Fax", contact1.getFaxNumber());
|
||||
String emailFieldContent = fullOutput ? contact1.getEmailAddress() : whoisRedactedEmailText;
|
||||
emitField(ImmutableList.of(contactType, "Email"), emailFieldContent);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<schema targetNamespace="urn:google:params:xml:ns:packageToken-1.0"
|
||||
xmlns:packageToken="urn:google:params:xml:ns:packageToken-1.0"
|
||||
xmlns="http://www.w3.org/2001/XMLSchema"
|
||||
elementFormDefault="qualified">
|
||||
|
||||
<annotation>
|
||||
<documentation>
|
||||
Extensible Provisioning Protocol v1.0
|
||||
Package Token Extension.
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
<!-- Element used in info command request to get a package token for a domain. -->
|
||||
<element name="info"
|
||||
type="packageToken:infoType"/>
|
||||
|
||||
<complexType name="infoType"/>
|
||||
|
||||
<!-- Element returned in an info command response with a package token for a package domain. -->
|
||||
<element name="packageData"
|
||||
type="packageToken:packageDataType"/>
|
||||
|
||||
<complexType name="packageDataType">
|
||||
<sequence>
|
||||
<element name="token" type="packageToken:tokenType" maxOccurs="unbounded"/>
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<simpleType name="tokenType">
|
||||
<restriction base="string">
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
|
||||
<!-- End of schema.-->
|
||||
</schema>
|
||||
@@ -45,7 +45,7 @@
|
||||
<class>google.registry.model.common.DatabaseMigrationStateSchedule</class>
|
||||
<class>google.registry.model.console.User</class>
|
||||
<class>google.registry.model.contact.ContactHistory</class>
|
||||
<class>google.registry.model.contact.ContactResource</class>
|
||||
<class>google.registry.model.contact.Contact</class>
|
||||
<class>google.registry.model.domain.Domain</class>
|
||||
<class>google.registry.model.domain.DomainHistory</class>
|
||||
<class>google.registry.model.domain.GracePeriod</class>
|
||||
@@ -104,7 +104,7 @@
|
||||
<class>google.registry.model.billing.VKeyConverter_Cancellation</class>
|
||||
<class>google.registry.model.billing.VKeyConverter_OneTime</class>
|
||||
<class>google.registry.model.billing.VKeyConverter_Recurring</class>
|
||||
<class>google.registry.model.contact.VKeyConverter_ContactResource</class>
|
||||
<class>google.registry.model.contact.VKeyConverter_Contact</class>
|
||||
<class>google.registry.model.domain.VKeyConverter_Domain</class>
|
||||
<class>google.registry.model.domain.token.VKeyConverter_AllocationToken</class>
|
||||
<class>google.registry.model.host.VKeyConverter_Host</class>
|
||||
|
||||
@@ -27,7 +27,7 @@ import static org.joda.time.Duration.standardSeconds;
|
||||
|
||||
import com.google.cloud.tasks.v2.HttpMethod;
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.CloudTasksHelper;
|
||||
import google.registry.testing.CloudTasksHelper.TaskMatcher;
|
||||
@@ -80,7 +80,7 @@ public class AsyncTaskEnqueuerTest {
|
||||
|
||||
@Test
|
||||
void test_enqueueAsyncResave_success() {
|
||||
ContactResource contact = persistActiveContact("jd23456");
|
||||
Contact contact = persistActiveContact("jd23456");
|
||||
asyncTaskEnqueuer.enqueueAsyncResave(
|
||||
contact.createVKey(), clock.nowUtc(), clock.nowUtc().plusDays(5));
|
||||
cloudTasksHelper.assertTasksEnqueued(
|
||||
@@ -97,7 +97,7 @@ public class AsyncTaskEnqueuerTest {
|
||||
|
||||
@Test
|
||||
void test_enqueueAsyncResave_multipleResaves() {
|
||||
ContactResource contact = persistActiveContact("jd23456");
|
||||
Contact contact = persistActiveContact("jd23456");
|
||||
DateTime now = clock.nowUtc();
|
||||
asyncTaskEnqueuer.enqueueAsyncResave(
|
||||
contact.createVKey(),
|
||||
@@ -119,7 +119,7 @@ public class AsyncTaskEnqueuerTest {
|
||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
@Test
|
||||
void test_enqueueAsyncResave_ignoresTasksTooFarIntoFuture() {
|
||||
ContactResource contact = persistActiveContact("jd23456");
|
||||
Contact contact = persistActiveContact("jd23456");
|
||||
asyncTaskEnqueuer.enqueueAsyncResave(
|
||||
contact.createVKey(), clock.nowUtc(), clock.nowUtc().plusDays(31));
|
||||
cloudTasksHelper.assertNoTasksEnqueued(QUEUE_ASYNC_ACTIONS);
|
||||
|
||||
@@ -23,12 +23,12 @@ import static org.apache.http.HttpStatus.SC_OK;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactAddress;
|
||||
import google.registry.model.contact.ContactAuthInfo;
|
||||
import google.registry.model.contact.ContactBase;
|
||||
import google.registry.model.contact.ContactHistory;
|
||||
import google.registry.model.contact.ContactPhoneNumber;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Disclose;
|
||||
import google.registry.model.contact.PostalInfo;
|
||||
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
||||
@@ -48,8 +48,8 @@ class WipeOutContactHistoryPiiActionTest {
|
||||
|
||||
private static final int TEST_BATCH_SIZE = 20;
|
||||
private static final int MIN_MONTHS_BEFORE_WIPE_OUT = 18;
|
||||
private static final ContactResource defaultContactResource =
|
||||
new ContactResource.Builder()
|
||||
private static final Contact DEFAULT_CONTACT =
|
||||
new Contact.Builder()
|
||||
.setContactId("sh8013")
|
||||
.setRepoId("2FF-ROID")
|
||||
.setStatusValues(ImmutableSet.of(StatusValue.CLIENT_DELETE_PROHIBITED))
|
||||
@@ -117,8 +117,7 @@ class WipeOutContactHistoryPiiActionTest {
|
||||
@Test
|
||||
void getAllHistoryEntitiesOlderThan_returnsAllPersistedEntities() {
|
||||
ImmutableList<ContactHistory> expectedToBeWipedOut =
|
||||
persistLotsOfContactHistoryEntities(
|
||||
20, MIN_MONTHS_BEFORE_WIPE_OUT + 1, 0, defaultContactResource);
|
||||
persistLotsOfContactHistoryEntities(20, MIN_MONTHS_BEFORE_WIPE_OUT + 1, 0, DEFAULT_CONTACT);
|
||||
jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
@@ -131,12 +130,10 @@ class WipeOutContactHistoryPiiActionTest {
|
||||
@Test
|
||||
void getAllHistoryEntitiesOlderThan_returnsOnlyOldEnoughPersistedEntities() {
|
||||
ImmutableList<ContactHistory> expectedToBeWipedOut =
|
||||
persistLotsOfContactHistoryEntities(
|
||||
19, MIN_MONTHS_BEFORE_WIPE_OUT + 2, 0, defaultContactResource);
|
||||
persistLotsOfContactHistoryEntities(19, MIN_MONTHS_BEFORE_WIPE_OUT + 2, 0, DEFAULT_CONTACT);
|
||||
|
||||
// persisted entities that should not be part of the actual result
|
||||
persistLotsOfContactHistoryEntities(
|
||||
15, 17, MIN_MONTHS_BEFORE_WIPE_OUT - 1, defaultContactResource);
|
||||
persistLotsOfContactHistoryEntities(15, 17, MIN_MONTHS_BEFORE_WIPE_OUT - 1, DEFAULT_CONTACT);
|
||||
|
||||
jpaTm()
|
||||
.transact(
|
||||
@@ -179,7 +176,7 @@ class WipeOutContactHistoryPiiActionTest {
|
||||
void run_withOneBatchOfEntities_success() {
|
||||
int numOfMonthsFromNow = MIN_MONTHS_BEFORE_WIPE_OUT + 2;
|
||||
ImmutableList<ContactHistory> expectedToBeWipedOut =
|
||||
persistLotsOfContactHistoryEntities(20, numOfMonthsFromNow, 0, defaultContactResource);
|
||||
persistLotsOfContactHistoryEntities(20, numOfMonthsFromNow, 0, DEFAULT_CONTACT);
|
||||
|
||||
// The query should return a stream of all persisted entities.
|
||||
assertThat(
|
||||
@@ -216,7 +213,7 @@ class WipeOutContactHistoryPiiActionTest {
|
||||
void run_withMultipleBatches_numOfEntitiesAsNonMultipleOfBatchSize_success() {
|
||||
int numOfMonthsFromNow = MIN_MONTHS_BEFORE_WIPE_OUT + 2;
|
||||
ImmutableList<ContactHistory> expectedToBeWipedOut =
|
||||
persistLotsOfContactHistoryEntities(56, numOfMonthsFromNow, 0, defaultContactResource);
|
||||
persistLotsOfContactHistoryEntities(56, numOfMonthsFromNow, 0, DEFAULT_CONTACT);
|
||||
|
||||
// The query should return a subset of all persisted data.
|
||||
assertThat(
|
||||
@@ -253,7 +250,7 @@ class WipeOutContactHistoryPiiActionTest {
|
||||
int numOfMonthsFromNow = MIN_MONTHS_BEFORE_WIPE_OUT + 2;
|
||||
ImmutableList<ContactHistory> expectedToBeWipedOut =
|
||||
persistLotsOfContactHistoryEntities(
|
||||
TEST_BATCH_SIZE * 2, numOfMonthsFromNow, 0, defaultContactResource);
|
||||
TEST_BATCH_SIZE * 2, numOfMonthsFromNow, 0, DEFAULT_CONTACT);
|
||||
|
||||
// The query should return a subset of all persisted data.
|
||||
assertThat(
|
||||
@@ -302,7 +299,7 @@ class WipeOutContactHistoryPiiActionTest {
|
||||
void wipeOutContactHistoryData_wipesOutMultipleEntities() {
|
||||
int numOfMonthsFromNow = MIN_MONTHS_BEFORE_WIPE_OUT + 3;
|
||||
ImmutableList<ContactHistory> expectedToBeWipedOut =
|
||||
persistLotsOfContactHistoryEntities(20, numOfMonthsFromNow, 0, defaultContactResource);
|
||||
persistLotsOfContactHistoryEntities(20, numOfMonthsFromNow, 0, DEFAULT_CONTACT);
|
||||
|
||||
assertAllEntitiesContainPii(DatabaseHelper.loadByEntitiesIfPresent(expectedToBeWipedOut));
|
||||
|
||||
@@ -319,7 +316,7 @@ class WipeOutContactHistoryPiiActionTest {
|
||||
|
||||
/** persists a number of ContactHistory entities for load and query testing. */
|
||||
ImmutableList<ContactHistory> persistLotsOfContactHistoryEntities(
|
||||
int numOfEntities, int minusMonths, int minusDays, ContactResource contact) {
|
||||
int numOfEntities, int minusMonths, int minusDays, Contact contact) {
|
||||
ImmutableList.Builder<ContactHistory> expectedEntitesBuilder = new ImmutableList.Builder<>();
|
||||
for (int i = 0; i < numOfEntities; i++) {
|
||||
expectedEntitesBuilder.add(
|
||||
|
||||
@@ -16,6 +16,7 @@ package google.registry.beam.common;
|
||||
|
||||
import static google.registry.testing.AppEngineExtension.makeRegistrar1;
|
||||
import static google.registry.testing.DatabaseHelper.insertInDb;
|
||||
import static google.registry.testing.DatabaseHelper.newContact;
|
||||
import static google.registry.testing.DatabaseHelper.newRegistry;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
@@ -25,8 +26,8 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.beam.TestPipelineExtension;
|
||||
import google.registry.beam.common.RegistryJpaIO.Read;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactBase;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainAuthInfo;
|
||||
import google.registry.model.domain.GracePeriod;
|
||||
@@ -42,7 +43,6 @@ import google.registry.persistence.transaction.CriteriaQueryBuilder;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
import google.registry.testing.DatastoreEntityExtension;
|
||||
import google.registry.testing.FakeClock;
|
||||
import org.apache.beam.sdk.testing.PAssert;
|
||||
@@ -76,17 +76,17 @@ public class RegistryJpaReadTest {
|
||||
final transient TestPipelineExtension testPipeline =
|
||||
TestPipelineExtension.create().enableAbandonedNodeEnforcement(true);
|
||||
|
||||
private transient ImmutableList<ContactResource> contacts;
|
||||
private transient ImmutableList<Contact> contacts;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
Registrar ofyRegistrar = AppEngineExtension.makeRegistrar2();
|
||||
insertInDb(ofyRegistrar);
|
||||
|
||||
ImmutableList.Builder<ContactResource> builder = new ImmutableList.Builder<>();
|
||||
ImmutableList.Builder<Contact> builder = new ImmutableList.Builder<>();
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ContactResource contact = DatabaseHelper.newContactResource("contact_" + i);
|
||||
Contact contact = newContact("contact_" + i);
|
||||
builder.add(contact);
|
||||
}
|
||||
contacts = builder.build();
|
||||
@@ -95,10 +95,9 @@ public class RegistryJpaReadTest {
|
||||
|
||||
@Test
|
||||
void readWithCriteriaQuery() {
|
||||
Read<ContactResource, String> read =
|
||||
Read<Contact, String> read =
|
||||
RegistryJpaIO.read(
|
||||
() -> CriteriaQueryBuilder.create(ContactResource.class).build(),
|
||||
ContactBase::getContactId);
|
||||
() -> CriteriaQueryBuilder.create(Contact.class).build(), ContactBase::getContactId);
|
||||
PCollection<String> repoIds = testPipeline.apply(read);
|
||||
|
||||
PAssert.that(repoIds).containsInAnyOrder("contact_0", "contact_1", "contact_2");
|
||||
@@ -172,8 +171,8 @@ public class RegistryJpaReadTest {
|
||||
.setRegistrarId("registrar1")
|
||||
.setEmailAddress("me@google.com")
|
||||
.build();
|
||||
ContactResource contact =
|
||||
new ContactResource.Builder()
|
||||
Contact contact =
|
||||
new Contact.Builder()
|
||||
.setRepoId("contactid_1")
|
||||
.setCreationRegistrarId(registrar.getRegistrarId())
|
||||
.setTransferData(new ContactTransferData.Builder().build())
|
||||
|
||||
@@ -17,11 +17,11 @@ package google.registry.beam.common;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.ImmutableObjectSubject.immutableObjectCorrespondence;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.testing.DatabaseHelper.newContactResource;
|
||||
import static google.registry.testing.DatabaseHelper.newContact;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import google.registry.beam.TestPipelineExtension;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
@@ -55,21 +55,17 @@ class RegistryJpaWriteTest implements Serializable {
|
||||
@Test
|
||||
void writeToSql_twoWriters() {
|
||||
jpaTm().transact(() -> jpaTm().put(AppEngineExtension.makeRegistrar2()));
|
||||
ImmutableList.Builder<ContactResource> contactsBuilder = new ImmutableList.Builder<>();
|
||||
ImmutableList.Builder<Contact> contactsBuilder = new ImmutableList.Builder<>();
|
||||
for (int i = 0; i < 3; i++) {
|
||||
contactsBuilder.add(newContactResource("contact_" + i));
|
||||
contactsBuilder.add(newContact("contact_" + i));
|
||||
}
|
||||
ImmutableList<ContactResource> contacts = contactsBuilder.build();
|
||||
ImmutableList<Contact> contacts = contactsBuilder.build();
|
||||
testPipeline
|
||||
.apply(Create.of(contacts))
|
||||
.apply(
|
||||
RegistryJpaIO.<ContactResource>write()
|
||||
.withName("ContactResource")
|
||||
.withBatchSize(4)
|
||||
.withShards(2));
|
||||
.apply(RegistryJpaIO.<Contact>write().withName("Contact").withBatchSize(4).withShards(2));
|
||||
testPipeline.run().waitUntilFinish();
|
||||
|
||||
assertThat(jpaTm().transact(() -> jpaTm().loadAllOf(ContactResource.class)))
|
||||
assertThat(jpaTm().transact(() -> jpaTm().loadAllOf(Contact.class)))
|
||||
.comparingElementsUsing(immutableObjectCorrespondence("revisions", "updateTimestamp"))
|
||||
.containsExactlyElementsIn(contacts);
|
||||
}
|
||||
|
||||
@@ -53,9 +53,9 @@ import google.registry.gcs.GcsUtils;
|
||||
import google.registry.keyring.api.PgpHelper;
|
||||
import google.registry.model.common.Cursor;
|
||||
import google.registry.model.common.Cursor.CursorType;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactBase;
|
||||
import google.registry.model.contact.ContactHistory;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.DesignatedContact;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
@@ -265,9 +265,9 @@ public class RdePipelineTest {
|
||||
|
||||
// This contact is never referenced.
|
||||
persistContactHistory(persistActiveContact("contactX"));
|
||||
ContactResource contact1 = persistActiveContact("contact1234");
|
||||
Contact contact1 = persistActiveContact("contact1234");
|
||||
persistContactHistory(contact1);
|
||||
ContactResource contact2 = persistActiveContact("contact456");
|
||||
Contact contact2 = persistActiveContact("contact456");
|
||||
persistContactHistory(contact2);
|
||||
|
||||
// This host is never referenced.
|
||||
@@ -302,7 +302,7 @@ public class RdePipelineTest {
|
||||
persistDomainHistory(deletedDomain.asBuilder().setDeletionTime(clock.nowUtc()).build());
|
||||
kittyDomain = kittyDomain.asBuilder().setDomainName("cat.fun").build();
|
||||
persistDomainHistory(kittyDomain);
|
||||
ContactResource contact3 = persistActiveContact("contact789");
|
||||
Contact contact3 = persistActiveContact("contact789");
|
||||
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.
|
||||
@@ -329,7 +329,7 @@ public class RdePipelineTest {
|
||||
// resulting deposit fragments.
|
||||
clock.advanceBy(Duration.standardDays(2));
|
||||
persistDomainHistory(kittyDomain.asBuilder().setDeletionTime(clock.nowUtc()).build());
|
||||
ContactResource futureContact = persistActiveContact("future-contact");
|
||||
Contact futureContact = persistActiveContact("future-contact");
|
||||
persistContactHistory(futureContact);
|
||||
Host futureHost = persistActiveHost("ns1.future.tld");
|
||||
persistHostHistory(futureHost);
|
||||
|
||||
+5
-5
@@ -32,7 +32,7 @@ import static org.mockito.Mockito.verify;
|
||||
|
||||
import google.registry.beam.TestPipelineExtension;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.GracePeriod;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
@@ -81,7 +81,7 @@ public class ResaveAllEppResourcesPipelineTest {
|
||||
|
||||
@Test
|
||||
void testPipeline_unchangedEntity() {
|
||||
ContactResource contact = persistActiveContact("test123");
|
||||
Contact contact = persistActiveContact("test123");
|
||||
DateTime creationTime = contact.getUpdateTimestamp().getTimestamp();
|
||||
fakeClock.advanceOneMilli();
|
||||
assertThat(loadByEntity(contact).getUpdateTimestamp().getTimestamp()).isEqualTo(creationTime);
|
||||
@@ -92,7 +92,7 @@ public class ResaveAllEppResourcesPipelineTest {
|
||||
|
||||
@Test
|
||||
void testPipeline_fulfilledContactTransfer() {
|
||||
ContactResource contact = persistActiveContact("test123");
|
||||
Contact contact = persistActiveContact("test123");
|
||||
DateTime now = fakeClock.nowUtc();
|
||||
contact = persistContactWithPendingTransfer(contact, now, now.plusDays(5), now);
|
||||
fakeClock.advanceBy(Duration.standardDays(10));
|
||||
@@ -154,7 +154,7 @@ public class ResaveAllEppResourcesPipelineTest {
|
||||
@Test
|
||||
void testPipeline_fastOnlySavesChanged() {
|
||||
DateTime now = fakeClock.nowUtc();
|
||||
ContactResource contact = persistActiveContact("jd1234");
|
||||
Contact contact = persistActiveContact("jd1234");
|
||||
persistDomainWithDependentResources("renewed", "tld", contact, now, now, now.plusYears(1));
|
||||
persistActiveDomain("nonrenewed.tld", now, now.plusYears(20));
|
||||
// Spy the transaction manager so we can be sure we're only saving the renewed domain
|
||||
@@ -171,7 +171,7 @@ public class ResaveAllEppResourcesPipelineTest {
|
||||
void testPipeline_notFastResavesAll() {
|
||||
options.setFast(false);
|
||||
DateTime now = fakeClock.nowUtc();
|
||||
ContactResource contact = persistActiveContact("jd1234");
|
||||
Contact contact = persistActiveContact("jd1234");
|
||||
Domain renewed =
|
||||
persistDomainWithDependentResources("renewed", "tld", contact, now, now, now.plusYears(1));
|
||||
Domain nonRenewed =
|
||||
|
||||
@@ -37,7 +37,7 @@ import com.google.common.truth.Correspondence.BinaryPredicate;
|
||||
import google.registry.beam.TestPipelineExtension;
|
||||
import google.registry.beam.spec11.SafeBrowsingTransforms.EvaluateSafeBrowsingFn;
|
||||
import google.registry.beam.spec11.SafeBrowsingTransformsTest.HttpResponder;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainAuthInfo;
|
||||
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
||||
@@ -258,9 +258,9 @@ class Spec11PipelineTest {
|
||||
createTld("bank");
|
||||
createTld("dev");
|
||||
|
||||
ContactResource contact1 = persistActiveContact(registrar1.getRegistrarId());
|
||||
ContactResource contact2 = persistActiveContact(registrar2.getRegistrarId());
|
||||
ContactResource contact3 = persistActiveContact(registrar3.getRegistrarId());
|
||||
Contact contact1 = persistActiveContact(registrar1.getRegistrarId());
|
||||
Contact contact2 = persistActiveContact(registrar2.getRegistrarId());
|
||||
Contact contact3 = persistActiveContact(registrar3.getRegistrarId());
|
||||
|
||||
persistResource(createDomain("111.com", "123456789-COM", registrar1, contact1));
|
||||
persistResource(createDomain("party-night.net", "2244AABBC-NET", registrar2, contact2));
|
||||
@@ -297,7 +297,7 @@ class Spec11PipelineTest {
|
||||
}
|
||||
|
||||
private Domain createDomain(
|
||||
String domainName, String repoId, Registrar registrar, ContactResource contact) {
|
||||
String domainName, String repoId, Registrar registrar, Contact contact) {
|
||||
return new Domain.Builder()
|
||||
.setDomainName(domainName)
|
||||
.setRepoId(repoId)
|
||||
|
||||
@@ -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.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for {@link ContactCheckFlow}. */
|
||||
class ContactCheckFlowTest extends ResourceCheckFlowTestCase<ContactCheckFlow, ContactResource> {
|
||||
class ContactCheckFlowTest extends ResourceCheckFlowTestCase<ContactCheckFlow, Contact> {
|
||||
|
||||
ContactCheckFlowTest() {
|
||||
setEppInput("contact_check.xml");
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
package google.registry.flows.contact;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.testing.ContactResourceSubject.assertAboutContacts;
|
||||
import static google.registry.testing.ContactSubject.assertAboutContacts;
|
||||
import static google.registry.testing.DatabaseHelper.assertNoBillingEvents;
|
||||
import static google.registry.testing.DatabaseHelper.newContactResource;
|
||||
import static google.registry.testing.DatabaseHelper.newContact;
|
||||
import static google.registry.testing.DatabaseHelper.persistActiveContact;
|
||||
import static google.registry.testing.DatabaseHelper.persistDeletedContact;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
@@ -31,12 +31,12 @@ import google.registry.flows.contact.ContactFlowUtils.BadInternationalizedPostal
|
||||
import google.registry.flows.contact.ContactFlowUtils.DeclineContactDisclosureFieldDisallowedPolicyException;
|
||||
import google.registry.flows.exceptions.ResourceAlreadyExistsForThisClientException;
|
||||
import google.registry.flows.exceptions.ResourceCreateContentionException;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for {@link ContactCreateFlow}. */
|
||||
class ContactCreateFlowTest extends ResourceFlowTestCase<ContactCreateFlow, ContactResource> {
|
||||
class ContactCreateFlowTest extends ResourceFlowTestCase<ContactCreateFlow, Contact> {
|
||||
|
||||
ContactCreateFlowTest() {
|
||||
setEppInput("contact_create.xml");
|
||||
@@ -47,7 +47,7 @@ class ContactCreateFlowTest extends ResourceFlowTestCase<ContactCreateFlow, Cont
|
||||
assertTransactionalFlow(true);
|
||||
runFlowAssertResponse(loadFile("contact_create_response.xml"));
|
||||
// Check that the contact was created and persisted with a history entry.
|
||||
ContactResource contact = reloadResourceByForeignKey();
|
||||
Contact contact = reloadResourceByForeignKey();
|
||||
assertAboutContacts().that(contact).hasOnlyOneHistoryEntryWhich().hasNoXml();
|
||||
assertNoBillingEvents();
|
||||
assertLastHistoryContainsResource(contact);
|
||||
@@ -93,7 +93,7 @@ class ContactCreateFlowTest extends ResourceFlowTestCase<ContactCreateFlow, Cont
|
||||
void testFailure_resourceContention() throws Exception {
|
||||
String targetId = getUniqueIdFromCommand();
|
||||
persistResource(
|
||||
newContactResource(targetId)
|
||||
newContact(targetId)
|
||||
.asBuilder()
|
||||
.setPersistedCurrentSponsorRegistrarId("NewRegistrar")
|
||||
.build());
|
||||
|
||||
@@ -17,11 +17,11 @@ package google.registry.flows.contact;
|
||||
import static com.google.common.collect.MoreCollectors.onlyElement;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_DELETE;
|
||||
import static google.registry.testing.ContactResourceSubject.assertAboutContacts;
|
||||
import static google.registry.testing.ContactSubject.assertAboutContacts;
|
||||
import static google.registry.testing.DatabaseHelper.assertNoBillingEvents;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.getPollMessages;
|
||||
import static google.registry.testing.DatabaseHelper.newContactResource;
|
||||
import static google.registry.testing.DatabaseHelper.newContact;
|
||||
import static google.registry.testing.DatabaseHelper.persistActiveContact;
|
||||
import static google.registry.testing.DatabaseHelper.persistContactWithPendingTransfer;
|
||||
import static google.registry.testing.DatabaseHelper.persistDeletedContact;
|
||||
@@ -39,7 +39,7 @@ import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
|
||||
import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException;
|
||||
import google.registry.flows.exceptions.ResourceStatusProhibitsOperationException;
|
||||
import google.registry.flows.exceptions.ResourceToDeleteIsReferencedException;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
import google.registry.model.poll.PendingActionNotificationResponse;
|
||||
@@ -56,7 +56,7 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for {@link ContactDeleteFlow}. */
|
||||
class ContactDeleteFlowTest extends ResourceFlowTestCase<ContactDeleteFlow, ContactResource> {
|
||||
class ContactDeleteFlowTest extends ResourceFlowTestCase<ContactDeleteFlow, Contact> {
|
||||
|
||||
@BeforeEach
|
||||
void initFlowTest() {
|
||||
@@ -99,7 +99,7 @@ class ContactDeleteFlowTest extends ResourceFlowTestCase<ContactDeleteFlow, Cont
|
||||
assertTransactionalFlow(true);
|
||||
runFlowAssertResponse(loadFile("contact_delete_response.xml"));
|
||||
assertSqlDeleteSuccess(Type.CONTACT_DELETE, Type.CONTACT_TRANSFER_REQUEST);
|
||||
ContactResource softDeletedContact = reloadResourceByForeignKey(clock.nowUtc().minusMillis(1));
|
||||
Contact softDeletedContact = reloadResourceByForeignKey(clock.nowUtc().minusMillis(1));
|
||||
assertThat(softDeletedContact.getTransferData())
|
||||
.isEqualTo(
|
||||
oldTransferData
|
||||
@@ -175,7 +175,7 @@ class ContactDeleteFlowTest extends ResourceFlowTestCase<ContactDeleteFlow, Cont
|
||||
private void doFailingStatusTest(StatusValue statusValue, Class<? extends EppException> exception)
|
||||
throws Exception {
|
||||
persistResource(
|
||||
newContactResource(getUniqueIdFromCommand())
|
||||
newContact(getUniqueIdFromCommand())
|
||||
.asBuilder()
|
||||
.setStatusValues(ImmutableSet.of(statusValue))
|
||||
.build());
|
||||
|
||||
@@ -29,10 +29,10 @@ import google.registry.flows.FlowUtils.NotLoggedInException;
|
||||
import google.registry.flows.ResourceFlowTestCase;
|
||||
import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
|
||||
import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactAddress;
|
||||
import google.registry.model.contact.ContactAuthInfo;
|
||||
import google.registry.model.contact.ContactPhoneNumber;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Disclose;
|
||||
import google.registry.model.contact.PostalInfo;
|
||||
import google.registry.model.contact.PostalInfo.Type;
|
||||
@@ -44,16 +44,16 @@ import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for {@link ContactInfoFlow}. */
|
||||
class ContactInfoFlowTest extends ResourceFlowTestCase<ContactInfoFlow, ContactResource> {
|
||||
class ContactInfoFlowTest extends ResourceFlowTestCase<ContactInfoFlow, Contact> {
|
||||
|
||||
ContactInfoFlowTest() {
|
||||
setEppInput("contact_info.xml");
|
||||
}
|
||||
|
||||
private ContactResource persistContactResource(boolean active) {
|
||||
ContactResource contact =
|
||||
private Contact persistContact(boolean active) {
|
||||
Contact contact =
|
||||
persistResource(
|
||||
new ContactResource.Builder()
|
||||
new Contact.Builder()
|
||||
.setContactId("sh8013")
|
||||
.setRepoId("2FF-ROID")
|
||||
.setDeletionTime(active ? null : clock.nowUtc().minusDays(1))
|
||||
@@ -107,7 +107,7 @@ class ContactInfoFlowTest extends ResourceFlowTestCase<ContactInfoFlow, ContactR
|
||||
|
||||
@Test
|
||||
void testSuccess() throws Exception {
|
||||
persistContactResource(true);
|
||||
persistContact(true);
|
||||
// Check that the persisted contact info was returned.
|
||||
assertTransactionalFlow(false);
|
||||
runFlowAssertResponse(
|
||||
@@ -121,7 +121,7 @@ class ContactInfoFlowTest extends ResourceFlowTestCase<ContactInfoFlow, ContactR
|
||||
@Test
|
||||
void testSuccess_linked() throws Exception {
|
||||
createTld("foobar");
|
||||
persistResource(DatabaseHelper.newDomain("example.foobar", persistContactResource(true)));
|
||||
persistResource(DatabaseHelper.newDomain("example.foobar", persistContact(true)));
|
||||
// Check that the persisted contact info was returned.
|
||||
assertTransactionalFlow(false);
|
||||
runFlowAssertResponse(
|
||||
@@ -135,7 +135,7 @@ class ContactInfoFlowTest extends ResourceFlowTestCase<ContactInfoFlow, ContactR
|
||||
@Test
|
||||
void testSuccess_owningRegistrarWithoutAuthInfo_seesAuthInfo() throws Exception {
|
||||
setEppInput("contact_info_no_authinfo.xml");
|
||||
persistContactResource(true);
|
||||
persistContact(true);
|
||||
// Check that the persisted contact info was returned.
|
||||
assertTransactionalFlow(false);
|
||||
runFlowAssertResponse(
|
||||
@@ -149,7 +149,7 @@ class ContactInfoFlowTest extends ResourceFlowTestCase<ContactInfoFlow, ContactR
|
||||
@Test
|
||||
void testFailure_otherRegistrar_notAuthorized() throws Exception {
|
||||
setRegistrarIdForFlow("NewRegistrar");
|
||||
persistContactResource(true);
|
||||
persistContact(true);
|
||||
// Check that the persisted contact info was returned.
|
||||
assertTransactionalFlow(false);
|
||||
ResourceNotOwnedException thrown = assertThrows(ResourceNotOwnedException.class, this::runFlow);
|
||||
@@ -160,7 +160,7 @@ class ContactInfoFlowTest extends ResourceFlowTestCase<ContactInfoFlow, ContactR
|
||||
void testSuccess_otherRegistrarWithoutAuthInfoAsSuperuser_doesNotSeeAuthInfo() throws Exception {
|
||||
setRegistrarIdForFlow("NewRegistrar");
|
||||
setEppInput("contact_info_no_authinfo.xml");
|
||||
persistContactResource(true);
|
||||
persistContact(true);
|
||||
// Check that the persisted contact info was returned.
|
||||
assertTransactionalFlow(false);
|
||||
runFlowAssertResponse(
|
||||
@@ -176,7 +176,7 @@ class ContactInfoFlowTest extends ResourceFlowTestCase<ContactInfoFlow, ContactR
|
||||
@Test
|
||||
void testSuccess_otherRegistrarWithAuthInfoAsSuperuser_seesAuthInfo() throws Exception {
|
||||
setRegistrarIdForFlow("NewRegistrar");
|
||||
persistContactResource(true);
|
||||
persistContact(true);
|
||||
// Check that the persisted contact info was returned.
|
||||
assertTransactionalFlow(false);
|
||||
runFlowAssertResponse(
|
||||
@@ -199,7 +199,7 @@ class ContactInfoFlowTest extends ResourceFlowTestCase<ContactInfoFlow, ContactR
|
||||
|
||||
@Test
|
||||
void testFailure_existedButWasDeleted() throws Exception {
|
||||
persistContactResource(false);
|
||||
persistContact(false);
|
||||
ResourceDoesNotExistException thrown =
|
||||
assertThrows(ResourceDoesNotExistException.class, this::runFlow);
|
||||
assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand()));
|
||||
@@ -208,7 +208,7 @@ class ContactInfoFlowTest extends ResourceFlowTestCase<ContactInfoFlow, ContactR
|
||||
|
||||
@Test
|
||||
void testIcannActivityReportField_getsLogged() throws Exception {
|
||||
persistContactResource(true);
|
||||
persistContact(true);
|
||||
runFlow();
|
||||
assertIcannReportingActivityFieldLogged("srs-cont-info");
|
||||
}
|
||||
|
||||
+3
-3
@@ -16,7 +16,7 @@ package google.registry.flows.contact;
|
||||
|
||||
import static com.google.common.collect.MoreCollectors.onlyElement;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.testing.ContactResourceSubject.assertAboutContacts;
|
||||
import static google.registry.testing.ContactSubject.assertAboutContacts;
|
||||
import static google.registry.testing.DatabaseHelper.assertNoBillingEvents;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.getOnlyPollMessage;
|
||||
@@ -31,8 +31,8 @@ import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException;
|
||||
import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
|
||||
import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException;
|
||||
import google.registry.flows.exceptions.NotPendingTransferException;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactAuthInfo;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
import google.registry.model.poll.PendingActionNotificationResponse;
|
||||
@@ -46,7 +46,7 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for {@link ContactTransferApproveFlow}. */
|
||||
class ContactTransferApproveFlowTest
|
||||
extends ContactTransferFlowTestCase<ContactTransferApproveFlow, ContactResource> {
|
||||
extends ContactTransferFlowTestCase<ContactTransferApproveFlow, Contact> {
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
|
||||
@@ -16,7 +16,7 @@ package google.registry.flows.contact;
|
||||
|
||||
import static com.google.common.collect.MoreCollectors.onlyElement;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.testing.ContactResourceSubject.assertAboutContacts;
|
||||
import static google.registry.testing.ContactSubject.assertAboutContacts;
|
||||
import static google.registry.testing.DatabaseHelper.assertNoBillingEvents;
|
||||
import static google.registry.testing.DatabaseHelper.getOnlyPollMessage;
|
||||
import static google.registry.testing.DatabaseHelper.getPollMessages;
|
||||
@@ -30,8 +30,8 @@ import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException;
|
||||
import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
|
||||
import google.registry.flows.exceptions.NotPendingTransferException;
|
||||
import google.registry.flows.exceptions.NotTransferInitiatorException;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactAuthInfo;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
@@ -43,7 +43,7 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for {@link ContactTransferCancelFlow}. */
|
||||
class ContactTransferCancelFlowTest
|
||||
extends ContactTransferFlowTestCase<ContactTransferCancelFlow, ContactResource> {
|
||||
extends ContactTransferFlowTestCase<ContactTransferCancelFlow, Contact> {
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
|
||||
@@ -15,14 +15,14 @@
|
||||
package google.registry.flows.contact;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static google.registry.testing.DatabaseHelper.newContactResource;
|
||||
import static google.registry.testing.DatabaseHelper.newContact;
|
||||
import static google.registry.testing.DatabaseHelper.persistContactWithPendingTransfer;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
|
||||
import google.registry.flows.Flow;
|
||||
import google.registry.flows.ResourceFlowTestCase;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.tld.Registry;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
@@ -47,7 +47,7 @@ abstract class ContactTransferFlowTestCase<F extends Flow, R extends EppResource
|
||||
TRANSFER_REQUEST_TIME.plus(Registry.DEFAULT_TRANSFER_GRACE_PERIOD);
|
||||
private static final Duration TIME_SINCE_REQUEST = Duration.standardDays(3);
|
||||
|
||||
protected ContactResource contact;
|
||||
protected Contact contact;
|
||||
|
||||
ContactTransferFlowTestCase() {
|
||||
checkState(!Registry.DEFAULT_TRANSFER_GRACE_PERIOD.isShorterThan(TIME_SINCE_REQUEST));
|
||||
@@ -64,11 +64,12 @@ abstract class ContactTransferFlowTestCase<F extends Flow, R extends EppResource
|
||||
|
||||
/** Adds a contact that has a pending transfer on it from TheRegistrar to NewRegistrar. */
|
||||
void setupContactWithPendingTransfer() {
|
||||
contact = persistContactWithPendingTransfer(
|
||||
newContactResource("sh8013"),
|
||||
TRANSFER_REQUEST_TIME,
|
||||
TRANSFER_EXPIRATION_TIME,
|
||||
TRANSFER_REQUEST_TIME);
|
||||
contact =
|
||||
persistContactWithPendingTransfer(
|
||||
newContact("sh8013"),
|
||||
TRANSFER_REQUEST_TIME,
|
||||
TRANSFER_EXPIRATION_TIME,
|
||||
TRANSFER_REQUEST_TIME);
|
||||
}
|
||||
|
||||
/** Changes the transfer status on the persisted contact. */
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
package google.registry.flows.contact;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.testing.ContactResourceSubject.assertAboutContacts;
|
||||
import static google.registry.testing.ContactSubject.assertAboutContacts;
|
||||
import static google.registry.testing.DatabaseHelper.assertNoBillingEvents;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptions;
|
||||
@@ -27,8 +27,8 @@ import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException;
|
||||
import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
|
||||
import google.registry.flows.exceptions.NoTransferHistoryToQueryException;
|
||||
import google.registry.flows.exceptions.NotAuthorizedToViewTransferException;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactAuthInfo;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
@@ -38,7 +38,7 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for {@link ContactTransferQueryFlow}. */
|
||||
class ContactTransferQueryFlowTest
|
||||
extends ContactTransferFlowTestCase<ContactTransferQueryFlow, ContactResource> {
|
||||
extends ContactTransferFlowTestCase<ContactTransferQueryFlow, Contact> {
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
|
||||
@@ -16,7 +16,7 @@ package google.registry.flows.contact;
|
||||
|
||||
import static com.google.common.collect.MoreCollectors.onlyElement;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.testing.ContactResourceSubject.assertAboutContacts;
|
||||
import static google.registry.testing.ContactSubject.assertAboutContacts;
|
||||
import static google.registry.testing.DatabaseHelper.assertNoBillingEvents;
|
||||
import static google.registry.testing.DatabaseHelper.getOnlyPollMessage;
|
||||
import static google.registry.testing.DatabaseHelper.getPollMessages;
|
||||
@@ -30,8 +30,8 @@ import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException;
|
||||
import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
|
||||
import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException;
|
||||
import google.registry.flows.exceptions.NotPendingTransferException;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactAuthInfo;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
import google.registry.model.poll.PendingActionNotificationResponse;
|
||||
@@ -45,7 +45,7 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for {@link ContactTransferRejectFlow}. */
|
||||
class ContactTransferRejectFlowTest
|
||||
extends ContactTransferFlowTestCase<ContactTransferRejectFlow, ContactResource> {
|
||||
extends ContactTransferFlowTestCase<ContactTransferRejectFlow, Contact> {
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
|
||||
+3
-3
@@ -20,7 +20,7 @@ import static com.google.common.collect.Iterables.getOnlyElement;
|
||||
import static com.google.common.collect.MoreCollectors.onlyElement;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.config.RegistryConfig.getContactAutomaticTransferLength;
|
||||
import static google.registry.testing.ContactResourceSubject.assertAboutContacts;
|
||||
import static google.registry.testing.ContactSubject.assertAboutContacts;
|
||||
import static google.registry.testing.DatabaseHelper.assertNoBillingEvents;
|
||||
import static google.registry.testing.DatabaseHelper.assertPollMessagesEqual;
|
||||
import static google.registry.testing.DatabaseHelper.deleteResource;
|
||||
@@ -42,8 +42,8 @@ import google.registry.flows.exceptions.AlreadyPendingTransferException;
|
||||
import google.registry.flows.exceptions.MissingTransferRequestAuthInfoException;
|
||||
import google.registry.flows.exceptions.ObjectAlreadySponsoredException;
|
||||
import google.registry.flows.exceptions.ResourceStatusProhibitsOperationException;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactAuthInfo;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
@@ -57,7 +57,7 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for {@link ContactTransferRequestFlow}. */
|
||||
class ContactTransferRequestFlowTest
|
||||
extends ContactTransferFlowTestCase<ContactTransferRequestFlow, ContactResource> {
|
||||
extends ContactTransferFlowTestCase<ContactTransferRequestFlow, Contact> {
|
||||
|
||||
ContactTransferRequestFlowTest() {
|
||||
// We need the transfer to happen at exactly this time in order for the response to match up.
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
package google.registry.flows.contact;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.testing.ContactResourceSubject.assertAboutContacts;
|
||||
import static google.registry.testing.ContactSubject.assertAboutContacts;
|
||||
import static google.registry.testing.DatabaseHelper.assertNoBillingEvents;
|
||||
import static google.registry.testing.DatabaseHelper.newContactResource;
|
||||
import static google.registry.testing.DatabaseHelper.newContact;
|
||||
import static google.registry.testing.DatabaseHelper.persistActiveContact;
|
||||
import static google.registry.testing.DatabaseHelper.persistDeletedContact;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
@@ -37,15 +37,15 @@ import google.registry.flows.contact.ContactFlowUtils.BadInternationalizedPostal
|
||||
import google.registry.flows.contact.ContactFlowUtils.DeclineContactDisclosureFieldDisallowedPolicyException;
|
||||
import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException;
|
||||
import google.registry.flows.exceptions.ResourceStatusProhibitsOperationException;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactAddress;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.PostalInfo;
|
||||
import google.registry.model.contact.PostalInfo.Type;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for {@link ContactUpdateFlow}. */
|
||||
class ContactUpdateFlowTest extends ResourceFlowTestCase<ContactUpdateFlow, ContactResource> {
|
||||
class ContactUpdateFlowTest extends ResourceFlowTestCase<ContactUpdateFlow, Contact> {
|
||||
|
||||
ContactUpdateFlowTest() {
|
||||
setEppInput("contact_update.xml");
|
||||
@@ -56,7 +56,7 @@ class ContactUpdateFlowTest extends ResourceFlowTestCase<ContactUpdateFlow, Cont
|
||||
clock.advanceOneMilli();
|
||||
assertTransactionalFlow(true);
|
||||
runFlowAssertResponse(loadFile("generic_success_response.xml"));
|
||||
ContactResource contact = reloadResourceByForeignKey();
|
||||
Contact contact = reloadResourceByForeignKey();
|
||||
// Check that the contact was updated. This value came from the xml.
|
||||
assertAboutContacts()
|
||||
.that(contact)
|
||||
@@ -88,19 +88,22 @@ class ContactUpdateFlowTest extends ResourceFlowTestCase<ContactUpdateFlow, Cont
|
||||
|
||||
@Test
|
||||
void testSuccess_updatingInternationalizedPostalInfoDeletesLocalized() throws Exception {
|
||||
ContactResource contact =
|
||||
Contact contact =
|
||||
persistResource(
|
||||
newContactResource(getUniqueIdFromCommand()).asBuilder()
|
||||
.setLocalizedPostalInfo(new PostalInfo.Builder()
|
||||
.setType(Type.LOCALIZED)
|
||||
.setAddress(new ContactAddress.Builder()
|
||||
.setStreet(ImmutableList.of("111 8th Ave", "4th Floor"))
|
||||
.setCity("New York")
|
||||
.setState("NY")
|
||||
.setZip("10011")
|
||||
.setCountryCode("US")
|
||||
newContact(getUniqueIdFromCommand())
|
||||
.asBuilder()
|
||||
.setLocalizedPostalInfo(
|
||||
new PostalInfo.Builder()
|
||||
.setType(Type.LOCALIZED)
|
||||
.setAddress(
|
||||
new ContactAddress.Builder()
|
||||
.setStreet(ImmutableList.of("111 8th Ave", "4th Floor"))
|
||||
.setCity("New York")
|
||||
.setState("NY")
|
||||
.setZip("10011")
|
||||
.setCountryCode("US")
|
||||
.build())
|
||||
.build())
|
||||
.build())
|
||||
.build());
|
||||
clock.advanceOneMilli();
|
||||
// The test xml updates the internationalized postal info and should therefore implicitly delete
|
||||
@@ -127,19 +130,22 @@ class ContactUpdateFlowTest extends ResourceFlowTestCase<ContactUpdateFlow, Cont
|
||||
@Test
|
||||
void testSuccess_updatingLocalizedPostalInfoDeletesInternationalized() throws Exception {
|
||||
setEppInput("contact_update_localized.xml");
|
||||
ContactResource contact =
|
||||
Contact contact =
|
||||
persistResource(
|
||||
newContactResource(getUniqueIdFromCommand()).asBuilder()
|
||||
.setInternationalizedPostalInfo(new PostalInfo.Builder()
|
||||
.setType(Type.INTERNATIONALIZED)
|
||||
.setAddress(new ContactAddress.Builder()
|
||||
.setStreet(ImmutableList.of("111 8th Ave", "4th Floor"))
|
||||
.setCity("New York")
|
||||
.setState("NY")
|
||||
.setZip("10011")
|
||||
.setCountryCode("US")
|
||||
newContact(getUniqueIdFromCommand())
|
||||
.asBuilder()
|
||||
.setInternationalizedPostalInfo(
|
||||
new PostalInfo.Builder()
|
||||
.setType(Type.INTERNATIONALIZED)
|
||||
.setAddress(
|
||||
new ContactAddress.Builder()
|
||||
.setStreet(ImmutableList.of("111 8th Ave", "4th Floor"))
|
||||
.setCity("New York")
|
||||
.setState("NY")
|
||||
.setZip("10011")
|
||||
.setCountryCode("US")
|
||||
.build())
|
||||
.build())
|
||||
.build())
|
||||
.build());
|
||||
clock.advanceOneMilli();
|
||||
// The test xml updates the localized postal info and should therefore implicitly delete
|
||||
@@ -167,19 +173,22 @@ class ContactUpdateFlowTest extends ResourceFlowTestCase<ContactUpdateFlow, Cont
|
||||
void testSuccess_partialPostalInfoUpdate() throws Exception {
|
||||
setEppInput("contact_update_partial_postalinfo.xml");
|
||||
persistResource(
|
||||
newContactResource(getUniqueIdFromCommand()).asBuilder()
|
||||
.setLocalizedPostalInfo(new PostalInfo.Builder()
|
||||
.setType(Type.LOCALIZED)
|
||||
.setName("A. Person")
|
||||
.setOrg("Company Inc.")
|
||||
.setAddress(new ContactAddress.Builder()
|
||||
.setStreet(ImmutableList.of("123 4th st", "5th Floor"))
|
||||
.setCity("City")
|
||||
.setState("AB")
|
||||
.setZip("12345")
|
||||
.setCountryCode("US")
|
||||
newContact(getUniqueIdFromCommand())
|
||||
.asBuilder()
|
||||
.setLocalizedPostalInfo(
|
||||
new PostalInfo.Builder()
|
||||
.setType(Type.LOCALIZED)
|
||||
.setName("A. Person")
|
||||
.setOrg("Company Inc.")
|
||||
.setAddress(
|
||||
new ContactAddress.Builder()
|
||||
.setStreet(ImmutableList.of("123 4th st", "5th Floor"))
|
||||
.setCity("City")
|
||||
.setState("AB")
|
||||
.setZip("12345")
|
||||
.setCountryCode("US")
|
||||
.build())
|
||||
.build())
|
||||
.build())
|
||||
.build());
|
||||
clock.advanceOneMilli();
|
||||
// The test xml updates the address of the postal info and should leave the name untouched.
|
||||
@@ -203,32 +212,37 @@ class ContactUpdateFlowTest extends ResourceFlowTestCase<ContactUpdateFlow, Cont
|
||||
void testSuccess_updateOnePostalInfo_touchOtherPostalInfoPreservesIt() throws Exception {
|
||||
setEppInput("contact_update_partial_postalinfo_preserve_int.xml");
|
||||
persistResource(
|
||||
newContactResource(getUniqueIdFromCommand()).asBuilder()
|
||||
.setLocalizedPostalInfo(new PostalInfo.Builder()
|
||||
.setType(Type.LOCALIZED)
|
||||
.setName("A. Person")
|
||||
.setOrg("Company Inc.")
|
||||
.setAddress(new ContactAddress.Builder()
|
||||
.setStreet(ImmutableList.of("123 4th st", "5th Floor"))
|
||||
.setCity("City")
|
||||
.setState("AB")
|
||||
.setZip("12345")
|
||||
.setCountryCode("US")
|
||||
.build())
|
||||
.build())
|
||||
.setInternationalizedPostalInfo(new PostalInfo.Builder()
|
||||
.setType(Type.INTERNATIONALIZED)
|
||||
.setName("B. Person")
|
||||
.setOrg("Company Co.")
|
||||
.setAddress(new ContactAddress.Builder()
|
||||
.setStreet(ImmutableList.of("100 200th Dr.", "6th Floor"))
|
||||
.setCity("Town")
|
||||
.setState("CD")
|
||||
.setZip("67890")
|
||||
.setCountryCode("US")
|
||||
.build())
|
||||
.build())
|
||||
.build());
|
||||
newContact(getUniqueIdFromCommand())
|
||||
.asBuilder()
|
||||
.setLocalizedPostalInfo(
|
||||
new PostalInfo.Builder()
|
||||
.setType(Type.LOCALIZED)
|
||||
.setName("A. Person")
|
||||
.setOrg("Company Inc.")
|
||||
.setAddress(
|
||||
new ContactAddress.Builder()
|
||||
.setStreet(ImmutableList.of("123 4th st", "5th Floor"))
|
||||
.setCity("City")
|
||||
.setState("AB")
|
||||
.setZip("12345")
|
||||
.setCountryCode("US")
|
||||
.build())
|
||||
.build())
|
||||
.setInternationalizedPostalInfo(
|
||||
new PostalInfo.Builder()
|
||||
.setType(Type.INTERNATIONALIZED)
|
||||
.setName("B. Person")
|
||||
.setOrg("Company Co.")
|
||||
.setAddress(
|
||||
new ContactAddress.Builder()
|
||||
.setStreet(ImmutableList.of("100 200th Dr.", "6th Floor"))
|
||||
.setCity("Town")
|
||||
.setState("CD")
|
||||
.setZip("67890")
|
||||
.setCountryCode("US")
|
||||
.build())
|
||||
.build())
|
||||
.build());
|
||||
clock.advanceOneMilli();
|
||||
// The test xml updates the address of the localized postal info. It also sets the name of the
|
||||
// internationalized postal info to the same value it previously had, which causes it to be
|
||||
@@ -320,7 +334,7 @@ class ContactUpdateFlowTest extends ResourceFlowTestCase<ContactUpdateFlow, Cont
|
||||
void testSuccess_clientUpdateProhibited_removed() throws Exception {
|
||||
setEppInput("contact_update_remove_client_update_prohibited.xml");
|
||||
persistResource(
|
||||
newContactResource(getUniqueIdFromCommand())
|
||||
newContact(getUniqueIdFromCommand())
|
||||
.asBuilder()
|
||||
.setStatusValues(ImmutableSet.of(StatusValue.CLIENT_UPDATE_PROHIBITED))
|
||||
.build());
|
||||
@@ -334,7 +348,7 @@ class ContactUpdateFlowTest extends ResourceFlowTestCase<ContactUpdateFlow, Cont
|
||||
void testSuccess_superuserClientUpdateProhibited_notRemoved() throws Exception {
|
||||
setEppInput("contact_update_prohibited_status.xml");
|
||||
persistResource(
|
||||
newContactResource(getUniqueIdFromCommand())
|
||||
newContact(getUniqueIdFromCommand())
|
||||
.asBuilder()
|
||||
.setStatusValues(ImmutableSet.of(StatusValue.CLIENT_UPDATE_PROHIBITED))
|
||||
.build());
|
||||
@@ -351,7 +365,7 @@ class ContactUpdateFlowTest extends ResourceFlowTestCase<ContactUpdateFlow, Cont
|
||||
@Test
|
||||
void testFailure_clientUpdateProhibited_notRemoved() throws Exception {
|
||||
persistResource(
|
||||
newContactResource(getUniqueIdFromCommand())
|
||||
newContact(getUniqueIdFromCommand())
|
||||
.asBuilder()
|
||||
.setStatusValues(ImmutableSet.of(StatusValue.CLIENT_UPDATE_PROHIBITED))
|
||||
.build());
|
||||
@@ -363,7 +377,7 @@ class ContactUpdateFlowTest extends ResourceFlowTestCase<ContactUpdateFlow, Cont
|
||||
@Test
|
||||
void testFailure_serverUpdateProhibited() throws Exception {
|
||||
persistResource(
|
||||
newContactResource(getUniqueIdFromCommand())
|
||||
newContact(getUniqueIdFromCommand())
|
||||
.asBuilder()
|
||||
.setStatusValues(ImmutableSet.of(StatusValue.SERVER_UPDATE_PROHIBITED))
|
||||
.build());
|
||||
@@ -376,7 +390,7 @@ class ContactUpdateFlowTest extends ResourceFlowTestCase<ContactUpdateFlow, Cont
|
||||
@Test
|
||||
void testFailure_pendingDeleteProhibited() throws Exception {
|
||||
persistResource(
|
||||
newContactResource(getUniqueIdFromCommand())
|
||||
newContact(getUniqueIdFromCommand())
|
||||
.asBuilder()
|
||||
.setStatusValues(ImmutableSet.of(StatusValue.PENDING_DELETE))
|
||||
.build());
|
||||
|
||||
@@ -43,7 +43,7 @@ import static google.registry.testing.DatabaseHelper.createTlds;
|
||||
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.newContact;
|
||||
import static google.registry.testing.DatabaseHelper.newHost;
|
||||
import static google.registry.testing.DatabaseHelper.persistActiveContact;
|
||||
import static google.registry.testing.DatabaseHelper.persistActiveDomain;
|
||||
@@ -1352,7 +1352,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
|
||||
private void assertAllocationTokenWasRedeemed(String token) throws Exception {
|
||||
AllocationToken reloadedToken =
|
||||
tm().transact(() -> tm().loadByKey(VKey.create(AllocationToken.class, token)));
|
||||
tm().transact(() -> tm().loadByKey(VKey.createSql(AllocationToken.class, token)));
|
||||
assertThat(reloadedToken.isRedeemed()).isTrue();
|
||||
assertThat(reloadedToken.getRedemptionHistoryEntry())
|
||||
.hasValue(
|
||||
@@ -1362,7 +1362,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
|
||||
private void assertAllocationTokenWasNotRedeemed(String token) {
|
||||
AllocationToken reloadedToken =
|
||||
tm().transact(() -> tm().loadByKey(VKey.create(AllocationToken.class, token)));
|
||||
tm().transact(() -> tm().loadByKey(VKey.createSql(AllocationToken.class, token)));
|
||||
assertThat(reloadedToken.isRedeemed()).isFalse();
|
||||
}
|
||||
|
||||
@@ -1723,8 +1723,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||
persistActiveHost("ns1.example.net");
|
||||
persistActiveHost("ns2.example.net");
|
||||
persistActiveContact("sh8013");
|
||||
persistResource(
|
||||
newContactResource("jd1234").asBuilder().addStatusValue(PENDING_DELETE).build());
|
||||
persistResource(newContact("jd1234").asBuilder().addStatusValue(PENDING_DELETE).build());
|
||||
clock.advanceOneMilli();
|
||||
LinkedResourceInPendingDeleteProhibitsOperationException thrown =
|
||||
assertThrows(LinkedResourceInPendingDeleteProhibitsOperationException.class, this::runFlow);
|
||||
|
||||
@@ -80,7 +80,7 @@ import google.registry.flows.exceptions.ResourceStatusProhibitsOperationExceptio
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.billing.BillingEvent.Flag;
|
||||
import google.registry.model.billing.BillingEvent.Reason;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.domain.GracePeriod;
|
||||
@@ -155,7 +155,7 @@ class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow, Domain
|
||||
|
||||
private void createReferencedEntities(DateTime expirationTime) throws Exception {
|
||||
// Persist a linked contact.
|
||||
ContactResource contact = persistActiveContact("sh8013");
|
||||
Contact contact = persistActiveContact("sh8013");
|
||||
domain =
|
||||
persistResource(
|
||||
DatabaseHelper.newDomain(getUniqueIdFromCommand())
|
||||
@@ -742,9 +742,7 @@ class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow, Domain
|
||||
DatabaseHelper.newDomain("example1.tld")
|
||||
.asBuilder()
|
||||
.setRegistrant(
|
||||
loadByForeignKey(ContactResource.class, "sh8013", clock.nowUtc())
|
||||
.get()
|
||||
.createVKey())
|
||||
loadByForeignKey(Contact.class, "sh8013", clock.nowUtc()).get().createVKey())
|
||||
.setNameservers(ImmutableSet.of(host.createVKey()))
|
||||
.setDeletionTime(START_OF_TIME)
|
||||
.build());
|
||||
|
||||
@@ -19,6 +19,7 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.billing.BillingEvent.RenewalPriceBehavior.DEFAULT;
|
||||
import static google.registry.model.billing.BillingEvent.RenewalPriceBehavior.NONPREMIUM;
|
||||
import static google.registry.model.billing.BillingEvent.RenewalPriceBehavior.SPECIFIED;
|
||||
import static google.registry.model.eppcommon.EppXmlTransformer.marshal;
|
||||
import static google.registry.model.tld.Registry.TldState.QUIET_PERIOD;
|
||||
import static google.registry.testing.DatabaseHelper.assertNoBillingEvents;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
@@ -31,6 +32,8 @@ import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptio
|
||||
import static google.registry.testing.TestDataHelper.updateSubstitutions;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
import static google.registry.xml.XmlTestUtils.assertXmlEquals;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.joda.money.CurrencyUnit.USD;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
@@ -52,8 +55,8 @@ 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.Contact;
|
||||
import google.registry.model.contact.ContactAuthInfo;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.DesignatedContact;
|
||||
import google.registry.model.domain.DesignatedContact.Type;
|
||||
import google.registry.model.domain.Domain;
|
||||
@@ -62,14 +65,18 @@ import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.domain.GracePeriod;
|
||||
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.domain.token.AllocationToken.TokenType;
|
||||
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.eppoutput.EppOutput;
|
||||
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.xml.ValidationMode;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.annotation.Nullable;
|
||||
import org.joda.money.Money;
|
||||
@@ -94,8 +101,8 @@ class DomainInfoFlowTest extends ResourceFlowTestCase<DomainInfoFlow, Domain> {
|
||||
|
||||
private static final Pattern OK_PATTERN = Pattern.compile("\"ok\"");
|
||||
|
||||
private ContactResource registrant;
|
||||
private ContactResource contact;
|
||||
private Contact registrant;
|
||||
private Contact contact;
|
||||
private Host host1;
|
||||
private Host host2;
|
||||
private Host host3;
|
||||
@@ -661,7 +668,7 @@ class DomainInfoFlowTest extends ResourceFlowTestCase<DomainInfoFlow, Domain> {
|
||||
@Test
|
||||
void testFailure_differentRegistrarUnrelatedContactAuthInfo() {
|
||||
persistTestEntities(false);
|
||||
ContactResource unrelatedContact = persistActiveContact("foo1234");
|
||||
Contact unrelatedContact = persistActiveContact("foo1234");
|
||||
sessionMetadata.setRegistrarId("ClientZ");
|
||||
setEppInput("domain_info_with_contact_auth.xml");
|
||||
// Replace the ROID in the xml file with the one for our unrelated contact.
|
||||
@@ -673,7 +680,7 @@ class DomainInfoFlowTest extends ResourceFlowTestCase<DomainInfoFlow, Domain> {
|
||||
@Test
|
||||
void testFailure_unrelatedContactAuthInfo() {
|
||||
persistTestEntities(false);
|
||||
ContactResource unrelatedContact = persistActiveContact("foo1234");
|
||||
Contact unrelatedContact = persistActiveContact("foo1234");
|
||||
setEppInput("domain_info_with_contact_auth.xml");
|
||||
// Replace the ROID in the xml file with the one for our unrelated contact.
|
||||
eppLoader.replaceAll("JD1234-REP", unrelatedContact.getRepoId());
|
||||
@@ -1075,4 +1082,77 @@ class DomainInfoFlowTest extends ResourceFlowTestCase<DomainInfoFlow, Domain> {
|
||||
assertIcannReportingActivityFieldLogged("srs-dom-info");
|
||||
assertTldsFieldLogged("tld");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPackageInfoExtension_returnsPackageInfo() throws Exception {
|
||||
persistTestEntities(false);
|
||||
AllocationToken token =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(TokenType.PACKAGE)
|
||||
.setCreationTimeForTest(DateTime.parse("2010-11-12T05:00:00Z"))
|
||||
.setAllowedTlds(ImmutableSet.of("foo"))
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("NewRegistrar"))
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
|
||||
.setDiscountFraction(1)
|
||||
.build());
|
||||
domain = domain.asBuilder().setCurrentPackageToken(token.createVKey()).build();
|
||||
persistResource(domain);
|
||||
setEppInput("domain_info_package.xml");
|
||||
doSuccessfulTest("domain_info_response_package.xml", false);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPackageInfoExtension_returnsPackageInfoForSuperUser() throws Exception {
|
||||
persistTestEntities(false);
|
||||
AllocationToken token =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(TokenType.PACKAGE)
|
||||
.setCreationTimeForTest(DateTime.parse("2010-11-12T05:00:00Z"))
|
||||
.setAllowedTlds(ImmutableSet.of("foo"))
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("NewRegistrar"))
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
|
||||
.setDiscountFraction(1)
|
||||
.build());
|
||||
domain = domain.asBuilder().setCurrentPackageToken(token.createVKey()).build();
|
||||
persistResource(domain);
|
||||
sessionMetadata.setRegistrarId("TheRegistrar");
|
||||
setEppInput("domain_info_package.xml");
|
||||
EppOutput output = runFlowAsSuperuser();
|
||||
String expectedOutput =
|
||||
loadFile(
|
||||
"domain_info_response_superuser_package.xml",
|
||||
updateSubstitutions(ImmutableMap.of(), "ROID", "2FF-TLD"));
|
||||
assertXmlEquals(expectedOutput, new String(marshal(output, ValidationMode.LENIENT), UTF_8));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPackageInfoExtension_nameNotInPackage() throws Exception {
|
||||
setEppInput("domain_info_package.xml");
|
||||
doSuccessfulTest("domain_info_response_empty_package.xml");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPackageInfoExtension_notCurrentSponsorRegistrar() throws Exception {
|
||||
persistTestEntities(false);
|
||||
AllocationToken token =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(TokenType.PACKAGE)
|
||||
.setCreationTimeForTest(DateTime.parse("2010-11-12T05:00:00Z"))
|
||||
.setAllowedTlds(ImmutableSet.of("foo"))
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("NewRegistrar"))
|
||||
.setRenewalPriceBehavior(RenewalPriceBehavior.SPECIFIED)
|
||||
.setDiscountFraction(1)
|
||||
.build());
|
||||
domain = domain.asBuilder().setCurrentPackageToken(token.createVKey()).build();
|
||||
persistResource(domain);
|
||||
sessionMetadata.setRegistrarId("TheRegistrar");
|
||||
setEppInput("domain_info_package.xml");
|
||||
doSuccessfulTest("domain_info_response_unauthorized.xml", false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import static google.registry.flows.domain.DomainTransferFlowTestCase.persistWit
|
||||
import static google.registry.model.billing.BillingEvent.RenewalPriceBehavior.DEFAULT;
|
||||
import static google.registry.model.billing.BillingEvent.RenewalPriceBehavior.NONPREMIUM;
|
||||
import static google.registry.model.billing.BillingEvent.RenewalPriceBehavior.SPECIFIED;
|
||||
import static google.registry.model.domain.token.AllocationToken.TokenType.PACKAGE;
|
||||
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.persistence.transaction.TransactionManagerFactory.tm;
|
||||
@@ -48,6 +49,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.common.truth.Truth8;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppRequestSource;
|
||||
@@ -73,6 +75,8 @@ import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTok
|
||||
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.domain.token.AllocationTokenFlowUtils.MissingRemovePackageTokenOnPackageDomainException;
|
||||
import google.registry.flows.domain.token.AllocationTokenFlowUtils.RemovePackageTokenOnNonPackageDomainException;
|
||||
import google.registry.flows.exceptions.ResourceStatusProhibitsOperationException;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.billing.BillingEvent.Flag;
|
||||
@@ -328,7 +332,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain>
|
||||
@Test
|
||||
private void assertAllocationTokenWasNotRedeemed(String token) {
|
||||
AllocationToken reloadedToken =
|
||||
tm().transact(() -> tm().loadByKey(VKey.create(AllocationToken.class, token)));
|
||||
tm().transact(() -> tm().loadByKey(VKey.createSql(AllocationToken.class, token)));
|
||||
assertThat(reloadedToken.isRedeemed()).isFalse();
|
||||
}
|
||||
|
||||
@@ -591,7 +595,8 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain>
|
||||
@Test
|
||||
void testSuccess_allocationToken() throws Exception {
|
||||
setEppInput(
|
||||
"domain_renew_allocationtoken.xml", ImmutableMap.of("DOMAIN", "example.tld", "YEARS", "2"));
|
||||
"domain_renew_allocationtoken.xml",
|
||||
ImmutableMap.of("DOMAIN", "example.tld", "YEARS", "2", "TOKEN", "abc123"));
|
||||
persistDomain();
|
||||
AllocationToken allocationToken =
|
||||
persistResource(
|
||||
@@ -611,7 +616,8 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain>
|
||||
@Test
|
||||
void testSuccess_allocationTokenMultiUse() throws Exception {
|
||||
setEppInput(
|
||||
"domain_renew_allocationtoken.xml", ImmutableMap.of("DOMAIN", "example.tld", "YEARS", "2"));
|
||||
"domain_renew_allocationtoken.xml",
|
||||
ImmutableMap.of("DOMAIN", "example.tld", "YEARS", "2", "TOKEN", "abc123"));
|
||||
persistDomain();
|
||||
persistResource(
|
||||
new AllocationToken.Builder().setToken("abc123").setTokenType(UNLIMITED_USE).build());
|
||||
@@ -622,7 +628,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain>
|
||||
clock.advanceOneMilli();
|
||||
setEppInput(
|
||||
"domain_renew_allocationtoken.xml",
|
||||
ImmutableMap.of("DOMAIN", "other-example.tld", "YEARS", "2"));
|
||||
ImmutableMap.of("DOMAIN", "other-example.tld", "YEARS", "2", "TOKEN", "abc123"));
|
||||
persistDomain();
|
||||
runFlowAssertResponse(
|
||||
loadFile(
|
||||
@@ -633,7 +639,8 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain>
|
||||
@Test
|
||||
void testFailure_invalidAllocationToken() throws Exception {
|
||||
setEppInput(
|
||||
"domain_renew_allocationtoken.xml", ImmutableMap.of("DOMAIN", "example.tld", "YEARS", "2"));
|
||||
"domain_renew_allocationtoken.xml",
|
||||
ImmutableMap.of("DOMAIN", "example.tld", "YEARS", "2", "TOKEN", "abc123"));
|
||||
persistDomain();
|
||||
EppException thrown = assertThrows(InvalidAllocationTokenException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
@@ -642,7 +649,8 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain>
|
||||
@Test
|
||||
void testFailure_allocationTokenIsForADifferentDomain() throws Exception {
|
||||
setEppInput(
|
||||
"domain_renew_allocationtoken.xml", ImmutableMap.of("DOMAIN", "example.tld", "YEARS", "2"));
|
||||
"domain_renew_allocationtoken.xml",
|
||||
ImmutableMap.of("DOMAIN", "example.tld", "YEARS", "2", "TOKEN", "abc123"));
|
||||
persistDomain();
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
@@ -660,7 +668,8 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain>
|
||||
@Test
|
||||
void testFailure_promotionNotActive() throws Exception {
|
||||
setEppInput(
|
||||
"domain_renew_allocationtoken.xml", ImmutableMap.of("DOMAIN", "example.tld", "YEARS", "2"));
|
||||
"domain_renew_allocationtoken.xml",
|
||||
ImmutableMap.of("DOMAIN", "example.tld", "YEARS", "2", "TOKEN", "abc123"));
|
||||
persistDomain();
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
@@ -682,7 +691,8 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain>
|
||||
@Test
|
||||
void testFailure_promoTokenNotValidForRegistrar() throws Exception {
|
||||
setEppInput(
|
||||
"domain_renew_allocationtoken.xml", ImmutableMap.of("DOMAIN", "example.tld", "YEARS", "2"));
|
||||
"domain_renew_allocationtoken.xml",
|
||||
ImmutableMap.of("DOMAIN", "example.tld", "YEARS", "2", "TOKEN", "abc123"));
|
||||
persistDomain();
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
@@ -706,7 +716,8 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain>
|
||||
@Test
|
||||
void testFailure_promoTokenNotValidForTld() throws Exception {
|
||||
setEppInput(
|
||||
"domain_renew_allocationtoken.xml", ImmutableMap.of("DOMAIN", "example.tld", "YEARS", "2"));
|
||||
"domain_renew_allocationtoken.xml",
|
||||
ImmutableMap.of("DOMAIN", "example.tld", "YEARS", "2", "TOKEN", "abc123"));
|
||||
persistDomain();
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
@@ -730,7 +741,8 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain>
|
||||
@Test
|
||||
void testFailure_alreadyRedemeedAllocationToken() throws Exception {
|
||||
setEppInput(
|
||||
"domain_renew_allocationtoken.xml", ImmutableMap.of("DOMAIN", "example.tld", "YEARS", "2"));
|
||||
"domain_renew_allocationtoken.xml",
|
||||
ImmutableMap.of("DOMAIN", "example.tld", "YEARS", "2", "TOKEN", "abc123"));
|
||||
persistDomain();
|
||||
Domain domain = persistActiveDomain("foo.tld");
|
||||
Key<HistoryEntry> historyEntryKey = Key.create(Key.create(domain), HistoryEntry.class, 505L);
|
||||
@@ -1185,4 +1197,101 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain>
|
||||
TransactionReportField.netRenewsFieldFromYears(5),
|
||||
1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailsPackageDomainInvalidAllocationToken() throws Exception {
|
||||
AllocationToken token =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(PACKAGE)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.setRenewalPriceBehavior(SPECIFIED)
|
||||
.build());
|
||||
persistDomain();
|
||||
persistResource(
|
||||
reloadResourceByForeignKey()
|
||||
.asBuilder()
|
||||
.setCurrentPackageToken(token.createVKey())
|
||||
.build());
|
||||
|
||||
setEppInput(
|
||||
"domain_renew_allocationtoken.xml",
|
||||
ImmutableMap.of("DOMAIN", "example.tld", "YEARS", "2", "TOKEN", "abc123"));
|
||||
|
||||
EppException thrown =
|
||||
assertThrows(MissingRemovePackageTokenOnPackageDomainException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailsToRenewPackageDomainNoRemovePackageToken() throws Exception {
|
||||
AllocationToken token =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(PACKAGE)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.setRenewalPriceBehavior(SPECIFIED)
|
||||
.build());
|
||||
persistDomain();
|
||||
persistResource(
|
||||
reloadResourceByForeignKey()
|
||||
.asBuilder()
|
||||
.setCurrentPackageToken(token.createVKey())
|
||||
.build());
|
||||
|
||||
setEppInput("domain_renew.xml", ImmutableMap.of("DOMAIN", "example.tld", "YEARS", "5"));
|
||||
|
||||
EppException thrown =
|
||||
assertThrows(MissingRemovePackageTokenOnPackageDomainException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailsToRenewNonPackageDomainWithRemovePackageToken() throws Exception {
|
||||
persistDomain();
|
||||
|
||||
setEppInput(
|
||||
"domain_renew_allocationtoken.xml",
|
||||
ImmutableMap.of("DOMAIN", "example.tld", "YEARS", "2", "TOKEN", "__REMOVEPACKAGE__"));
|
||||
|
||||
EppException thrown =
|
||||
assertThrows(RemovePackageTokenOnNonPackageDomainException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccesfullyAppliesRemovePackageToken() throws Exception {
|
||||
AllocationToken token =
|
||||
persistResource(
|
||||
new AllocationToken.Builder()
|
||||
.setToken("abc123")
|
||||
.setTokenType(PACKAGE)
|
||||
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
|
||||
.setAllowedTlds(ImmutableSet.of("tld"))
|
||||
.setRenewalPriceBehavior(SPECIFIED)
|
||||
.build());
|
||||
persistDomain(SPECIFIED, Money.of(USD, 2));
|
||||
persistResource(
|
||||
reloadResourceByForeignKey()
|
||||
.asBuilder()
|
||||
.setCurrentPackageToken(token.createVKey())
|
||||
.build());
|
||||
setEppInput(
|
||||
"domain_renew_allocationtoken.xml",
|
||||
ImmutableMap.of("DOMAIN", "example.tld", "YEARS", "2", "TOKEN", "__REMOVEPACKAGE__"));
|
||||
|
||||
doSuccessfulTest(
|
||||
"domain_renew_response.xml",
|
||||
2,
|
||||
ImmutableMap.of("DOMAIN", "example.tld", "EXDATE", "2002-04-03T22:00:00Z"));
|
||||
|
||||
// We still need to verify that package token is removed as it's not being tested as a part of
|
||||
// doSuccessfulTest
|
||||
Domain domain = reloadResourceByForeignKey();
|
||||
Truth8.assertThat(domain.getCurrentPackageToken()).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ import google.registry.model.EppResource;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.billing.BillingEvent.Flag;
|
||||
import google.registry.model.billing.BillingEvent.Reason;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
@@ -71,7 +71,7 @@ abstract class DomainTransferFlowTestCase<F extends Flow, R extends EppResource>
|
||||
static final DateTime EXTENDED_REGISTRATION_EXPIRATION_TIME =
|
||||
REGISTRATION_EXPIRATION_TIME.plusYears(EXTENDED_REGISTRATION_YEARS);
|
||||
|
||||
protected ContactResource contact;
|
||||
protected Contact contact;
|
||||
protected Domain domain;
|
||||
Host subordinateHost;
|
||||
private DomainHistory historyEntryDomainCreate;
|
||||
|
||||
@@ -91,7 +91,7 @@ import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedExcepti
|
||||
import google.registry.flows.exceptions.ResourceStatusProhibitsOperationException;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.billing.BillingEvent.Reason;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.domain.DesignatedContact;
|
||||
import google.registry.model.domain.DesignatedContact.Type;
|
||||
import google.registry.model.domain.Domain;
|
||||
@@ -127,9 +127,9 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
|
||||
"DIGEST_TYPE", "1",
|
||||
"DIGEST", "A94A8FE5CCB19BA61C4C0873D391E987982FBBD3");
|
||||
|
||||
private ContactResource sh8013Contact;
|
||||
private ContactResource mak21Contact;
|
||||
private ContactResource unusedContact;
|
||||
private Contact sh8013Contact;
|
||||
private Contact mak21Contact;
|
||||
private Contact unusedContact;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
@@ -419,8 +419,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
|
||||
void testSuccess_registrantMovedToTechContact() throws Exception {
|
||||
setEppInput("domain_update_registrant_to_tech.xml");
|
||||
persistReferencedEntities();
|
||||
ContactResource sh8013 =
|
||||
loadByForeignKey(ContactResource.class, "sh8013", clock.nowUtc()).get();
|
||||
Contact sh8013 = loadByForeignKey(Contact.class, "sh8013", clock.nowUtc()).get();
|
||||
persistResource(
|
||||
DatabaseHelper.newDomain(getUniqueIdFromCommand())
|
||||
.asBuilder()
|
||||
@@ -434,9 +433,8 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
|
||||
void testSuccess_multipleReferencesToSameContactRemoved() throws Exception {
|
||||
setEppInput("domain_update_remove_multiple_contacts.xml");
|
||||
persistReferencedEntities();
|
||||
ContactResource sh8013 =
|
||||
loadByForeignKey(ContactResource.class, "sh8013", clock.nowUtc()).get();
|
||||
VKey<ContactResource> sh8013Key = sh8013.createVKey();
|
||||
Contact sh8013 = loadByForeignKey(Contact.class, "sh8013", clock.nowUtc()).get();
|
||||
VKey<Contact> sh8013Key = sh8013.createVKey();
|
||||
persistResource(
|
||||
DatabaseHelper.newDomain(getUniqueIdFromCommand())
|
||||
.asBuilder()
|
||||
@@ -1111,9 +1109,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
|
||||
.setContacts(
|
||||
DesignatedContact.create(
|
||||
Type.TECH,
|
||||
loadByForeignKey(ContactResource.class, "foo", clock.nowUtc())
|
||||
.get()
|
||||
.createVKey()))
|
||||
loadByForeignKey(Contact.class, "foo", clock.nowUtc()).get().createVKey()))
|
||||
.build());
|
||||
EppException thrown = assertThrows(DuplicateContactForRoleException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
@@ -1436,9 +1432,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
|
||||
.setContacts(
|
||||
DesignatedContact.create(
|
||||
Type.TECH,
|
||||
loadByForeignKey(ContactResource.class, "sh8013", clock.nowUtc())
|
||||
.get()
|
||||
.createVKey()))
|
||||
loadByForeignKey(Contact.class, "sh8013", clock.nowUtc()).get().createVKey()))
|
||||
.build());
|
||||
EppException thrown = assertThrows(AddRemoveSameValueException.class, this::runFlow);
|
||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||
@@ -1484,7 +1478,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
|
||||
persistActiveHost("ns2.example.foo");
|
||||
persistActiveContact("sh8013");
|
||||
persistResource(
|
||||
loadByForeignKey(ContactResource.class, "mak21", clock.nowUtc())
|
||||
loadByForeignKey(Contact.class, "mak21", clock.nowUtc())
|
||||
.get()
|
||||
.asBuilder()
|
||||
.addStatusValue(StatusValue.PENDING_DELETE)
|
||||
|
||||
@@ -28,7 +28,7 @@ import google.registry.flows.poll.PollAckFlow.InvalidMessageIdException;
|
||||
import google.registry.flows.poll.PollAckFlow.MessageDoesNotExistException;
|
||||
import google.registry.flows.poll.PollAckFlow.MissingMessageIdException;
|
||||
import google.registry.flows.poll.PollAckFlow.NotAuthorizedToAckMessageException;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.testing.DatabaseHelper;
|
||||
@@ -43,7 +43,7 @@ class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
|
||||
private static final long MESSAGE_ID = 3;
|
||||
|
||||
private Domain domain;
|
||||
private ContactResource contact;
|
||||
private Contact contact;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
@@ -116,7 +116,7 @@ class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_messageOnContactResource() throws Exception {
|
||||
void testSuccess_messageOnContact() throws Exception {
|
||||
persistOneTimePollMessage(MESSAGE_ID);
|
||||
assertTransactionalFlow(true);
|
||||
runFlowAssertResponse(loadFile("poll_ack_response_empty.xml"));
|
||||
|
||||
@@ -27,8 +27,8 @@ import com.google.common.collect.ImmutableList;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.FlowTestCase;
|
||||
import google.registry.flows.poll.PollRequestFlow.UnexpectedMessageIdException;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.contact.ContactHistory;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
import google.registry.model.host.Host;
|
||||
@@ -48,7 +48,7 @@ import org.junit.jupiter.api.Test;
|
||||
class PollRequestFlowTest extends FlowTestCase<PollRequestFlow> {
|
||||
|
||||
private Domain domain;
|
||||
private ContactResource contact;
|
||||
private Contact contact;
|
||||
private Host host;
|
||||
|
||||
@BeforeEach
|
||||
|
||||
@@ -22,7 +22,7 @@ import static google.registry.testing.DatabaseHelper.persistActiveHost;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.testing.TestCacheExtension;
|
||||
import java.time.Duration;
|
||||
@@ -38,14 +38,14 @@ public class EppResourceTest extends EntityTestCase {
|
||||
|
||||
@Test
|
||||
void test_loadCached_ignoresContactChange() {
|
||||
ContactResource originalContact = persistActiveContact("contact123");
|
||||
Contact originalContact = persistActiveContact("contact123");
|
||||
assertThat(EppResource.loadCached(ImmutableList.of(originalContact.createVKey())))
|
||||
.containsExactly(originalContact.createVKey(), originalContact);
|
||||
ContactResource modifiedContact =
|
||||
Contact modifiedContact =
|
||||
persistResource(originalContact.asBuilder().setEmailAddress("different@fake.lol").build());
|
||||
assertThat(EppResource.loadCached(ImmutableList.of(originalContact.createVKey())))
|
||||
.containsExactly(originalContact.createVKey(), originalContact);
|
||||
assertThat(loadByForeignKey(ContactResource.class, "contact123", fakeClock.nowUtc()))
|
||||
assertThat(loadByForeignKey(Contact.class, "contact123", fakeClock.nowUtc()))
|
||||
.hasValue(modifiedContact);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.common.base.Ascii;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.Contact;
|
||||
import google.registry.model.domain.DesignatedContact;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainAuthInfo;
|
||||
@@ -72,7 +72,7 @@ public final class TestSetupHelper {
|
||||
|
||||
public Registry registry;
|
||||
public Registrar registrar;
|
||||
public ContactResource contact;
|
||||
public Contact contact;
|
||||
public Domain domain;
|
||||
public DomainHistory domainHistory;
|
||||
public Host host;
|
||||
@@ -118,8 +118,8 @@ public final class TestSetupHelper {
|
||||
}
|
||||
}
|
||||
|
||||
static ContactResource createContact(String repoId, String registrarId) {
|
||||
return new ContactResource.Builder()
|
||||
static Contact createContact(String repoId, String registrarId) {
|
||||
return new Contact.Builder()
|
||||
.setRepoId(repoId)
|
||||
.setCreationRegistrarId(registrarId)
|
||||
.setTransferData(new ContactTransferData.Builder().build())
|
||||
@@ -127,7 +127,7 @@ public final class TestSetupHelper {
|
||||
.build();
|
||||
}
|
||||
|
||||
static Domain createSimpleDomain(ContactResource contact) {
|
||||
static Domain createSimpleDomain(Contact contact) {
|
||||
return DatabaseHelper.newDomain(DOMAIN_NAME, DOMAIN_REPO_ID, contact)
|
||||
.asBuilder()
|
||||
.setCreationRegistrarId(REGISTRAR_ID)
|
||||
@@ -135,7 +135,7 @@ public final class TestSetupHelper {
|
||||
.build();
|
||||
}
|
||||
|
||||
static Domain createFullDomain(ContactResource contact, Host host, FakeClock fakeClock) {
|
||||
static Domain createFullDomain(Contact contact, Host host, FakeClock fakeClock) {
|
||||
return createSimpleDomain(contact)
|
||||
.asBuilder()
|
||||
.setDomainName(DOMAIN_NAME)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user