diff --git a/docs/flows.md b/docs/flows.md index 34ebda932..beb177300 100644 --- a/docs/flows.md +++ b/docs/flows.md @@ -70,6 +70,8 @@ registrar that owns the contact or to a registrar that already supplied it. ### Errors +* 2201 + * The specified resource belongs to another client. * 2303 * Resource with this id does not exist. diff --git a/java/google/registry/flows/contact/ContactInfoFlow.java b/java/google/registry/flows/contact/ContactInfoFlow.java index 82a55cbc4..9a3e43299 100644 --- a/java/google/registry/flows/contact/ContactInfoFlow.java +++ b/java/google/registry/flows/contact/ContactInfoFlow.java @@ -16,7 +16,7 @@ package google.registry.flows.contact; import static google.registry.flows.FlowUtils.validateClientIsLoggedIn; import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence; -import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo; +import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership; import static google.registry.model.EppResourceUtils.isLinked; import com.google.common.collect.ImmutableSet; @@ -25,6 +25,7 @@ import google.registry.flows.EppException; import google.registry.flows.ExtensionManager; import google.registry.flows.Flow; import google.registry.flows.FlowModule.ClientId; +import google.registry.flows.FlowModule.Superuser; import google.registry.flows.FlowModule.TargetId; import google.registry.flows.annotations.ReportingSpec; import google.registry.model.contact.ContactInfoData; @@ -47,6 +48,7 @@ import org.joda.time.DateTime; * visible to the registrar that owns the contact or to a registrar that already supplied it. * * @error {@link google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException} + * @error {@link google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException} */ @ReportingSpec(ActivityReportField.CONTACT_INFO) public final class ContactInfoFlow implements Flow { @@ -56,16 +58,21 @@ public final class ContactInfoFlow implements Flow { @Inject @ClientId String clientId; @Inject @TargetId String targetId; @Inject Optional authInfo; + @Inject @Superuser boolean isSuperuser; @Inject EppResponse.Builder responseBuilder; - @Inject ContactInfoFlow() {} + + @Inject + ContactInfoFlow() {} @Override public final EppResponse run() throws EppException { DateTime now = clock.nowUtc(); - extensionManager.validate(); // There are no legal extensions for this flow. + extensionManager.validate(); // There are no legal extensions for this flow. validateClientIsLoggedIn(clientId); ContactResource contact = loadAndVerifyExistence(ContactResource.class, targetId, now); - verifyOptionalAuthInfo(authInfo, contact); + if (!isSuperuser) { + verifyResourceOwnership(clientId, contact); + } boolean includeAuthInfo = clientId.equals(contact.getCurrentSponsorClientId()) || authInfo.isPresent(); ImmutableSet.Builder statusValues = new ImmutableSet.Builder<>(); @@ -74,23 +81,24 @@ public final class ContactInfoFlow implements Flow { statusValues.add(StatusValue.LINKED); } return responseBuilder - .setResData(ContactInfoData.newBuilder() - .setContactId(contact.getContactId()) - .setRepoId(contact.getRepoId()) - .setStatusValues(statusValues.build()) - .setPostalInfos(contact.getPostalInfosAsList()) - .setVoiceNumber(contact.getVoiceNumber()) - .setFaxNumber(contact.getFaxNumber()) - .setEmailAddress(contact.getEmailAddress()) - .setCurrentSponsorClientId(contact.getCurrentSponsorClientId()) - .setCreationClientId(contact.getCreationClientId()) - .setCreationTime(contact.getCreationTime()) - .setLastEppUpdateClientId(contact.getLastEppUpdateClientId()) - .setLastEppUpdateTime(contact.getLastEppUpdateTime()) - .setLastTransferTime(contact.getLastTransferTime()) - .setAuthInfo(includeAuthInfo ? contact.getAuthInfo() : null) - .setDisclose(contact.getDisclose()) - .build()) + .setResData( + ContactInfoData.newBuilder() + .setContactId(contact.getContactId()) + .setRepoId(contact.getRepoId()) + .setStatusValues(statusValues.build()) + .setPostalInfos(contact.getPostalInfosAsList()) + .setVoiceNumber(contact.getVoiceNumber()) + .setFaxNumber(contact.getFaxNumber()) + .setEmailAddress(contact.getEmailAddress()) + .setCurrentSponsorClientId(contact.getCurrentSponsorClientId()) + .setCreationClientId(contact.getCreationClientId()) + .setCreationTime(contact.getCreationTime()) + .setLastEppUpdateClientId(contact.getLastEppUpdateClientId()) + .setLastEppUpdateTime(contact.getLastEppUpdateTime()) + .setLastTransferTime(contact.getLastTransferTime()) + .setAuthInfo(includeAuthInfo ? contact.getAuthInfo() : null) + .setDisclose(contact.getDisclose()) + .build()) .build(); } } diff --git a/javatests/google/registry/flows/contact/ContactInfoFlowTest.java b/javatests/google/registry/flows/contact/ContactInfoFlowTest.java index 3e88fd139..ccd972f3f 100644 --- a/javatests/google/registry/flows/contact/ContactInfoFlowTest.java +++ b/javatests/google/registry/flows/contact/ContactInfoFlowTest.java @@ -27,6 +27,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import google.registry.flows.ResourceFlowTestCase; import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException; +import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException; import google.registry.model.contact.ContactAddress; import google.registry.model.contact.ContactAuthInfo; import google.registry.model.contact.ContactPhoneNumber; @@ -135,13 +136,26 @@ public class ContactInfoFlowTest extends ResourceFlowTestCase