Fix nits on flows:

Rename existingResource flows variable to be specific to EPP resource type and replace some explicit checks with helper methods.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=133774229
This commit is contained in:
cgoldfeder 2016-09-20 17:07:46 -07:00 committed by Ben McIlwain
parent df70da48a2
commit aed3c0f0d0
14 changed files with 125 additions and 156 deletions

View file

@ -31,6 +31,7 @@ import com.googlecode.objectify.Key;
import com.googlecode.objectify.Work; import com.googlecode.objectify.Work;
import google.registry.flows.EppException.AuthorizationErrorException; import google.registry.flows.EppException.AuthorizationErrorException;
import google.registry.flows.EppException.InvalidAuthorizationInformationErrorException; import google.registry.flows.EppException.InvalidAuthorizationInformationErrorException;
import google.registry.flows.exceptions.MissingTransferRequestAuthInfoException;
import google.registry.flows.exceptions.ResourceAlreadyExistsException; import google.registry.flows.exceptions.ResourceAlreadyExistsException;
import google.registry.flows.exceptions.ResourceStatusProhibitsOperationException; import google.registry.flows.exceptions.ResourceStatusProhibitsOperationException;
import google.registry.flows.exceptions.ResourceToDeleteIsReferencedException; import google.registry.flows.exceptions.ResourceToDeleteIsReferencedException;
@ -314,6 +315,15 @@ public class ResourceFlowUtils {
} }
} }
/** Check that the given AuthInfo is present and valid for a resource being transferred. */
public static void verifyRequiredAuthInfoForResourceTransfer(
Optional<AuthInfo> authInfo, ContactResource existingContact) throws EppException {
if (!authInfo.isPresent()) {
throw new MissingTransferRequestAuthInfoException();
}
verifyOptionalAuthInfoForResource(authInfo, existingContact);
}
/** Check that the given AuthInfo is valid for the given resource. */ /** Check that the given AuthInfo is valid for the given resource. */
public static void verifyAuthInfoForResource(AuthInfo authInfo, EppResource resource) public static void verifyAuthInfoForResource(AuthInfo authInfo, EppResource resource)
throws EppException { throws EppException {

View file

@ -14,10 +14,10 @@
package google.registry.flows.contact; package google.registry.flows.contact;
import static google.registry.flows.ResourceFlowUtils.verifyResourceDoesNotExist;
import static google.registry.flows.contact.ContactFlowUtils.validateAsciiPostalInfo; import static google.registry.flows.contact.ContactFlowUtils.validateAsciiPostalInfo;
import static google.registry.flows.contact.ContactFlowUtils.validateContactAgainstPolicy; import static google.registry.flows.contact.ContactFlowUtils.validateContactAgainstPolicy;
import static google.registry.model.EppResourceUtils.createContactHostRoid; import static google.registry.model.EppResourceUtils.createContactHostRoid;
import static google.registry.model.EppResourceUtils.loadByUniqueId;
import static google.registry.model.eppoutput.Result.Code.SUCCESS; import static google.registry.model.eppoutput.Result.Code.SUCCESS;
import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.ofy.ObjectifyService.ofy;
@ -27,7 +27,6 @@ import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.TargetId; import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow; import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow; import google.registry.flows.TransactionalFlow;
import google.registry.flows.exceptions.ResourceAlreadyExistsException;
import google.registry.model.contact.ContactCommand.Create; import google.registry.model.contact.ContactCommand.Create;
import google.registry.model.contact.ContactResource; import google.registry.model.contact.ContactResource;
import google.registry.model.contact.ContactResource.Builder; import google.registry.model.contact.ContactResource.Builder;
@ -64,28 +63,26 @@ public class ContactCreateFlow extends LoggedInFlow implements TransactionalFlow
@Override @Override
protected final EppOutput run() throws EppException { protected final EppOutput run() throws EppException {
Create command = (Create) resourceCommand; Create command = (Create) resourceCommand;
if (loadByUniqueId(ContactResource.class, targetId, now) != null) { verifyResourceDoesNotExist(ContactResource.class, targetId, now);
throw new ResourceAlreadyExistsException(targetId);
}
Builder builder = new Builder(); Builder builder = new Builder();
command.applyTo(builder); command.applyTo(builder);
ContactResource newResource = builder ContactResource newContact = builder
.setCreationClientId(clientId) .setCreationClientId(clientId)
.setCurrentSponsorClientId(clientId) .setCurrentSponsorClientId(clientId)
.setRepoId(createContactHostRoid(ObjectifyService.allocateId())) .setRepoId(createContactHostRoid(ObjectifyService.allocateId()))
.build(); .build();
validateAsciiPostalInfo(newResource.getInternationalizedPostalInfo()); validateAsciiPostalInfo(newContact.getInternationalizedPostalInfo());
validateContactAgainstPolicy(newResource); validateContactAgainstPolicy(newContact);
historyBuilder historyBuilder
.setType(HistoryEntry.Type.CONTACT_CREATE) .setType(HistoryEntry.Type.CONTACT_CREATE)
.setModificationTime(now) .setModificationTime(now)
.setXmlBytes(null) // We don't want to store contact details in the history entry. .setXmlBytes(null) // We don't want to store contact details in the history entry.
.setParent(Key.create(newResource)); .setParent(Key.create(newContact));
ofy().save().entities( ofy().save().entities(
newResource, newContact,
historyBuilder.build(), historyBuilder.build(),
ForeignKeyIndex.create(newResource, newResource.getDeletionTime()), ForeignKeyIndex.create(newContact, newContact.getDeletionTime()),
EppResourceIndex.create(Key.create(newResource))); EppResourceIndex.create(Key.create(newContact)));
return createOutput(SUCCESS, ContactCreateData.create(newResource.getContactId(), now)); return createOutput(SUCCESS, ContactCreateData.create(newContact.getContactId(), now));
} }
} }

View file

@ -15,10 +15,10 @@
package google.registry.flows.contact; package google.registry.flows.contact;
import static google.registry.flows.ResourceFlowUtils.failfastForAsyncDelete; import static google.registry.flows.ResourceFlowUtils.failfastForAsyncDelete;
import static google.registry.flows.ResourceFlowUtils.loadResourceToMutate;
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses; import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource; import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership; import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
import static google.registry.model.EppResourceUtils.loadByUniqueId;
import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING; import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING;
import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.ofy.ObjectifyService.ofy;
@ -33,7 +33,6 @@ import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow; import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow; import google.registry.flows.TransactionalFlow;
import google.registry.flows.async.AsyncFlowEnqueuer; import google.registry.flows.async.AsyncFlowEnqueuer;
import google.registry.flows.exceptions.ResourceToMutateDoesNotExistException;
import google.registry.model.contact.ContactResource; import google.registry.model.contact.ContactResource;
import google.registry.model.domain.DomainBase; import google.registry.model.domain.DomainBase;
import google.registry.model.domain.metadata.MetadataExtension; import google.registry.model.domain.metadata.MetadataExtension;
@ -83,23 +82,20 @@ public class ContactDeleteFlow extends LoggedInFlow implements TransactionalFlow
@Override @Override
public final EppOutput run() throws EppException { public final EppOutput run() throws EppException {
failfastForAsyncDelete(targetId, now, ContactResource.class, GET_REFERENCED_CONTACTS); failfastForAsyncDelete(targetId, now, ContactResource.class, GET_REFERENCED_CONTACTS);
ContactResource existingResource = loadByUniqueId(ContactResource.class, targetId, now); ContactResource existingContact = loadResourceToMutate(ContactResource.class, targetId, now);
if (existingResource == null) { verifyNoDisallowedStatuses(existingContact, DISALLOWED_STATUSES);
throw new ResourceToMutateDoesNotExistException(ContactResource.class, targetId); verifyOptionalAuthInfoForResource(authInfo, existingContact);
}
verifyNoDisallowedStatuses(existingResource, DISALLOWED_STATUSES);
verifyOptionalAuthInfoForResource(authInfo, existingResource);
if (!isSuperuser) { if (!isSuperuser) {
verifyResourceOwnership(clientId, existingResource); verifyResourceOwnership(clientId, existingContact);
} }
asyncFlowEnqueuer.enqueueAsyncDelete(existingResource, clientId, isSuperuser); asyncFlowEnqueuer.enqueueAsyncDelete(existingContact, clientId, isSuperuser);
ContactResource newResource = ContactResource newContact =
existingResource.asBuilder().addStatusValue(StatusValue.PENDING_DELETE).build(); existingContact.asBuilder().addStatusValue(StatusValue.PENDING_DELETE).build();
historyBuilder historyBuilder
.setType(HistoryEntry.Type.CONTACT_PENDING_DELETE) .setType(HistoryEntry.Type.CONTACT_PENDING_DELETE)
.setModificationTime(now) .setModificationTime(now)
.setParent(Key.create(existingResource)); .setParent(Key.create(existingContact));
ofy().save().<Object>entities(newResource, historyBuilder.build()); ofy().save().<Object>entities(newContact, historyBuilder.build());
return createOutput(SUCCESS_WITH_ACTION_PENDING); return createOutput(SUCCESS_WITH_ACTION_PENDING);
} }
} }

View file

@ -14,16 +14,15 @@
package google.registry.flows.contact; package google.registry.flows.contact;
import static google.registry.flows.ResourceFlowUtils.loadResourceForQuery;
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource; import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
import static google.registry.model.EppResourceUtils.cloneResourceWithLinkedStatus; import static google.registry.model.EppResourceUtils.cloneResourceWithLinkedStatus;
import static google.registry.model.EppResourceUtils.loadByUniqueId;
import static google.registry.model.eppoutput.Result.Code.SUCCESS; import static google.registry.model.eppoutput.Result.Code.SUCCESS;
import com.google.common.base.Optional; import com.google.common.base.Optional;
import google.registry.flows.EppException; import google.registry.flows.EppException;
import google.registry.flows.FlowModule.TargetId; import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow; import google.registry.flows.LoggedInFlow;
import google.registry.flows.exceptions.ResourceToQueryDoesNotExistException;
import google.registry.model.contact.ContactResource; import google.registry.model.contact.ContactResource;
import google.registry.model.eppcommon.AuthInfo; import google.registry.model.eppcommon.AuthInfo;
import google.registry.model.eppoutput.EppOutput; import google.registry.model.eppoutput.EppOutput;
@ -42,11 +41,8 @@ public class ContactInfoFlow extends LoggedInFlow {
@Override @Override
public final EppOutput run() throws EppException { public final EppOutput run() throws EppException {
ContactResource existingResource = loadByUniqueId(ContactResource.class, targetId, now); ContactResource contact = loadResourceForQuery(ContactResource.class, targetId, now);
if (existingResource == null) { verifyOptionalAuthInfoForResource(authInfo, contact);
throw new ResourceToQueryDoesNotExistException(ContactResource.class, targetId); return createOutput(SUCCESS, cloneResourceWithLinkedStatus(contact, now));
}
verifyOptionalAuthInfoForResource(authInfo, existingResource);
return createOutput(SUCCESS, cloneResourceWithLinkedStatus(existingResource, now));
} }
} }

View file

@ -15,11 +15,11 @@
package google.registry.flows.contact; package google.registry.flows.contact;
import static google.registry.flows.ResourceFlowUtils.approvePendingTransfer; import static google.registry.flows.ResourceFlowUtils.approvePendingTransfer;
import static google.registry.flows.ResourceFlowUtils.loadResourceToMutate;
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource; import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership; import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
import static google.registry.flows.contact.ContactFlowUtils.createGainingTransferPollMessage; import static google.registry.flows.contact.ContactFlowUtils.createGainingTransferPollMessage;
import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse; import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse;
import static google.registry.model.EppResourceUtils.loadByUniqueId;
import static google.registry.model.eppoutput.Result.Code.SUCCESS; import static google.registry.model.eppoutput.Result.Code.SUCCESS;
import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.ofy.ObjectifyService.ofy;
@ -31,7 +31,6 @@ import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow; import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow; import google.registry.flows.TransactionalFlow;
import google.registry.flows.exceptions.NotPendingTransferException; import google.registry.flows.exceptions.NotPendingTransferException;
import google.registry.flows.exceptions.ResourceToMutateDoesNotExistException;
import google.registry.model.contact.ContactResource; import google.registry.model.contact.ContactResource;
import google.registry.model.domain.metadata.MetadataExtension; import google.registry.model.domain.metadata.MetadataExtension;
import google.registry.model.eppcommon.AuthInfo; import google.registry.model.eppcommon.AuthInfo;
@ -67,30 +66,27 @@ public class ContactTransferApproveFlow extends LoggedInFlow implements Transact
@Override @Override
public final EppOutput run() throws EppException { public final EppOutput run() throws EppException {
ContactResource existingResource = loadByUniqueId(ContactResource.class, targetId, now); ContactResource existingContact = loadResourceToMutate(ContactResource.class, targetId, now);
if (existingResource == null) { verifyOptionalAuthInfoForResource(authInfo, existingContact);
throw new ResourceToMutateDoesNotExistException(ContactResource.class, targetId); TransferData transferData = existingContact.getTransferData();
}
verifyOptionalAuthInfoForResource(authInfo, existingResource);
TransferData transferData = existingResource.getTransferData();
if (transferData.getTransferStatus() != TransferStatus.PENDING) { if (transferData.getTransferStatus() != TransferStatus.PENDING) {
throw new NotPendingTransferException(targetId); throw new NotPendingTransferException(targetId);
} }
verifyResourceOwnership(clientId, existingResource); verifyResourceOwnership(clientId, existingContact);
ContactResource newResource = ContactResource newContact =
approvePendingTransfer(existingResource, TransferStatus.CLIENT_APPROVED, now); approvePendingTransfer(existingContact, TransferStatus.CLIENT_APPROVED, now);
HistoryEntry historyEntry = historyBuilder HistoryEntry historyEntry = historyBuilder
.setType(HistoryEntry.Type.CONTACT_TRANSFER_APPROVE) .setType(HistoryEntry.Type.CONTACT_TRANSFER_APPROVE)
.setModificationTime(now) .setModificationTime(now)
.setParent(Key.create(existingResource)) .setParent(Key.create(existingContact))
.build(); .build();
// Create a poll message for the gaining client. // Create a poll message for the gaining client.
PollMessage gainingPollMessage = PollMessage gainingPollMessage =
createGainingTransferPollMessage(targetId, newResource.getTransferData(), historyEntry); createGainingTransferPollMessage(targetId, newContact.getTransferData(), historyEntry);
ofy().save().<Object>entities(newResource, historyEntry, gainingPollMessage); ofy().save().<Object>entities(newContact, historyEntry, gainingPollMessage);
// Delete the billing event and poll messages that were written in case the transfer would have // Delete the billing event and poll messages that were written in case the transfer would have
// been implicitly server approved. // been implicitly server approved.
ofy().delete().keys(transferData.getServerApproveEntities()); ofy().delete().keys(transferData.getServerApproveEntities());
return createOutput(SUCCESS, createTransferResponse(targetId, newResource.getTransferData())); return createOutput(SUCCESS, createTransferResponse(targetId, newContact.getTransferData()));
} }
} }

View file

@ -15,10 +15,10 @@
package google.registry.flows.contact; package google.registry.flows.contact;
import static google.registry.flows.ResourceFlowUtils.denyPendingTransfer; import static google.registry.flows.ResourceFlowUtils.denyPendingTransfer;
import static google.registry.flows.ResourceFlowUtils.loadResourceToMutate;
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource; import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
import static google.registry.flows.contact.ContactFlowUtils.createLosingTransferPollMessage; import static google.registry.flows.contact.ContactFlowUtils.createLosingTransferPollMessage;
import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse; import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse;
import static google.registry.model.EppResourceUtils.loadByUniqueId;
import static google.registry.model.eppoutput.Result.Code.SUCCESS; import static google.registry.model.eppoutput.Result.Code.SUCCESS;
import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.ofy.ObjectifyService.ofy;
@ -31,7 +31,6 @@ import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow; import google.registry.flows.TransactionalFlow;
import google.registry.flows.exceptions.NotPendingTransferException; import google.registry.flows.exceptions.NotPendingTransferException;
import google.registry.flows.exceptions.NotTransferInitiatorException; import google.registry.flows.exceptions.NotTransferInitiatorException;
import google.registry.flows.exceptions.ResourceToMutateDoesNotExistException;
import google.registry.model.contact.ContactResource; import google.registry.model.contact.ContactResource;
import google.registry.model.domain.metadata.MetadataExtension; import google.registry.model.domain.metadata.MetadataExtension;
import google.registry.model.eppcommon.AuthInfo; import google.registry.model.eppcommon.AuthInfo;
@ -67,33 +66,29 @@ public class ContactTransferCancelFlow extends LoggedInFlow implements Transacti
@Override @Override
protected final EppOutput run() throws EppException { protected final EppOutput run() throws EppException {
ContactResource existingResource = loadByUniqueId(ContactResource.class, targetId, now); ContactResource existingContact = loadResourceToMutate(ContactResource.class, targetId, now);
// Fail if the object doesn't exist or was deleted. verifyOptionalAuthInfoForResource(authInfo, existingContact);
if (existingResource == null) { TransferData transferData = existingContact.getTransferData();
throw new ResourceToMutateDoesNotExistException(ContactResource.class, targetId);
}
verifyOptionalAuthInfoForResource(authInfo, existingResource);
TransferData transferData = existingResource.getTransferData();
if (transferData.getTransferStatus() != TransferStatus.PENDING) { if (transferData.getTransferStatus() != TransferStatus.PENDING) {
throw new NotPendingTransferException(targetId); throw new NotPendingTransferException(targetId);
} }
if (!clientId.equals(transferData.getGainingClientId())) { if (!clientId.equals(transferData.getGainingClientId())) {
throw new NotTransferInitiatorException(); throw new NotTransferInitiatorException();
} }
ContactResource newResource = ContactResource newContact =
denyPendingTransfer(existingResource, TransferStatus.CLIENT_CANCELLED, now); denyPendingTransfer(existingContact, TransferStatus.CLIENT_CANCELLED, now);
HistoryEntry historyEntry = historyBuilder HistoryEntry historyEntry = historyBuilder
.setType(HistoryEntry.Type.CONTACT_TRANSFER_CANCEL) .setType(HistoryEntry.Type.CONTACT_TRANSFER_CANCEL)
.setModificationTime(now) .setModificationTime(now)
.setParent(Key.create(existingResource)) .setParent(Key.create(existingContact))
.build(); .build();
// Create a poll message for the losing client. // Create a poll message for the losing client.
PollMessage losingPollMessage = PollMessage losingPollMessage =
createLosingTransferPollMessage(targetId, newResource.getTransferData(), historyEntry); createLosingTransferPollMessage(targetId, newContact.getTransferData(), historyEntry);
ofy().save().<Object>entities(newResource, historyEntry, losingPollMessage); ofy().save().<Object>entities(newContact, historyEntry, losingPollMessage);
// Delete the billing event and poll messages that were written in case the transfer would have // Delete the billing event and poll messages that were written in case the transfer would have
// been implicitly server approved. // been implicitly server approved.
ofy().delete().keys(transferData.getServerApproveEntities()); ofy().delete().keys(transferData.getServerApproveEntities());
return createOutput(SUCCESS, createTransferResponse(targetId, newResource.getTransferData())); return createOutput(SUCCESS, createTransferResponse(targetId, newContact.getTransferData()));
} }
} }

View file

@ -14,9 +14,9 @@
package google.registry.flows.contact; package google.registry.flows.contact;
import static google.registry.flows.ResourceFlowUtils.loadResourceForQuery;
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource; import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse; import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse;
import static google.registry.model.EppResourceUtils.loadByUniqueId;
import static google.registry.model.eppoutput.Result.Code.SUCCESS; import static google.registry.model.eppoutput.Result.Code.SUCCESS;
import com.google.common.base.Optional; import com.google.common.base.Optional;
@ -26,7 +26,6 @@ import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow; import google.registry.flows.LoggedInFlow;
import google.registry.flows.exceptions.NoTransferHistoryToQueryException; import google.registry.flows.exceptions.NoTransferHistoryToQueryException;
import google.registry.flows.exceptions.NotAuthorizedToViewTransferException; import google.registry.flows.exceptions.NotAuthorizedToViewTransferException;
import google.registry.flows.exceptions.ResourceToQueryDoesNotExistException;
import google.registry.model.contact.ContactResource; import google.registry.model.contact.ContactResource;
import google.registry.model.eppcommon.AuthInfo; import google.registry.model.eppcommon.AuthInfo;
import google.registry.model.eppoutput.EppOutput; import google.registry.model.eppoutput.EppOutput;
@ -49,24 +48,20 @@ public class ContactTransferQueryFlow extends LoggedInFlow {
@Override @Override
public final EppOutput run() throws EppException { public final EppOutput run() throws EppException {
ContactResource existingResource = loadByUniqueId(ContactResource.class, targetId, now); ContactResource contact = loadResourceForQuery(ContactResource.class, targetId, now);
if (existingResource == null) { verifyOptionalAuthInfoForResource(authInfo, contact);
throw new ResourceToQueryDoesNotExistException(ContactResource.class, targetId);
}
verifyOptionalAuthInfoForResource(authInfo, existingResource);
// Most of the fields on the transfer response are required, so there's no way to return valid // 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). // XML if the object has never been transferred (and hence the fields aren't populated).
if (existingResource.getTransferData().getTransferStatus() == null) { if (contact.getTransferData().getTransferStatus() == null) {
throw new NoTransferHistoryToQueryException(); throw new NoTransferHistoryToQueryException();
} }
// Note that the authorization info on the command (if present) has already been verified. If // Note that the authorization info on the command (if present) has already been verified. If
// it's present, then the other checks are unnecessary. // it's present, then the other checks are unnecessary.
if (!authInfo.isPresent() if (!authInfo.isPresent()
&& !clientId.equals(existingResource.getTransferData().getGainingClientId()) && !clientId.equals(contact.getTransferData().getGainingClientId())
&& !clientId.equals(existingResource.getTransferData().getLosingClientId())) { && !clientId.equals(contact.getTransferData().getLosingClientId())) {
throw new NotAuthorizedToViewTransferException(); throw new NotAuthorizedToViewTransferException();
} }
return createOutput( return createOutput(SUCCESS, createTransferResponse(targetId, contact.getTransferData()));
SUCCESS, createTransferResponse(targetId, existingResource.getTransferData()));
} }
} }

View file

@ -15,11 +15,11 @@
package google.registry.flows.contact; package google.registry.flows.contact;
import static google.registry.flows.ResourceFlowUtils.denyPendingTransfer; import static google.registry.flows.ResourceFlowUtils.denyPendingTransfer;
import static google.registry.flows.ResourceFlowUtils.loadResourceToMutate;
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource; import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership; import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
import static google.registry.flows.contact.ContactFlowUtils.createGainingTransferPollMessage; import static google.registry.flows.contact.ContactFlowUtils.createGainingTransferPollMessage;
import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse; import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse;
import static google.registry.model.EppResourceUtils.loadByUniqueId;
import static google.registry.model.eppoutput.Result.Code.SUCCESS; import static google.registry.model.eppoutput.Result.Code.SUCCESS;
import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.ofy.ObjectifyService.ofy;
@ -31,7 +31,6 @@ import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow; import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow; import google.registry.flows.TransactionalFlow;
import google.registry.flows.exceptions.NotPendingTransferException; import google.registry.flows.exceptions.NotPendingTransferException;
import google.registry.flows.exceptions.ResourceToMutateDoesNotExistException;
import google.registry.model.contact.ContactResource; import google.registry.model.contact.ContactResource;
import google.registry.model.domain.metadata.MetadataExtension; import google.registry.model.domain.metadata.MetadataExtension;
import google.registry.model.eppcommon.AuthInfo; import google.registry.model.eppcommon.AuthInfo;
@ -65,29 +64,26 @@ public class ContactTransferRejectFlow extends LoggedInFlow implements Transacti
@Override @Override
protected final EppOutput run() throws EppException { protected final EppOutput run() throws EppException {
ContactResource existingResource = loadByUniqueId(ContactResource.class, targetId, now); ContactResource existingContact = loadResourceToMutate(ContactResource.class, targetId, now);
if (existingResource == null) { verifyOptionalAuthInfoForResource(authInfo, existingContact);
throw new ResourceToMutateDoesNotExistException(ContactResource.class, targetId); TransferData transferData = existingContact.getTransferData();
}
verifyOptionalAuthInfoForResource(authInfo, existingResource);
TransferData transferData = existingResource.getTransferData();
if (transferData.getTransferStatus() != TransferStatus.PENDING) { if (transferData.getTransferStatus() != TransferStatus.PENDING) {
throw new NotPendingTransferException(targetId); throw new NotPendingTransferException(targetId);
} }
verifyResourceOwnership(clientId, existingResource); verifyResourceOwnership(clientId, existingContact);
ContactResource newResource = ContactResource newContact =
denyPendingTransfer(existingResource, TransferStatus.CLIENT_REJECTED, now); denyPendingTransfer(existingContact, TransferStatus.CLIENT_REJECTED, now);
HistoryEntry historyEntry = historyBuilder HistoryEntry historyEntry = historyBuilder
.setType(HistoryEntry.Type.CONTACT_TRANSFER_REJECT) .setType(HistoryEntry.Type.CONTACT_TRANSFER_REJECT)
.setModificationTime(now) .setModificationTime(now)
.setParent(Key.create(existingResource)) .setParent(Key.create(existingContact))
.build(); .build();
PollMessage gainingPollMessage = PollMessage gainingPollMessage =
createGainingTransferPollMessage(targetId, newResource.getTransferData(), historyEntry); createGainingTransferPollMessage(targetId, newContact.getTransferData(), historyEntry);
ofy().save().<Object>entities(newResource, historyEntry, gainingPollMessage); ofy().save().<Object>entities(newContact, historyEntry, gainingPollMessage);
// Delete the billing event and poll messages that were written in case the transfer would have // Delete the billing event and poll messages that were written in case the transfer would have
// been implicitly server approved. // been implicitly server approved.
ofy().delete().keys(transferData.getServerApproveEntities()); ofy().delete().keys(transferData.getServerApproveEntities());
return createOutput(SUCCESS, createTransferResponse(targetId, newResource.getTransferData())); return createOutput(SUCCESS, createTransferResponse(targetId, newContact.getTransferData()));
} }
} }

View file

@ -14,12 +14,12 @@
package google.registry.flows.contact; package google.registry.flows.contact;
import static google.registry.flows.ResourceFlowUtils.verifyAuthInfoForResource; import static google.registry.flows.ResourceFlowUtils.loadResourceToMutate;
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses; import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
import static google.registry.flows.ResourceFlowUtils.verifyRequiredAuthInfoForResourceTransfer;
import static google.registry.flows.contact.ContactFlowUtils.createGainingTransferPollMessage; import static google.registry.flows.contact.ContactFlowUtils.createGainingTransferPollMessage;
import static google.registry.flows.contact.ContactFlowUtils.createLosingTransferPollMessage; import static google.registry.flows.contact.ContactFlowUtils.createLosingTransferPollMessage;
import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse; import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse;
import static google.registry.model.EppResourceUtils.loadByUniqueId;
import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING; import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING;
import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.ofy.ObjectifyService.ofy;
@ -33,9 +33,7 @@ import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.LoggedInFlow; import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow; import google.registry.flows.TransactionalFlow;
import google.registry.flows.exceptions.AlreadyPendingTransferException; import google.registry.flows.exceptions.AlreadyPendingTransferException;
import google.registry.flows.exceptions.MissingTransferRequestAuthInfoException;
import google.registry.flows.exceptions.ObjectAlreadySponsoredException; import google.registry.flows.exceptions.ObjectAlreadySponsoredException;
import google.registry.flows.exceptions.ResourceToMutateDoesNotExistException;
import google.registry.model.contact.ContactResource; import google.registry.model.contact.ContactResource;
import google.registry.model.domain.metadata.MetadataExtension; import google.registry.model.domain.metadata.MetadataExtension;
import google.registry.model.eppcommon.AuthInfo; import google.registry.model.eppcommon.AuthInfo;
@ -79,28 +77,22 @@ public class ContactTransferRequestFlow extends LoggedInFlow implements Transact
@Override @Override
protected final EppOutput run() throws EppException { protected final EppOutput run() throws EppException {
ContactResource existingResource = loadByUniqueId(ContactResource.class, targetId, now); ContactResource existingContact = loadResourceToMutate(ContactResource.class, targetId, now);
if (existingResource == null) { verifyRequiredAuthInfoForResourceTransfer(authInfo, existingContact);
throw new ResourceToMutateDoesNotExistException(ContactResource.class, targetId);
}
if (!authInfo.isPresent()) {
throw new MissingTransferRequestAuthInfoException();
}
verifyAuthInfoForResource(authInfo.get(), existingResource);
// Verify that the resource does not already have a pending transfer. // Verify that the resource does not already have a pending transfer.
if (TransferStatus.PENDING.equals(existingResource.getTransferData().getTransferStatus())) { if (TransferStatus.PENDING.equals(existingContact.getTransferData().getTransferStatus())) {
throw new AlreadyPendingTransferException(targetId); throw new AlreadyPendingTransferException(targetId);
} }
String losingClientId = existingResource.getCurrentSponsorClientId(); String losingClientId = existingContact.getCurrentSponsorClientId();
// Verify that this client doesn't already sponsor this resource. // Verify that this client doesn't already sponsor this resource.
if (gainingClientId.equals(losingClientId)) { if (gainingClientId.equals(losingClientId)) {
throw new ObjectAlreadySponsoredException(); throw new ObjectAlreadySponsoredException();
} }
verifyNoDisallowedStatuses(existingResource, DISALLOWED_STATUSES); verifyNoDisallowedStatuses(existingContact, DISALLOWED_STATUSES);
HistoryEntry historyEntry = historyBuilder HistoryEntry historyEntry = historyBuilder
.setType(HistoryEntry.Type.CONTACT_TRANSFER_REQUEST) .setType(HistoryEntry.Type.CONTACT_TRANSFER_REQUEST)
.setModificationTime(now) .setModificationTime(now)
.setParent(Key.create(existingResource)) .setParent(Key.create(existingContact))
.build(); .build();
DateTime transferExpirationTime = now.plus(automaticTransferLength); DateTime transferExpirationTime = now.plus(automaticTransferLength);
TransferData serverApproveTransferData = new TransferData.Builder() TransferData serverApproveTransferData = new TransferData.Builder()
@ -129,19 +121,19 @@ public class ContactTransferRequestFlow extends LoggedInFlow implements Transact
createLosingTransferPollMessage(targetId, pendingTransferData, historyEntry).asBuilder() createLosingTransferPollMessage(targetId, pendingTransferData, historyEntry).asBuilder()
.setEventTime(now) // Unlike the serverApprove messages, this applies immediately. .setEventTime(now) // Unlike the serverApprove messages, this applies immediately.
.build(); .build();
ContactResource newResource = existingResource.asBuilder() ContactResource newContact = existingContact.asBuilder()
.setTransferData(pendingTransferData) .setTransferData(pendingTransferData)
.addStatusValue(StatusValue.PENDING_TRANSFER) .addStatusValue(StatusValue.PENDING_TRANSFER)
.build(); .build();
ofy().save().<Object>entities( ofy().save().<Object>entities(
newResource, newContact,
historyEntry, historyEntry,
requestPollMessage, requestPollMessage,
serverApproveGainingPollMessage, serverApproveGainingPollMessage,
serverApproveLosingPollMessage); serverApproveLosingPollMessage);
return createOutput( return createOutput(
SUCCESS_WITH_ACTION_PENDING, SUCCESS_WITH_ACTION_PENDING,
createTransferResponse(targetId, newResource.getTransferData())); createTransferResponse(targetId, newContact.getTransferData()));
} }
} }

View file

@ -14,12 +14,12 @@
package google.registry.flows.contact; package google.registry.flows.contact;
import static google.registry.flows.ResourceFlowUtils.loadResourceToMutate;
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses; import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource; import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfoForResource;
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership; import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
import static google.registry.flows.contact.ContactFlowUtils.validateAsciiPostalInfo; import static google.registry.flows.contact.ContactFlowUtils.validateAsciiPostalInfo;
import static google.registry.flows.contact.ContactFlowUtils.validateContactAgainstPolicy; import static google.registry.flows.contact.ContactFlowUtils.validateContactAgainstPolicy;
import static google.registry.model.EppResourceUtils.loadByUniqueId;
import static google.registry.model.eppoutput.Result.Code.SUCCESS; import static google.registry.model.eppoutput.Result.Code.SUCCESS;
import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.ofy.ObjectifyService.ofy;
@ -34,7 +34,6 @@ import google.registry.flows.LoggedInFlow;
import google.registry.flows.TransactionalFlow; import google.registry.flows.TransactionalFlow;
import google.registry.flows.exceptions.AddRemoveSameValueEppException; import google.registry.flows.exceptions.AddRemoveSameValueEppException;
import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException; import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException;
import google.registry.flows.exceptions.ResourceToMutateDoesNotExistException;
import google.registry.flows.exceptions.StatusNotClientSettableException; import google.registry.flows.exceptions.StatusNotClientSettableException;
import google.registry.model.contact.ContactCommand.Update; import google.registry.model.contact.ContactCommand.Update;
import google.registry.model.contact.ContactResource; import google.registry.model.contact.ContactResource;
@ -86,13 +85,10 @@ public class ContactUpdateFlow extends LoggedInFlow implements TransactionalFlow
@Override @Override
public final EppOutput run() throws EppException { public final EppOutput run() throws EppException {
Update command = (Update) resourceCommand; Update command = (Update) resourceCommand;
ContactResource existingResource = loadByUniqueId(ContactResource.class, targetId, now); ContactResource existingContact = loadResourceToMutate(ContactResource.class, targetId, now);
if (existingResource == null) { verifyOptionalAuthInfoForResource(authInfo, existingContact);
throw new ResourceToMutateDoesNotExistException(ContactResource.class, targetId);
}
verifyOptionalAuthInfoForResource(authInfo, existingResource);
if (!isSuperuser) { if (!isSuperuser) {
verifyResourceOwnership(clientId, existingResource); verifyResourceOwnership(clientId, existingContact);
} }
for (StatusValue statusValue : Sets.union( for (StatusValue statusValue : Sets.union(
command.getInnerAdd().getStatusValues(), command.getInnerAdd().getStatusValues(),
@ -101,32 +97,32 @@ public class ContactUpdateFlow extends LoggedInFlow implements TransactionalFlow
throw new StatusNotClientSettableException(statusValue.getXmlName()); throw new StatusNotClientSettableException(statusValue.getXmlName());
} }
} }
verifyNoDisallowedStatuses(existingResource, DISALLOWED_STATUSES); verifyNoDisallowedStatuses(existingContact, DISALLOWED_STATUSES);
historyBuilder historyBuilder
.setType(HistoryEntry.Type.CONTACT_UPDATE) .setType(HistoryEntry.Type.CONTACT_UPDATE)
.setModificationTime(now) .setModificationTime(now)
.setXmlBytes(null) // We don't want to store contact details in the history entry. .setXmlBytes(null) // We don't want to store contact details in the history entry.
.setParent(Key.create(existingResource)); .setParent(Key.create(existingContact));
Builder builder = existingResource.asBuilder(); Builder builder = existingContact.asBuilder();
try { try {
command.applyTo(builder); command.applyTo(builder);
} catch (AddRemoveSameValueException e) { } catch (AddRemoveSameValueException e) {
throw new AddRemoveSameValueEppException(); throw new AddRemoveSameValueEppException();
} }
ContactResource newResource = builder ContactResource newContact = builder
.setLastEppUpdateTime(now) .setLastEppUpdateTime(now)
.setLastEppUpdateClientId(clientId) .setLastEppUpdateClientId(clientId)
.build(); .build();
// If the resource is marked with clientUpdateProhibited, and this update did not clear that // If the resource is marked with clientUpdateProhibited, and this update did not clear that
// status, then the update must be disallowed (unless a superuser is requesting the change). // status, then the update must be disallowed (unless a superuser is requesting the change).
if (!isSuperuser if (!isSuperuser
&& existingResource.getStatusValues().contains(StatusValue.CLIENT_UPDATE_PROHIBITED) && existingContact.getStatusValues().contains(StatusValue.CLIENT_UPDATE_PROHIBITED)
&& newResource.getStatusValues().contains(StatusValue.CLIENT_UPDATE_PROHIBITED)) { && newContact.getStatusValues().contains(StatusValue.CLIENT_UPDATE_PROHIBITED)) {
throw new ResourceHasClientUpdateProhibitedException(); throw new ResourceHasClientUpdateProhibitedException();
} }
validateAsciiPostalInfo(newResource.getInternationalizedPostalInfo()); validateAsciiPostalInfo(newContact.getInternationalizedPostalInfo());
validateContactAgainstPolicy(newResource); validateContactAgainstPolicy(newContact);
ofy().save().<Object>entities(newResource, historyBuilder.build()); ofy().save().<Object>entities(newContact, historyBuilder.build());
return createOutput(SUCCESS); return createOutput(SUCCESS);
} }
} }

View file

@ -96,7 +96,7 @@ public class HostCreateFlow extends LoggedInFlow implements TransactionalFlow {
} }
Builder builder = new Builder(); Builder builder = new Builder();
command.applyTo(builder); command.applyTo(builder);
HostResource newResource = builder HostResource newHost = builder
.setCreationClientId(clientId) .setCreationClientId(clientId)
.setCurrentSponsorClientId(clientId) .setCurrentSponsorClientId(clientId)
.setRepoId(createContactHostRoid(ObjectifyService.allocateId())) .setRepoId(createContactHostRoid(ObjectifyService.allocateId()))
@ -106,12 +106,12 @@ public class HostCreateFlow extends LoggedInFlow implements TransactionalFlow {
historyBuilder historyBuilder
.setType(HistoryEntry.Type.HOST_CREATE) .setType(HistoryEntry.Type.HOST_CREATE)
.setModificationTime(now) .setModificationTime(now)
.setParent(Key.create(newResource)); .setParent(Key.create(newHost));
ImmutableSet<ImmutableObject> entitiesToSave = ImmutableSet.of( ImmutableSet<ImmutableObject> entitiesToSave = ImmutableSet.of(
newResource, newHost,
historyBuilder.build(), historyBuilder.build(),
ForeignKeyIndex.create(newResource, newResource.getDeletionTime()), ForeignKeyIndex.create(newHost, newHost.getDeletionTime()),
EppResourceIndex.create(Key.create(newResource))); EppResourceIndex.create(Key.create(newHost)));
if (superordinateDomain.isPresent()) { if (superordinateDomain.isPresent()) {
entitiesToSave = union( entitiesToSave = union(
entitiesToSave, entitiesToSave,

View file

@ -79,20 +79,20 @@ public class HostDeleteFlow extends LoggedInFlow implements TransactionalFlow {
@Override @Override
public final EppOutput run() throws EppException { public final EppOutput run() throws EppException {
failfastForAsyncDelete(targetId, now, HostResource.class, GET_NAMESERVERS); failfastForAsyncDelete(targetId, now, HostResource.class, GET_NAMESERVERS);
HostResource existingResource = loadResourceToMutate(HostResource.class, targetId, now); HostResource existingHost = loadResourceToMutate(HostResource.class, targetId, now);
verifyNoDisallowedStatuses(existingResource, DISALLOWED_STATUSES); verifyNoDisallowedStatuses(existingHost, DISALLOWED_STATUSES);
verifyOptionalAuthInfoForResource(authInfo, existingResource); verifyOptionalAuthInfoForResource(authInfo, existingHost);
if (!isSuperuser) { if (!isSuperuser) {
verifyResourceOwnership(clientId, existingResource); verifyResourceOwnership(clientId, existingHost);
} }
asyncFlowEnqueuer.enqueueAsyncDelete(existingResource, clientId, isSuperuser); asyncFlowEnqueuer.enqueueAsyncDelete(existingHost, clientId, isSuperuser);
HostResource newResource = HostResource newHost =
existingResource.asBuilder().addStatusValue(StatusValue.PENDING_DELETE).build(); existingHost.asBuilder().addStatusValue(StatusValue.PENDING_DELETE).build();
historyBuilder historyBuilder
.setType(HistoryEntry.Type.HOST_PENDING_DELETE) .setType(HistoryEntry.Type.HOST_PENDING_DELETE)
.setModificationTime(now) .setModificationTime(now)
.setParent(Key.create(existingResource)); .setParent(Key.create(existingHost));
ofy().save().<Object>entities(newResource, historyBuilder.build()); ofy().save().<Object>entities(newHost, historyBuilder.build());
return createOutput(SUCCESS_WITH_ACTION_PENDING); return createOutput(SUCCESS_WITH_ACTION_PENDING);
} }
} }

View file

@ -41,8 +41,8 @@ public class HostInfoFlow extends LoggedInFlow {
@Override @Override
public EppOutput run() throws EppException { public EppOutput run() throws EppException {
HostResource existingResource = loadResourceForQuery(HostResource.class, targetId, now); HostResource host = loadResourceForQuery(HostResource.class, targetId, now);
verifyOptionalAuthInfoForResource(authInfo, existingResource); verifyOptionalAuthInfoForResource(authInfo, host);
return createOutput(SUCCESS, cloneResourceWithLinkedStatus(existingResource, now)); return createOutput(SUCCESS, cloneResourceWithLinkedStatus(host, now));
} }
} }

View file

@ -106,17 +106,17 @@ public class HostUpdateFlow extends LoggedInFlow implements TransactionalFlow {
public final EppOutput run() throws EppException { public final EppOutput run() throws EppException {
Update command = (Update) resourceCommand; Update command = (Update) resourceCommand;
String suppliedNewHostName = command.getInnerChange().getFullyQualifiedHostName(); String suppliedNewHostName = command.getInnerChange().getFullyQualifiedHostName();
HostResource existingResource = loadResourceToMutate(HostResource.class, targetId, now); HostResource existingHost = loadResourceToMutate(HostResource.class, targetId, now);
boolean isHostRename = suppliedNewHostName != null; boolean isHostRename = suppliedNewHostName != null;
String oldHostName = targetId; String oldHostName = targetId;
String newHostName = firstNonNull(suppliedNewHostName, oldHostName); String newHostName = firstNonNull(suppliedNewHostName, oldHostName);
Optional<DomainResource> superordinateDomain = Optional<DomainResource> superordinateDomain =
Optional.fromNullable(lookupSuperordinateDomain(validateHostName(newHostName), now)); Optional.fromNullable(lookupSuperordinateDomain(validateHostName(newHostName), now));
verifyUpdateAllowed(command, existingResource, superordinateDomain.orNull()); verifyUpdateAllowed(command, existingHost, superordinateDomain.orNull());
if (isHostRename && loadAndGetKey(HostResource.class, newHostName, now) != null) { if (isHostRename && loadAndGetKey(HostResource.class, newHostName, now) != null) {
throw new HostAlreadyExistsException(newHostName); throw new HostAlreadyExistsException(newHostName);
} }
Builder builder = existingResource.asBuilder(); Builder builder = existingHost.asBuilder();
try { try {
command.applyTo(builder); command.applyTo(builder);
} catch (AddRemoveSameValueException e) { } catch (AddRemoveSameValueException e) {
@ -132,23 +132,23 @@ public class HostUpdateFlow extends LoggedInFlow implements TransactionalFlow {
superordinateDomain.isPresent() ? Key.create(superordinateDomain.get()) : null) superordinateDomain.isPresent() ? Key.create(superordinateDomain.get()) : null)
.setLastSuperordinateChange(superordinateDomain == null ? null : now); .setLastSuperordinateChange(superordinateDomain == null ? null : now);
// Rely on the host's cloneProjectedAtTime() method to handle setting of transfer data. // Rely on the host's cloneProjectedAtTime() method to handle setting of transfer data.
HostResource newResource = builder.build().cloneProjectedAtTime(now); HostResource newHost = builder.build().cloneProjectedAtTime(now);
verifyHasIpsIffIsExternal(command, existingResource, newResource); verifyHasIpsIffIsExternal(command, existingHost, newHost);
ImmutableSet.Builder<ImmutableObject> entitiesToSave = new ImmutableSet.Builder<>(); ImmutableSet.Builder<ImmutableObject> entitiesToSave = new ImmutableSet.Builder<>();
entitiesToSave.add(newResource); entitiesToSave.add(newHost);
// Keep the {@link ForeignKeyIndex} for this host up to date. // Keep the {@link ForeignKeyIndex} for this host up to date.
if (isHostRename) { if (isHostRename) {
// Update the foreign key for the old host name and save one for the new host name. // Update the foreign key for the old host name and save one for the new host name.
entitiesToSave.add( entitiesToSave.add(
ForeignKeyIndex.create(existingResource, now), ForeignKeyIndex.create(existingHost, now),
ForeignKeyIndex.create(newResource, newResource.getDeletionTime())); ForeignKeyIndex.create(newHost, newHost.getDeletionTime()));
updateSuperordinateDomains(existingResource, newResource); updateSuperordinateDomains(existingHost, newHost);
} }
enqueueTasks(existingResource, newResource); enqueueTasks(existingHost, newHost);
entitiesToSave.add(historyBuilder entitiesToSave.add(historyBuilder
.setType(HistoryEntry.Type.HOST_UPDATE) .setType(HistoryEntry.Type.HOST_UPDATE)
.setModificationTime(now) .setModificationTime(now)
.setParent(Key.create(existingResource)) .setParent(Key.create(existingHost))
.build()); .build());
ofy().save().entities(entitiesToSave.build()); ofy().save().entities(entitiesToSave.build());
return createOutput(SUCCESS); return createOutput(SUCCESS);