mirror of
https://github.com/google/nomulus.git
synced 2025-05-13 07:57:13 +02:00
Scope down TransferData to only ContactResource and DomainResource
HostResource and DomainApplication are not transferable, (or at least, not directly in the case of hosts) and have no need for the TransferData field. In a flat-flow world, we can push it down to where it's actually used. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=139201423
This commit is contained in:
parent
0234795240
commit
84009eaccb
24 changed files with 309 additions and 240 deletions
|
@ -39,14 +39,15 @@ import google.registry.flows.EppException.ParameterValuePolicyErrorException;
|
|||
import google.registry.flows.EppException.ParameterValueRangeErrorException;
|
||||
import google.registry.flows.exceptions.MissingTransferRequestAuthInfoException;
|
||||
import google.registry.flows.exceptions.NotPendingTransferException;
|
||||
import google.registry.flows.exceptions.NotTransferInitiatorException;
|
||||
import google.registry.flows.exceptions.ResourceAlreadyExistsException;
|
||||
import google.registry.flows.exceptions.ResourceStatusProhibitsOperationException;
|
||||
import google.registry.flows.exceptions.ResourceToDeleteIsReferencedException;
|
||||
import google.registry.flows.exceptions.TooManyResourceChecksException;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.EppResource.Builder;
|
||||
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.domain.DomainBase;
|
||||
import google.registry.model.domain.DomainResource;
|
||||
|
@ -66,6 +67,7 @@ import google.registry.model.transfer.TransferResponse.DomainTransferResponse;
|
|||
import google.registry.model.transfer.TransferStatus;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** Static utility functions for resource flows. */
|
||||
|
@ -141,33 +143,6 @@ public final class ResourceFlowUtils {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs common deletion operations on an EPP resource and returns a builder for further
|
||||
* modifications. This is broken out into ResourceFlowUtils in order to expose the functionality
|
||||
* to async flows (i.e. mapreduces).
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <R extends EppResource> Builder<R, ? extends Builder<R, ?>>
|
||||
prepareDeletedResourceAsBuilder(R resource, DateTime now) {
|
||||
Builder<R, ? extends Builder<R, ?>> builder =
|
||||
(Builder<R, ? extends Builder<R, ?>>) resource.asBuilder()
|
||||
.setDeletionTime(now)
|
||||
.setStatusValues(null)
|
||||
.setTransferData(
|
||||
resource.getStatusValues().contains(StatusValue.PENDING_TRANSFER)
|
||||
? resource.getTransferData().asBuilder()
|
||||
.setTransferStatus(TransferStatus.SERVER_CANCELLED)
|
||||
.setServerApproveEntities(null)
|
||||
.setServerApproveBillingEvent(null)
|
||||
.setServerApproveAutorenewEvent(null)
|
||||
.setServerApproveAutorenewPollMessage(null)
|
||||
.setPendingTransferExpirationTime(null)
|
||||
.build()
|
||||
: resource.getTransferData())
|
||||
.wipeOut();
|
||||
return builder;
|
||||
}
|
||||
|
||||
/** Update the relevant {@link ForeignKeyIndex} to cache the new deletion time. */
|
||||
public static <R extends EppResource> void updateForeignKeyIndexDeletionTime(R resource) {
|
||||
if (resource instanceof ForeignKeyedEppResource) {
|
||||
|
@ -176,7 +151,8 @@ public final class ResourceFlowUtils {
|
|||
}
|
||||
|
||||
/** If there is a transfer out, delete the server-approve entities and enqueue a poll message. */
|
||||
public static <R extends EppResource> void handlePendingTransferOnDelete(
|
||||
public static <R extends EppResource & ResourceWithTransferData>
|
||||
void handlePendingTransferOnDelete(
|
||||
R resource, R newResource, DateTime now, HistoryEntry historyEntry) {
|
||||
if (resource.getStatusValues().contains(StatusValue.PENDING_TRANSFER)) {
|
||||
TransferData oldTransferData = resource.getTransferData();
|
||||
|
@ -230,19 +206,15 @@ public final class ResourceFlowUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Turn a resource into a builder with its pending transfer resolved.
|
||||
* Create a {@link TransferData} object representing a resolved transfer.
|
||||
*
|
||||
* <p>This removes the {@link StatusValue#PENDING_TRANSFER} status, sets the
|
||||
* {@link TransferStatus}, clears all the server-approve fields on the {@link TransferData}
|
||||
* including the extended registration years field, and sets the expiration time of the last
|
||||
* <p>This clears all the server-approve fields on the {@link TransferData} including the extended
|
||||
* registration years field, sets the status field, and sets the expiration time of the last
|
||||
* pending transfer to now.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <R extends EppResource> EppResource.Builder<R, ?> resolvePendingTransfer(
|
||||
R resource, TransferStatus transferStatus, DateTime now) {
|
||||
return (EppResource.Builder<R, ?>) resource.asBuilder()
|
||||
.removeStatusValue(StatusValue.PENDING_TRANSFER)
|
||||
.setTransferData(resource.getTransferData().asBuilder()
|
||||
public static TransferData createResolvedTransferData(
|
||||
TransferData oldTransferData, TransferStatus transferStatus, DateTime now) {
|
||||
return oldTransferData.asBuilder()
|
||||
.setExtendedRegistrationYears(null)
|
||||
.setServerApproveEntities(null)
|
||||
.setServerApproveBillingEvent(null)
|
||||
|
@ -250,7 +222,29 @@ public final class ResourceFlowUtils {
|
|||
.setServerApproveAutorenewPollMessage(null)
|
||||
.setTransferStatus(transferStatus)
|
||||
.setPendingTransferExpirationTime(now)
|
||||
.build());
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn a resource into a builder with its pending transfer resolved.
|
||||
*
|
||||
* <p>This removes the {@link StatusValue#PENDING_TRANSFER} status, sets the
|
||||
* {@link TransferStatus}, clears all the server-approve fields on the {@link TransferData}
|
||||
* including the extended registration years field, and sets the expiration time of the last
|
||||
* pending transfer to now.
|
||||
*
|
||||
* @param now the time that the transfer was resolved, or null if the transfer was never actually
|
||||
* resolved but the resource was deleted while it was still pending.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <
|
||||
R extends EppResource & ResourceWithTransferData,
|
||||
B extends EppResource.Builder<R, B> & BuilderWithTransferData<B>> B resolvePendingTransfer(
|
||||
R resource, TransferStatus transferStatus, @Nullable DateTime now) {
|
||||
return ((B) resource.asBuilder())
|
||||
.removeStatusValue(StatusValue.PENDING_TRANSFER)
|
||||
.setTransferData(
|
||||
createResolvedTransferData(resource.getTransferData(), transferStatus, now));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -261,7 +255,7 @@ public final class ResourceFlowUtils {
|
|||
* including the extended registration years field, and sets the expiration time of the last
|
||||
* pending transfer to now.
|
||||
*/
|
||||
public static <R extends EppResource> R approvePendingTransfer(
|
||||
public static <R extends EppResource & ResourceWithTransferData> R approvePendingTransfer(
|
||||
R resource, TransferStatus transferStatus, DateTime now) {
|
||||
Builder<R, ?> builder = resolvePendingTransfer(resource, transferStatus, now);
|
||||
builder
|
||||
|
@ -278,13 +272,13 @@ public final class ResourceFlowUtils {
|
|||
* including the extended registration years field, sets the new client id, and sets the last
|
||||
* transfer time and the expiration time of the last pending transfer to now.
|
||||
*/
|
||||
public static <R extends EppResource> R denyPendingTransfer(
|
||||
public static <R extends EppResource & ResourceWithTransferData> R denyPendingTransfer(
|
||||
R resource, TransferStatus transferStatus, DateTime now) {
|
||||
return resolvePendingTransfer(resource, transferStatus, now).build();
|
||||
}
|
||||
|
||||
public static void verifyHasPendingTransfer(EppResource resource)
|
||||
throws NotPendingTransferException {
|
||||
public static <R extends EppResource & ResourceWithTransferData> void verifyHasPendingTransfer(
|
||||
R resource) throws NotPendingTransferException {
|
||||
if (resource.getTransferData().getTransferStatus() != TransferStatus.PENDING) {
|
||||
throw new NotPendingTransferException(resource.getForeignKey());
|
||||
}
|
||||
|
@ -311,13 +305,6 @@ public final class ResourceFlowUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static void verifyIsGainingRegistrar(EppResource resource, String clientId)
|
||||
throws NotTransferInitiatorException {
|
||||
if (!clientId.equals(resource.getTransferData().getGainingClientId())) {
|
||||
throw new NotTransferInitiatorException();
|
||||
}
|
||||
}
|
||||
|
||||
/** Check that the given AuthInfo is present for a resource being transferred. */
|
||||
public static void verifyAuthInfoPresentForResourceTransfer(Optional<AuthInfo> authInfo)
|
||||
throws EppException {
|
||||
|
|
|
@ -20,8 +20,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static com.google.common.math.IntMath.divide;
|
||||
import static com.googlecode.objectify.Key.getKind;
|
||||
import static google.registry.flows.ResourceFlowUtils.createResolvedTransferData;
|
||||
import static google.registry.flows.ResourceFlowUtils.handlePendingTransferOnDelete;
|
||||
import static google.registry.flows.ResourceFlowUtils.prepareDeletedResourceAsBuilder;
|
||||
import static google.registry.flows.ResourceFlowUtils.updateForeignKeyIndexDeletionTime;
|
||||
import static google.registry.model.EppResourceUtils.isActive;
|
||||
import static google.registry.model.EppResourceUtils.isDeleted;
|
||||
|
@ -66,6 +66,7 @@ import google.registry.model.domain.DomainBase;
|
|||
import google.registry.model.host.HostResource;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.util.Clock;
|
||||
|
@ -313,7 +314,20 @@ public class DeleteContactsAndHostsAction implements Runnable {
|
|||
|
||||
EppResource resourceToSave;
|
||||
if (deleteAllowed) {
|
||||
resourceToSave = prepareDeletedResourceAsBuilder(resource, now).build();
|
||||
EppResource.Builder<?, ?> resourceToSaveBuilder;
|
||||
if (resource instanceof ContactResource) {
|
||||
ContactResource contact = (ContactResource) resource;
|
||||
resourceToSaveBuilder = contact.asBuilder()
|
||||
.setTransferData(createResolvedTransferData(
|
||||
contact.getTransferData(), TransferStatus.SERVER_CANCELLED, null))
|
||||
.wipeOut();
|
||||
} else {
|
||||
resourceToSaveBuilder = resource.asBuilder();
|
||||
}
|
||||
resourceToSave = resourceToSaveBuilder
|
||||
.setDeletionTime(now)
|
||||
.setStatusValues(null)
|
||||
.build();
|
||||
performDeleteTasks(resource, resourceToSave, now, historyEntry);
|
||||
updateForeignKeyIndexDeletionTime(resourceToSave);
|
||||
} else {
|
||||
|
@ -346,7 +360,10 @@ public class DeleteContactsAndHostsAction implements Runnable {
|
|||
HistoryEntry historyEntryForDelete) {
|
||||
if (existingResource instanceof ContactResource) {
|
||||
handlePendingTransferOnDelete(
|
||||
existingResource, deletedResource, deletionTime, historyEntryForDelete);
|
||||
(ContactResource) existingResource,
|
||||
(ContactResource) deletedResource,
|
||||
deletionTime,
|
||||
historyEntryForDelete);
|
||||
} else if (existingResource instanceof HostResource) {
|
||||
HostResource host = (HostResource) existingResource;
|
||||
if (host.getSuperordinateDomain() != null) {
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
package google.registry.flows.domain;
|
||||
|
||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.handlePendingTransferOnDelete;
|
||||
import static google.registry.flows.ResourceFlowUtils.prepareDeletedResourceAsBuilder;
|
||||
import static google.registry.flows.ResourceFlowUtils.updateForeignKeyIndexDeletionTime;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyExistence;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo;
|
||||
|
@ -100,15 +98,16 @@ public final class DomainApplicationDeleteFlow implements TransactionalFlow {
|
|||
throw new SunriseApplicationCannotBeDeletedInLandrushException();
|
||||
}
|
||||
}
|
||||
DomainApplication newApplication =
|
||||
prepareDeletedResourceAsBuilder(existingApplication, now).build();
|
||||
DomainApplication newApplication = existingApplication.asBuilder()
|
||||
.setDeletionTime(now)
|
||||
.setStatusValues(null)
|
||||
.build();
|
||||
HistoryEntry historyEntry = historyBuilder
|
||||
.setType(HistoryEntry.Type.DOMAIN_APPLICATION_DELETE)
|
||||
.setModificationTime(now)
|
||||
.setParent(Key.create(existingApplication))
|
||||
.build();
|
||||
updateForeignKeyIndexDeletionTime(newApplication);
|
||||
handlePendingTransferOnDelete(existingApplication, newApplication, now, historyEntry);
|
||||
handleExtraFlowLogic(tld, historyEntry, existingApplication, now);
|
||||
ofy().save().<Object>entities(newApplication, historyEntry);
|
||||
return responseBuilder.build();
|
||||
|
|
|
@ -18,7 +18,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||
import static google.registry.flows.ResourceFlowUtils.handlePendingTransferOnDelete;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
import static google.registry.flows.ResourceFlowUtils.prepareDeletedResourceAsBuilder;
|
||||
import static google.registry.flows.ResourceFlowUtils.resolvePendingTransfer;
|
||||
import static google.registry.flows.ResourceFlowUtils.updateForeignKeyIndexDeletionTime;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo;
|
||||
|
@ -70,6 +70,7 @@ import google.registry.model.poll.PollMessage;
|
|||
import google.registry.model.poll.PollMessage.OneTime;
|
||||
import google.registry.model.registry.Registry;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
@ -119,7 +120,8 @@ public final class DomainDeleteFlow implements TransactionalFlow {
|
|||
Registry registry = Registry.get(existingDomain.getTld());
|
||||
verifyDeleteAllowed(existingDomain, registry, now);
|
||||
HistoryEntry historyEntry = buildHistoryEntry(existingDomain, now);
|
||||
Builder builder = (Builder) prepareDeletedResourceAsBuilder(existingDomain, now);
|
||||
Builder builder = resolvePendingTransfer(existingDomain, TransferStatus.SERVER_CANCELLED, null);
|
||||
builder.setDeletionTime(now).setStatusValues(null);
|
||||
// If the domain is in the Add Grace Period, we delete it immediately, which is already
|
||||
// reflected in the builder we just prepared. Otherwise we give it a PENDING_DELETE status.
|
||||
if (!existingDomain.getGracePeriodStatuses().contains(GracePeriodStatus.ADD)) {
|
||||
|
|
|
@ -18,7 +18,6 @@ import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
|||
import static google.registry.flows.ResourceFlowUtils.denyPendingTransfer;
|
||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyHasPendingTransfer;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyIsGainingRegistrar;
|
||||
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.createLosingTransferPollMessage;
|
||||
|
@ -34,6 +33,7 @@ import google.registry.flows.ExtensionManager;
|
|||
import google.registry.flows.FlowModule.ClientId;
|
||||
import google.registry.flows.FlowModule.TargetId;
|
||||
import google.registry.flows.TransactionalFlow;
|
||||
import google.registry.flows.exceptions.NotTransferInitiatorException;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.domain.DomainResource;
|
||||
import google.registry.model.domain.metadata.MetadataExtension;
|
||||
|
@ -81,7 +81,9 @@ public final class DomainTransferCancelFlow implements TransactionalFlow {
|
|||
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
|
||||
verifyOptionalAuthInfo(authInfo, existingDomain);
|
||||
verifyHasPendingTransfer(existingDomain);
|
||||
verifyIsGainingRegistrar(existingDomain, clientId);
|
||||
if (!clientId.equals(existingDomain.getTransferData().getGainingClientId())) {
|
||||
throw new NotTransferInitiatorException();
|
||||
}
|
||||
checkAllowedAccessToTld(clientId, existingDomain.getTld());
|
||||
HistoryEntry historyEntry = historyBuilder
|
||||
.setType(HistoryEntry.Type.DOMAIN_TRANSFER_CANCEL)
|
||||
|
|
|
@ -117,10 +117,6 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable,
|
|||
/** Status values associated with this resource. */
|
||||
Set<StatusValue> status;
|
||||
|
||||
/** Data about any pending or past transfers on this contact. */
|
||||
@XmlTransient
|
||||
TransferData transferData;
|
||||
|
||||
/**
|
||||
* Sorted map of {@link DateTime} keys (modified time) to {@link CommitLogManifest} entries.
|
||||
*
|
||||
|
@ -161,15 +157,6 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable,
|
|||
return nullToEmptyImmutableCopy(status);
|
||||
}
|
||||
|
||||
public final TransferData getTransferData() {
|
||||
return Optional.fromNullable(transferData).or(TransferData.EMPTY);
|
||||
}
|
||||
|
||||
/** Returns whether there is any transferData. */
|
||||
public final boolean hasTransferData() {
|
||||
return transferData != null;
|
||||
}
|
||||
|
||||
@XmlElement(name = "trDate")
|
||||
public DateTime getLastTransferTime() {
|
||||
return lastTransferTime;
|
||||
|
@ -196,6 +183,16 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable,
|
|||
/** EppResources that are loaded via foreign keys should implement this marker interface. */
|
||||
public interface ForeignKeyedEppResource {}
|
||||
|
||||
/** An interface for resources that have transfer data. */
|
||||
public interface ResourceWithTransferData {
|
||||
public TransferData getTransferData();
|
||||
}
|
||||
|
||||
/** An interface for builders of resources that have transfer data. */
|
||||
public interface BuilderWithTransferData<B extends BuilderWithTransferData<B>> {
|
||||
public B setTransferData(TransferData transferData);
|
||||
}
|
||||
|
||||
/** Abstract builder for {@link EppResource} types. */
|
||||
public abstract static class Builder<T extends EppResource, B extends Builder<?, ?>>
|
||||
extends GenericBuilder<T, B> {
|
||||
|
@ -292,23 +289,12 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable,
|
|||
difference(getInstance().getStatusValues(), statusValues)));
|
||||
}
|
||||
|
||||
/** Set this resource's transfer data. */
|
||||
public B setTransferData(TransferData transferData) {
|
||||
getInstance().transferData = transferData;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
/** Set this resource's repoId. */
|
||||
public B setRepoId(String repoId) {
|
||||
getInstance().repoId = repoId;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
/** Wipe out any personal information in the resource. */
|
||||
public B wipeOut() {
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
/** Build the resource, nullifying empty strings and sets and setting defaults. */
|
||||
@Override
|
||||
public T build() {
|
||||
|
@ -323,10 +309,6 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable,
|
|||
|
||||
/** Build the resource, nullifying empty strings and sets and setting defaults. */
|
||||
public T buildWithoutImplicitStatusValues() {
|
||||
// If TransferData is totally empty, set it to null.
|
||||
if (TransferData.EMPTY.equals(getInstance().transferData)) {
|
||||
setTransferData(null);
|
||||
}
|
||||
// If there is no deletion time, set it to END_OF_TIME.
|
||||
setDeletionTime(Optional.fromNullable(getInstance().deletionTime).or(END_OF_TIME));
|
||||
return ImmutableObject.cloneEmptyToNull(super.build());
|
||||
|
|
|
@ -29,7 +29,9 @@ import com.googlecode.objectify.Result;
|
|||
import com.googlecode.objectify.util.ResultNow;
|
||||
import google.registry.config.RegistryEnvironment;
|
||||
import google.registry.model.EppResource.Builder;
|
||||
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.domain.DomainApplication;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
|
@ -201,8 +203,8 @@ public final class EppResourceUtils {
|
|||
}
|
||||
|
||||
/** Process an automatic transfer on a resource. */
|
||||
public static void setAutomaticTransferSuccessProperties(
|
||||
Builder<?, ?> builder, TransferData transferData) {
|
||||
public static <B extends Builder<?, B> & BuilderWithTransferData<B>>
|
||||
void setAutomaticTransferSuccessProperties(B builder, TransferData transferData) {
|
||||
checkArgument(TransferStatus.PENDING.equals(transferData.getTransferStatus()));
|
||||
builder.removeStatusValue(StatusValue.PENDING_TRANSFER)
|
||||
.setTransferData(transferData.asBuilder()
|
||||
|
@ -222,8 +224,10 @@ public final class EppResourceUtils {
|
|||
* <li>Process an automatic transfer.
|
||||
* </ul>
|
||||
*/
|
||||
public static <T extends EppResource> void projectResourceOntoBuilderAtTime(
|
||||
T resource, Builder<?, ?> builder, DateTime now) {
|
||||
public static <
|
||||
T extends EppResource & ResourceWithTransferData,
|
||||
B extends Builder<?, B> & BuilderWithTransferData<B>>
|
||||
void projectResourceOntoBuilderAtTime(T resource, B builder, DateTime now) {
|
||||
TransferData transferData = resource.getTransferData();
|
||||
// If there's a pending transfer that has expired, process it.
|
||||
DateTime expirationTime = transferData.getPendingTransferExpirationTime();
|
||||
|
|
|
@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkArgument;
|
|||
import static google.registry.model.EppResourceUtils.projectResourceOntoBuilderAtTime;
|
||||
import static google.registry.model.ofy.Ofy.RECOMMENDED_MEMCACHE_EXPIRATION;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.FluentIterable;
|
||||
import com.google.common.collect.Lists;
|
||||
|
@ -28,8 +29,10 @@ import com.googlecode.objectify.annotation.Index;
|
|||
import com.googlecode.objectify.condition.IfNull;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.EppResource.ForeignKeyedEppResource;
|
||||
import google.registry.model.EppResource.ResourceWithTransferData;
|
||||
import google.registry.model.annotations.ExternalMessagingName;
|
||||
import google.registry.model.contact.PostalInfo.Type;
|
||||
import google.registry.model.transfer.TransferData;
|
||||
import java.util.List;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
@ -64,7 +67,8 @@ import org.joda.time.DateTime;
|
|||
@Cache(expirationSeconds = RECOMMENDED_MEMCACHE_EXPIRATION)
|
||||
@Entity
|
||||
@ExternalMessagingName("contact")
|
||||
public class ContactResource extends EppResource implements ForeignKeyedEppResource {
|
||||
public class ContactResource extends EppResource
|
||||
implements ForeignKeyedEppResource, ResourceWithTransferData {
|
||||
|
||||
/**
|
||||
* Unique identifier for this contact.
|
||||
|
@ -78,13 +82,16 @@ public class ContactResource extends EppResource implements ForeignKeyedEppResou
|
|||
|
||||
/**
|
||||
* Localized postal info for the contact. All contained values must be representable in the 7-bit
|
||||
* US-ASCII character set. Personal info; cleared by wipeOut().
|
||||
* US-ASCII character set. Personal info; cleared by {@link Builder#wipeOut}.
|
||||
*/
|
||||
@IgnoreSave(IfNull.class)
|
||||
@XmlTransient
|
||||
PostalInfo localizedPostalInfo;
|
||||
|
||||
/** Internationalized postal info for the contact. Personal info; cleared by wipeOut(). */
|
||||
/**
|
||||
* Internationalized postal info for the contact. Personal info; cleared by
|
||||
* {@link Builder#wipeOut}.
|
||||
*/
|
||||
@IgnoreSave(IfNull.class)
|
||||
@XmlTransient
|
||||
PostalInfo internationalizedPostalInfo;
|
||||
|
@ -92,21 +99,21 @@ public class ContactResource extends EppResource implements ForeignKeyedEppResou
|
|||
/**
|
||||
* 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 wipeOut().
|
||||
* info; cleared by {@link Builder#wipeOut}.
|
||||
*/
|
||||
@Index
|
||||
@XmlTransient
|
||||
String searchName;
|
||||
|
||||
/** Contact’s voice number. Personal info; cleared by wipeOut(). */
|
||||
/** Contact’s voice number. Personal info; cleared by {@link Builder#wipeOut}. */
|
||||
@IgnoreSave(IfNull.class)
|
||||
ContactPhoneNumber voice;
|
||||
|
||||
/** Contact’s fax number. Personal info; cleared by wipeOut(). */
|
||||
/** Contact’s fax number. Personal info; cleared by {@link Builder#wipeOut}. */
|
||||
@IgnoreSave(IfNull.class)
|
||||
ContactPhoneNumber fax;
|
||||
|
||||
/** Contact’s email address. Personal info; cleared by wipeOut(). */
|
||||
/** Contact’s email address. Personal info; cleared by {@link Builder#wipeOut}. */
|
||||
@IgnoreSave(IfNull.class)
|
||||
@XmlJavaTypeAdapter(CollapsedStringAdapter.class)
|
||||
String email;
|
||||
|
@ -114,6 +121,10 @@ public class ContactResource extends EppResource implements ForeignKeyedEppResou
|
|||
/** Authorization info (aka transfer secret) of the contact. */
|
||||
ContactAuthInfo authInfo;
|
||||
|
||||
/** Data about any pending or past transfers on this contact. */
|
||||
@XmlTransient
|
||||
TransferData transferData;
|
||||
|
||||
// If any new fields are added which contain personal information, make sure they are cleared by
|
||||
// the wipeOut() function, so that data is not kept around for deleted contacts.
|
||||
|
||||
|
@ -154,6 +165,11 @@ public class ContactResource extends EppResource implements ForeignKeyedEppResou
|
|||
return disclose;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final TransferData getTransferData() {
|
||||
return Optional.fromNullable(transferData).or(TransferData.EMPTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getForeignKey() {
|
||||
return contactId;
|
||||
|
@ -188,7 +204,9 @@ public class ContactResource extends EppResource implements ForeignKeyedEppResou
|
|||
}
|
||||
|
||||
/** A builder for constructing {@link ContactResource}, since it is immutable. */
|
||||
public static class Builder extends EppResource.Builder<ContactResource, Builder> {
|
||||
public static class Builder extends EppResource.Builder<ContactResource, Builder>
|
||||
implements BuilderWithTransferData<Builder>{
|
||||
|
||||
public Builder() {}
|
||||
|
||||
private Builder(ContactResource instance) {
|
||||
|
@ -252,26 +270,42 @@ public class ContactResource extends EppResource implements ForeignKeyedEppResou
|
|||
}
|
||||
|
||||
@Override
|
||||
public Builder setTransferData(TransferData transferData) {
|
||||
getInstance().transferData = transferData;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all personally identifying information about a contact.
|
||||
*
|
||||
* <p>This should be used when deleting a contact so that the soft-deleted entity doesn't
|
||||
* contain information that the registrant requested to be deleted.
|
||||
*/
|
||||
public Builder wipeOut() {
|
||||
this.setEmailAddress(null);
|
||||
this.setFaxNumber(null);
|
||||
this.setInternationalizedPostalInfo(null);
|
||||
this.setLocalizedPostalInfo(null);
|
||||
this.setVoiceNumber(null);
|
||||
return super.wipeOut();
|
||||
setEmailAddress(null);
|
||||
setFaxNumber(null);
|
||||
setInternationalizedPostalInfo(null);
|
||||
setLocalizedPostalInfo(null);
|
||||
setVoiceNumber(null);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContactResource build() {
|
||||
ContactResource instance = getInstance();
|
||||
// If TransferData is totally empty, set it to null.
|
||||
if (TransferData.EMPTY.equals(instance.transferData)) {
|
||||
setTransferData(null);
|
||||
}
|
||||
// Set the searchName using the internationalized and localized postal info names.
|
||||
if ((getInstance().internationalizedPostalInfo != null)
|
||||
&& (getInstance().internationalizedPostalInfo.getName() != null)) {
|
||||
getInstance().searchName = getInstance().internationalizedPostalInfo.getName();
|
||||
} else if ((getInstance().localizedPostalInfo != null)
|
||||
&& (getInstance().localizedPostalInfo.getName() != null)) {
|
||||
getInstance().searchName = getInstance().localizedPostalInfo.getName();
|
||||
if ((instance.internationalizedPostalInfo != null)
|
||||
&& (instance.internationalizedPostalInfo.getName() != null)) {
|
||||
instance.searchName = instance.internationalizedPostalInfo.getName();
|
||||
} else if ((instance.localizedPostalInfo != null)
|
||||
&& (instance.localizedPostalInfo.getName() != null)) {
|
||||
instance.searchName = instance.localizedPostalInfo.getName();
|
||||
} else {
|
||||
getInstance().searchName = null;
|
||||
instance.searchName = null;
|
||||
}
|
||||
return super.build();
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import com.googlecode.objectify.annotation.EntitySubclass;
|
|||
import com.googlecode.objectify.annotation.IgnoreSave;
|
||||
import com.googlecode.objectify.condition.IfNull;
|
||||
import google.registry.model.EppResource.ForeignKeyedEppResource;
|
||||
import google.registry.model.EppResource.ResourceWithTransferData;
|
||||
import google.registry.model.annotations.ExternalMessagingName;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||
|
@ -75,7 +76,8 @@ import org.joda.time.Interval;
|
|||
@Cache(expirationSeconds = RECOMMENDED_MEMCACHE_EXPIRATION)
|
||||
@EntitySubclass(index = true)
|
||||
@ExternalMessagingName("domain")
|
||||
public class DomainResource extends DomainBase implements ForeignKeyedEppResource {
|
||||
public class DomainResource extends DomainBase
|
||||
implements ForeignKeyedEppResource, ResourceWithTransferData {
|
||||
|
||||
/** The max number of years that a domain can be registered for, as set by ICANN policy. */
|
||||
public static final int MAX_REGISTRATION_YEARS = 10;
|
||||
|
@ -156,6 +158,10 @@ public class DomainResource extends DomainBase implements ForeignKeyedEppResourc
|
|||
@XmlTransient
|
||||
Key<DomainApplication> application;
|
||||
|
||||
/** Data about any pending or past transfers on this domain. */
|
||||
@XmlTransient
|
||||
TransferData transferData;
|
||||
|
||||
public ImmutableSet<String> getSubordinateHosts() {
|
||||
return nullToEmptyImmutableCopy(subordinateHosts);
|
||||
}
|
||||
|
@ -192,6 +198,11 @@ public class DomainResource extends DomainBase implements ForeignKeyedEppResourc
|
|||
return application;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final TransferData getTransferData() {
|
||||
return Optional.fromNullable(transferData).or(TransferData.EMPTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getForeignKey() {
|
||||
return fullyQualifiedDomainName;
|
||||
|
@ -356,7 +367,8 @@ public class DomainResource extends DomainBase implements ForeignKeyedEppResourc
|
|||
}
|
||||
|
||||
/** A builder for constructing {@link DomainResource}, since it is immutable. */
|
||||
public static class Builder extends DomainBase.Builder<DomainResource, Builder> {
|
||||
public static class Builder extends DomainBase.Builder<DomainResource, Builder>
|
||||
implements BuilderWithTransferData<Builder> {
|
||||
|
||||
public Builder() {}
|
||||
|
||||
|
@ -366,6 +378,10 @@ public class DomainResource extends DomainBase implements ForeignKeyedEppResourc
|
|||
|
||||
@Override
|
||||
public DomainResource build() {
|
||||
// If TransferData is totally empty, set it to null.
|
||||
if (TransferData.EMPTY.equals(getInstance().transferData)) {
|
||||
setTransferData(null);
|
||||
}
|
||||
// A DomainResource has status INACTIVE if there are no nameservers.
|
||||
if (getInstance().getNameservers().isEmpty()) {
|
||||
addStatusValue(StatusValue.INACTIVE);
|
||||
|
@ -440,5 +456,11 @@ public class DomainResource extends DomainBase implements ForeignKeyedEppResourc
|
|||
getInstance().gracePeriods = difference(getInstance().getGracePeriods(), gracePeriod);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder setTransferData(TransferData transferData) {
|
||||
getInstance().transferData = transferData;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ package google.registry.model.host;
|
|||
|
||||
import static com.google.common.collect.Sets.difference;
|
||||
import static com.google.common.collect.Sets.union;
|
||||
import static google.registry.model.EppResourceUtils.projectResourceOntoBuilderAtTime;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.ofy.Ofy.RECOMMENDED_MEMCACHE_EXPIRATION;
|
||||
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
|
||||
|
@ -126,15 +125,14 @@ public class HostResource extends EppResource implements ForeignKeyedEppResource
|
|||
@Override
|
||||
public HostResource cloneProjectedAtTime(DateTime now) {
|
||||
Builder builder = this.asBuilder();
|
||||
projectResourceOntoBuilderAtTime(this, builder, now);
|
||||
|
||||
if (superordinateDomain == null) {
|
||||
// If this was a subordinate host to a domain that was being transferred, there might be a
|
||||
// pending transfer still extant, so remove it.
|
||||
builder.setTransferData(null).removeStatusValue(StatusValue.PENDING_TRANSFER);
|
||||
builder.removeStatusValue(StatusValue.PENDING_TRANSFER);
|
||||
} else {
|
||||
// For hosts with superordinate domains, the client id, last transfer time, and transfer data
|
||||
// need to be read off the domain projected to the correct time.
|
||||
// For hosts with superordinate domains, the client id, last transfer time, and transfer
|
||||
// status value need to be read off the domain projected to the correct time.
|
||||
DomainResource domainAtTime = ofy().load().key(superordinateDomain).now()
|
||||
.cloneProjectedAtTime(now);
|
||||
builder.setCurrentSponsorClientId(domainAtTime.getCurrentSponsorClientId());
|
||||
|
@ -145,15 +143,14 @@ public class HostResource extends EppResource implements ForeignKeyedEppResource
|
|||
.isBefore(Optional.fromNullable(domainAtTime.getLastTransferTime()).or(START_OF_TIME))) {
|
||||
builder.setLastTransferTime(domainAtTime.getLastTransferTime());
|
||||
}
|
||||
// Copy the transfer status and data from the superordinate domain onto the host, because the
|
||||
// host's doesn't matter and the superordinate domain always has the canonical data.
|
||||
TransferData domainTransferData = domainAtTime.getTransferData();
|
||||
if (TransferStatus.PENDING.equals(domainTransferData.getTransferStatus())) {
|
||||
// Copy the transfer status from the superordinate domain onto the host, because the host's
|
||||
// doesn't matter and the superordinate domain always has the canonical data.
|
||||
TransferStatus domainTransferStatus = domainAtTime.getTransferData().getTransferStatus();
|
||||
if (TransferStatus.PENDING.equals(domainTransferStatus)) {
|
||||
builder.addStatusValue(StatusValue.PENDING_TRANSFER);
|
||||
} else {
|
||||
builder.removeStatusValue(StatusValue.PENDING_TRANSFER);
|
||||
}
|
||||
builder.setTransferData(domainTransferData);
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
|
|
@ -242,11 +242,20 @@ public class VerifyEntityIntegrityAction implements Runnable {
|
|||
Key<?> key = Key.create(domainBase);
|
||||
verifyExistence(key, domainBase.getReferencedContacts());
|
||||
verifyExistence(key, domainBase.getNameservers());
|
||||
verifyExistence(key, domainBase.getTransferData().getServerApproveAutorenewEvent());
|
||||
verifyExistence(key, domainBase.getTransferData().getServerApproveAutorenewPollMessage());
|
||||
verifyExistence(key, domainBase.getTransferData().getServerApproveBillingEvent());
|
||||
if (domainBase instanceof DomainApplication) {
|
||||
getContext().incrementCounter("domain applications");
|
||||
DomainApplication application = (DomainApplication) domainBase;
|
||||
emit(
|
||||
MapperKey.create(EntityKind.APPLICATION, application.getFullyQualifiedDomainName()),
|
||||
Key.create(application));
|
||||
} else if (domainBase instanceof DomainResource) {
|
||||
getContext().incrementCounter("domain resources");
|
||||
DomainResource domain = (DomainResource) domainBase;
|
||||
verifyExistence(key, domain.getTransferData().getServerApproveAutorenewEvent());
|
||||
verifyExistence(key, domain.getTransferData().getServerApproveAutorenewPollMessage());
|
||||
verifyExistence(key, domain.getTransferData().getServerApproveBillingEvent());
|
||||
verifyExistence(key, FluentIterable
|
||||
.from(domainBase.getTransferData().getServerApproveEntities())
|
||||
.from(domain.getTransferData().getServerApproveEntities())
|
||||
.transform(
|
||||
new Function<Key<? extends TransferServerApproveEntity>,
|
||||
Key<TransferServerApproveEntity>>() {
|
||||
|
@ -257,15 +266,6 @@ public class VerifyEntityIntegrityAction implements Runnable {
|
|||
return (Key<TransferServerApproveEntity>) key;
|
||||
}})
|
||||
.toSet());
|
||||
if (domainBase instanceof DomainApplication) {
|
||||
getContext().incrementCounter("domain applications");
|
||||
DomainApplication application = (DomainApplication) domainBase;
|
||||
emit(
|
||||
MapperKey.create(EntityKind.APPLICATION, application.getFullyQualifiedDomainName()),
|
||||
Key.create(application));
|
||||
} else if (domainBase instanceof DomainResource) {
|
||||
getContext().incrementCounter("domain resources");
|
||||
DomainResource domain = (DomainResource) domainBase;
|
||||
verifyExistence(key, domain.getApplication());
|
||||
verifyExistence(key, domain.getAutorenewBillingEvent());
|
||||
for (GracePeriod gracePeriod : domain.getGracePeriods()) {
|
||||
|
|
|
@ -43,7 +43,6 @@ import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
|
|||
import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException;
|
||||
import google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException;
|
||||
import google.registry.flows.exceptions.NotPendingTransferException;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.billing.BillingEvent.Cancellation;
|
||||
import google.registry.model.billing.BillingEvent.Cancellation.Builder;
|
||||
|
@ -98,8 +97,8 @@ public class DomainTransferApproveFlowTest
|
|||
clock.advanceOneMilli();
|
||||
}
|
||||
|
||||
private void assertTransferApproved(EppResource resource) {
|
||||
assertAboutEppResources().that(resource)
|
||||
private void assertTransferApproved(DomainResource domain) {
|
||||
assertAboutDomains().that(domain)
|
||||
.hasTransferStatus(TransferStatus.CLIENT_APPROVED).and()
|
||||
.hasCurrentSponsorClientId("NewRegistrar").and()
|
||||
.hasLastTransferTime(clock.nowUtc()).and()
|
||||
|
@ -107,6 +106,13 @@ public class DomainTransferApproveFlowTest
|
|||
.doesNotHaveStatusValue(StatusValue.PENDING_TRANSFER);
|
||||
}
|
||||
|
||||
private void assertTransferApproved(HostResource host) {
|
||||
assertAboutEppResources().that(host)
|
||||
.hasCurrentSponsorClientId("NewRegistrar").and()
|
||||
.hasLastTransferTime(clock.nowUtc()).and()
|
||||
.doesNotHaveStatusValue(StatusValue.PENDING_TRANSFER);
|
||||
}
|
||||
|
||||
private void setEppLoader(String commandFilename) {
|
||||
setEppInput(commandFilename);
|
||||
// Replace the ROID in the xml file with the one generated in our test.
|
||||
|
|
|
@ -112,9 +112,7 @@ public class DomainTransferCancelFlowTest
|
|||
assertAboutDomains().that(domain)
|
||||
.hasRegistrationExpirationTime(originalExpirationTime).and()
|
||||
.hasLastTransferTimeNotEqualTo(clock.nowUtc());
|
||||
assertTransferFailed(
|
||||
reloadResourceAndCloneAtTime(subordinateHost, clock.nowUtc()),
|
||||
TransferStatus.CLIENT_CANCELLED);
|
||||
assertTransferFailed(reloadResourceAndCloneAtTime(subordinateHost, clock.nowUtc()));
|
||||
assertAboutDomains().that(domain).hasOneHistoryEntryEachOfTypes(
|
||||
HistoryEntry.Type.DOMAIN_CREATE,
|
||||
HistoryEntry.Type.DOMAIN_TRANSFER_REQUEST,
|
||||
|
|
|
@ -23,6 +23,7 @@ import static google.registry.testing.DatastoreHelper.getOnlyHistoryEntryOfType;
|
|||
import static google.registry.testing.DatastoreHelper.persistActiveContact;
|
||||
import static google.registry.testing.DatastoreHelper.persistDomainWithPendingTransfer;
|
||||
import static google.registry.testing.DatastoreHelper.persistResource;
|
||||
import static google.registry.testing.DomainResourceSubject.assertAboutDomains;
|
||||
import static google.registry.testing.GenericEppResourceSubject.assertAboutEppResources;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
|
||||
|
@ -210,19 +211,25 @@ public class DomainTransferFlowTestCase<F extends Flow, R extends EppResource>
|
|||
.build();
|
||||
}
|
||||
|
||||
protected void assertTransferFailed(EppResource resource, TransferStatus status) {
|
||||
assertAboutEppResources().that(resource)
|
||||
protected void assertTransferFailed(DomainResource domain, TransferStatus status) {
|
||||
assertAboutDomains().that(domain)
|
||||
.hasTransferStatus(status).and()
|
||||
.hasPendingTransferExpirationTime(clock.nowUtc()).and()
|
||||
.doesNotHaveStatusValue(StatusValue.PENDING_TRANSFER).and()
|
||||
.hasCurrentSponsorClientId("TheRegistrar");
|
||||
TransferData transferData = resource.getTransferData();
|
||||
TransferData transferData = domain.getTransferData();
|
||||
assertThat(transferData.getServerApproveBillingEvent()).isNull();
|
||||
assertThat(transferData.getServerApproveAutorenewEvent()).isNull();
|
||||
assertThat(transferData.getServerApproveAutorenewPollMessage()).isNull();
|
||||
assertThat(transferData.getServerApproveEntities()).isEmpty();
|
||||
}
|
||||
|
||||
protected void assertTransferFailed(HostResource resource) {
|
||||
assertAboutEppResources().that(resource)
|
||||
.doesNotHaveStatusValue(StatusValue.PENDING_TRANSFER).and()
|
||||
.hasCurrentSponsorClientId("TheRegistrar");
|
||||
}
|
||||
|
||||
/** Adds a .tld domain that has a pending transfer on it from TheRegistrar to NewRegistrar. */
|
||||
protected void setupDomainWithPendingTransfer() throws Exception {
|
||||
setupDomainWithPendingTransfer("tld");
|
||||
|
|
|
@ -82,9 +82,7 @@ public class DomainTransferRejectFlowTest
|
|||
// Transfer should have been rejected. Verify correct fields were set.
|
||||
domain = reloadResourceByForeignKey();
|
||||
assertTransferFailed(domain, TransferStatus.CLIENT_REJECTED);
|
||||
assertTransferFailed(
|
||||
reloadResourceAndCloneAtTime(subordinateHost, clock.nowUtc()),
|
||||
TransferStatus.CLIENT_REJECTED);
|
||||
assertTransferFailed(reloadResourceAndCloneAtTime(subordinateHost, clock.nowUtc()));
|
||||
assertAboutDomains().that(domain)
|
||||
.hasRegistrationExpirationTime(originalExpirationTime).and()
|
||||
.hasLastTransferTimeNotEqualTo(clock.nowUtc()).and()
|
||||
|
|
|
@ -53,7 +53,6 @@ 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.EppResource;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.billing.BillingEvent.Cancellation.Builder;
|
||||
import google.registry.model.billing.BillingEvent.Flag;
|
||||
|
@ -67,6 +66,7 @@ import google.registry.model.domain.TestExtraLogicManager.TestExtraLogicManagerS
|
|||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.host.HostResource;
|
||||
import google.registry.model.poll.PendingActionNotificationResponse;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
|
@ -102,8 +102,8 @@ public class DomainTransferRequestFlowTest
|
|||
RegistryExtraFlowLogicProxy.setOverride("flags", TestExtraLogicManager.class);
|
||||
}
|
||||
|
||||
private void assertTransferRequested(EppResource resource) throws Exception {
|
||||
assertAboutEppResources().that(resource)
|
||||
private void assertTransferRequested(DomainResource domain) throws Exception {
|
||||
assertAboutDomains().that(domain)
|
||||
.hasTransferStatus(TransferStatus.PENDING).and()
|
||||
.hasTransferGainingClientId("NewRegistrar").and()
|
||||
.hasTransferLosingClientId("TheRegistrar").and()
|
||||
|
@ -114,9 +114,15 @@ public class DomainTransferRequestFlowTest
|
|||
.hasStatusValue(StatusValue.PENDING_TRANSFER);
|
||||
}
|
||||
|
||||
private void assertTransferApproved(EppResource resource) {
|
||||
private void assertTransferRequested(HostResource host) throws Exception {
|
||||
assertAboutEppResources().that(host)
|
||||
.hasCurrentSponsorClientId("TheRegistrar").and()
|
||||
.hasStatusValue(StatusValue.PENDING_TRANSFER);
|
||||
}
|
||||
|
||||
private void assertTransferApproved(DomainResource domain) {
|
||||
DateTime afterAutoAck = clock.nowUtc().plus(Registry.get("tld").getAutomaticTransferLength());
|
||||
assertAboutEppResources().that(resource)
|
||||
assertAboutDomains().that(domain)
|
||||
.hasTransferStatus(TransferStatus.SERVER_APPROVED).and()
|
||||
.hasCurrentSponsorClientId("NewRegistrar").and()
|
||||
.hasLastTransferTime(afterAutoAck).and()
|
||||
|
@ -124,6 +130,14 @@ public class DomainTransferRequestFlowTest
|
|||
.doesNotHaveStatusValue(StatusValue.PENDING_TRANSFER);
|
||||
}
|
||||
|
||||
private void assertTransferApproved(HostResource host) {
|
||||
DateTime afterAutoAck = clock.nowUtc().plus(Registry.get("tld").getAutomaticTransferLength());
|
||||
assertAboutEppResources().that(host)
|
||||
.hasCurrentSponsorClientId("NewRegistrar").and()
|
||||
.hasLastTransferTime(afterAutoAck).and()
|
||||
.doesNotHaveStatusValue(StatusValue.PENDING_TRANSFER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a successful test. The extraExpectedBillingEvents parameter consists of cancellation
|
||||
* billing event builders that have had all of their attributes set except for the parent history
|
||||
|
|
|
@ -167,7 +167,7 @@ public class ContactResourceTest extends EntityTestCase {
|
|||
ContactResource withNull = new ContactResource.Builder().setTransferData(null).build();
|
||||
ContactResource withEmpty = withNull.asBuilder().setTransferData(TransferData.EMPTY).build();
|
||||
assertThat(withNull).isEqualTo(withEmpty);
|
||||
assertThat(withEmpty.hasTransferData()).isFalse();
|
||||
assertThat(withEmpty.transferData).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -36,7 +36,6 @@ import com.google.common.collect.ImmutableSet;
|
|||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.VoidWork;
|
||||
import google.registry.model.EntityTestCase;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.domain.launch.ApplicationStatus;
|
||||
import google.registry.model.domain.launch.LaunchNotice;
|
||||
import google.registry.model.domain.launch.LaunchPhase;
|
||||
|
@ -47,9 +46,6 @@ import google.registry.model.eppcommon.Trid;
|
|||
import google.registry.model.host.HostResource;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.smd.EncodedSignedMark;
|
||||
import google.registry.model.transfer.TransferData;
|
||||
import google.registry.model.transfer.TransferData.TransferServerApproveEntity;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import google.registry.testing.ExceptionRule;
|
||||
import org.joda.money.Money;
|
||||
import org.joda.time.DateTime;
|
||||
|
@ -95,19 +91,6 @@ public class DomainApplicationTest extends EntityTestCase {
|
|||
.setDsData(ImmutableSet.of(DelegationSignerData.create(1, 2, 3, new byte[] {0, 1, 2})))
|
||||
.setLaunchNotice(
|
||||
LaunchNotice.create("tcnid", "validatorId", START_OF_TIME, START_OF_TIME))
|
||||
.setTransferData(
|
||||
new TransferData.Builder()
|
||||
.setExtendedRegistrationYears(0)
|
||||
.setGainingClientId("gaining")
|
||||
.setLosingClientId("losing")
|
||||
.setPendingTransferExpirationTime(clock.nowUtc())
|
||||
.setServerApproveEntities(
|
||||
ImmutableSet.<Key<? extends TransferServerApproveEntity>>of(
|
||||
Key.create(BillingEvent.OneTime.class, 1)))
|
||||
.setTransferRequestTime(clock.nowUtc())
|
||||
.setTransferStatus(TransferStatus.SERVER_APPROVED)
|
||||
.setTransferRequestTrid(Trid.create("client trid"))
|
||||
.build())
|
||||
.setCreationTrid(Trid.create("client creation trid"))
|
||||
.setPhase(LaunchPhase.LANDRUSH)
|
||||
// TODO(b/32447342): set period
|
||||
|
@ -183,14 +166,6 @@ public class DomainApplicationTest extends EntityTestCase {
|
|||
.isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyTransferDataBecomesNull() throws Exception {
|
||||
DomainApplication withNull = emptyBuilder().setTransferData(null).build();
|
||||
DomainApplication withEmpty = withNull.asBuilder().setTransferData(TransferData.EMPTY).build();
|
||||
assertThat(withNull).isEqualTo(withEmpty);
|
||||
assertThat(withEmpty.hasTransferData()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToHydratedString_notCircular() {
|
||||
// If there are circular references, this will overflow the stack.
|
||||
|
|
|
@ -231,7 +231,7 @@ public class DomainResourceTest extends EntityTestCase {
|
|||
newDomainResource("example.com").asBuilder().setTransferData(null).build();
|
||||
DomainResource withEmpty = withNull.asBuilder().setTransferData(TransferData.EMPTY).build();
|
||||
assertThat(withNull).isEqualTo(withEmpty);
|
||||
assertThat(withEmpty.hasTransferData()).isFalse();
|
||||
assertThat(withEmpty.transferData).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -149,14 +149,6 @@ public class HostResourceTest extends EntityTestCase {
|
|||
.isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyTransferDataBecomesNull() throws Exception {
|
||||
HostResource withNull = new HostResource.Builder().setTransferData(null).build();
|
||||
HostResource withEmpty = withNull.asBuilder().setTransferData(TransferData.EMPTY).build();
|
||||
assertThat(withNull).isEqualTo(withEmpty);
|
||||
assertThat(withEmpty.hasTransferData()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testImplicitStatusValues() {
|
||||
// OK is implicit if there's no other statuses.
|
||||
|
@ -205,7 +197,6 @@ public class HostResourceTest extends EntityTestCase {
|
|||
hostResource.asBuilder()
|
||||
.setLastSuperordinateChange(superordinateChangeTime)
|
||||
.setLastTransferTime(hostTransferTime)
|
||||
.setTransferData(null)
|
||||
.build());
|
||||
return hostResource.cloneProjectedAtTime(clock.nowUtc()).getLastTransferTime();
|
||||
}
|
||||
|
@ -279,8 +270,6 @@ public class HostResourceTest extends EntityTestCase {
|
|||
.build())
|
||||
.build());
|
||||
HostResource afterTransfer = hostResource.cloneProjectedAtTime(clock.nowUtc().plusDays(1));
|
||||
assertThat(afterTransfer.getTransferData().getTransferStatus())
|
||||
.isEqualTo(TransferStatus.SERVER_APPROVED);
|
||||
assertThat(afterTransfer.getCurrentSponsorClientId()).isEqualTo("winner");
|
||||
assertThat(afterTransfer.getLastTransferTime()).isEqualTo(clock.nowUtc().plusDays(1));
|
||||
}
|
||||
|
|
|
@ -206,7 +206,6 @@ class google.registry.model.domain.DomainApplication {
|
|||
google.registry.model.domain.launch.LaunchNotice launchNotice;
|
||||
google.registry.model.domain.launch.LaunchPhase phase;
|
||||
google.registry.model.eppcommon.Trid creationTrid;
|
||||
google.registry.model.transfer.TransferData transferData;
|
||||
java.lang.String creationClientId;
|
||||
java.lang.String currentSponsorClientId;
|
||||
java.lang.String fullyQualifiedDomainName;
|
||||
|
@ -233,7 +232,6 @@ class google.registry.model.domain.DomainBase {
|
|||
google.registry.model.UpdateAutoTimestamp updateTimestamp;
|
||||
google.registry.model.domain.DomainAuthInfo authInfo;
|
||||
google.registry.model.domain.launch.LaunchNotice launchNotice;
|
||||
google.registry.model.transfer.TransferData transferData;
|
||||
java.lang.String creationClientId;
|
||||
java.lang.String currentSponsorClientId;
|
||||
java.lang.String fullyQualifiedDomainName;
|
||||
|
@ -387,7 +385,6 @@ class google.registry.model.host.HostResource {
|
|||
com.googlecode.objectify.Key<google.registry.model.domain.DomainResource> superordinateDomain;
|
||||
google.registry.model.CreateAutoTimestamp creationTime;
|
||||
google.registry.model.UpdateAutoTimestamp updateTimestamp;
|
||||
google.registry.model.transfer.TransferData transferData;
|
||||
java.lang.String creationClientId;
|
||||
java.lang.String currentSponsorClientId;
|
||||
java.lang.String fullyQualifiedHostName;
|
||||
|
|
|
@ -26,7 +26,6 @@ import com.google.common.truth.Subject;
|
|||
import google.registry.model.EppResource;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import google.registry.testing.TruthChainer.And;
|
||||
import google.registry.testing.TruthChainer.Which;
|
||||
import java.util.List;
|
||||
|
@ -194,41 +193,6 @@ abstract class AbstractEppResourceSubject
|
|||
"has currentSponsorClientId");
|
||||
}
|
||||
|
||||
public And<S> hasTransferStatus(TransferStatus transferStatus) {
|
||||
return hasValue(
|
||||
transferStatus,
|
||||
actual().getTransferData().getTransferStatus(),
|
||||
"has transferStatus");
|
||||
}
|
||||
|
||||
public And<S> hasTransferRequestClientTrid(String clTrid) {
|
||||
return hasValue(
|
||||
clTrid,
|
||||
actual().getTransferData().getTransferRequestTrid().getClientTransactionId(),
|
||||
"has trid");
|
||||
}
|
||||
|
||||
public And<S> hasPendingTransferExpirationTime(DateTime pendingTransferExpirationTime) {
|
||||
return hasValue(
|
||||
pendingTransferExpirationTime,
|
||||
actual().getTransferData().getPendingTransferExpirationTime(),
|
||||
"has pendingTransferExpirationTime");
|
||||
}
|
||||
|
||||
public And<S> hasTransferGainingClientId(String gainingClientId) {
|
||||
return hasValue(
|
||||
gainingClientId,
|
||||
actual().getTransferData().getGainingClientId(),
|
||||
"has transfer ga");
|
||||
}
|
||||
|
||||
public And<S> hasTransferLosingClientId(String losingClientId) {
|
||||
return hasValue(
|
||||
losingClientId,
|
||||
actual().getTransferData().getLosingClientId(),
|
||||
"has transfer losingClientId");
|
||||
}
|
||||
|
||||
public And<S> isActiveAt(DateTime time) {
|
||||
if (!isActive(actual(), time)) {
|
||||
fail("is active at " + time);
|
||||
|
|
|
@ -22,7 +22,9 @@ import com.google.common.truth.FailureStrategy;
|
|||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.contact.PostalInfo;
|
||||
import google.registry.model.eppcommon.AuthInfo;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import google.registry.testing.TruthChainer.And;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** Truth subject for asserting things about {@link ContactResource} instances. */
|
||||
public final class ContactResourceSubject
|
||||
|
@ -124,6 +126,42 @@ public final class ContactResourceSubject
|
|||
return hasValue(pw, authInfo == null ? null : authInfo.getPw().getValue(), "has auth info pw");
|
||||
}
|
||||
|
||||
public And<ContactResourceSubject> hasTransferStatus(TransferStatus transferStatus) {
|
||||
return hasValue(
|
||||
transferStatus,
|
||||
actual().getTransferData().getTransferStatus(),
|
||||
"has transferStatus");
|
||||
}
|
||||
|
||||
public And<ContactResourceSubject> hasTransferRequestClientTrid(String clTrid) {
|
||||
return hasValue(
|
||||
clTrid,
|
||||
actual().getTransferData().getTransferRequestTrid().getClientTransactionId(),
|
||||
"has trid");
|
||||
}
|
||||
|
||||
public And<ContactResourceSubject> hasPendingTransferExpirationTime(
|
||||
DateTime pendingTransferExpirationTime) {
|
||||
return hasValue(
|
||||
pendingTransferExpirationTime,
|
||||
actual().getTransferData().getPendingTransferExpirationTime(),
|
||||
"has pendingTransferExpirationTime");
|
||||
}
|
||||
|
||||
public And<ContactResourceSubject> hasTransferGainingClientId(String gainingClientId) {
|
||||
return hasValue(
|
||||
gainingClientId,
|
||||
actual().getTransferData().getGainingClientId(),
|
||||
"has transfer ga");
|
||||
}
|
||||
|
||||
public And<ContactResourceSubject> hasTransferLosingClientId(String losingClientId) {
|
||||
return hasValue(
|
||||
losingClientId,
|
||||
actual().getTransferData().getLosingClientId(),
|
||||
"has transfer losingClientId");
|
||||
}
|
||||
|
||||
public static DelegatedVerb<ContactResourceSubject, ContactResource> assertAboutContacts() {
|
||||
return assertAbout(new SubjectFactory());
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertAbout;
|
|||
import com.google.common.truth.AbstractVerb.DelegatedVerb;
|
||||
import com.google.common.truth.FailureStrategy;
|
||||
import google.registry.model.domain.DomainResource;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import google.registry.testing.TruthChainer.And;
|
||||
import java.util.Objects;
|
||||
import org.joda.time.DateTime;
|
||||
|
@ -32,6 +33,42 @@ public final class DomainResourceSubject
|
|||
private static class SubjectFactory
|
||||
extends ReflectiveSubjectFactory<DomainResource, DomainResourceSubject>{}
|
||||
|
||||
public And<DomainResourceSubject> hasTransferStatus(TransferStatus transferStatus) {
|
||||
return hasValue(
|
||||
transferStatus,
|
||||
actual().getTransferData().getTransferStatus(),
|
||||
"has transferStatus");
|
||||
}
|
||||
|
||||
public And<DomainResourceSubject> hasTransferRequestClientTrid(String clTrid) {
|
||||
return hasValue(
|
||||
clTrid,
|
||||
actual().getTransferData().getTransferRequestTrid().getClientTransactionId(),
|
||||
"has trid");
|
||||
}
|
||||
|
||||
public And<DomainResourceSubject> hasPendingTransferExpirationTime(
|
||||
DateTime pendingTransferExpirationTime) {
|
||||
return hasValue(
|
||||
pendingTransferExpirationTime,
|
||||
actual().getTransferData().getPendingTransferExpirationTime(),
|
||||
"has pendingTransferExpirationTime");
|
||||
}
|
||||
|
||||
public And<DomainResourceSubject> hasTransferGainingClientId(String gainingClientId) {
|
||||
return hasValue(
|
||||
gainingClientId,
|
||||
actual().getTransferData().getGainingClientId(),
|
||||
"has transfer ga");
|
||||
}
|
||||
|
||||
public And<DomainResourceSubject> hasTransferLosingClientId(String losingClientId) {
|
||||
return hasValue(
|
||||
losingClientId,
|
||||
actual().getTransferData().getLosingClientId(),
|
||||
"has transfer losingClientId");
|
||||
}
|
||||
|
||||
public And<DomainResourceSubject> hasRegistrationExpirationTime(DateTime expiration) {
|
||||
if (!Objects.equals(actual().getRegistrationExpirationTime(), expiration)) {
|
||||
failWithBadResults(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue