This is an automated email from the ASF dual-hosted git repository. ahuber pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/isis.git
commit f801957c961d9ae443a3bc3c8ded1daa07eed71f Author: Andi Huber <ahu...@apache.org> AuthorDate: Fri Apr 24 06:09:31 2020 +0200 ISIS-2340: share logic of ObjectAdapterAccessHelper/UpdateHelper (2) --- .../binding/interaction/ActionInteractor.java | 36 +++++++ .../binding/interaction/CollectionInteractor.java | 35 +++++++ .../binding/interaction/InteractionResponse.java | 21 ++++- .../binding/interaction/MemberInteractor.java | 57 +++++++++++ .../binding/interaction/ObjectInteractor.java | 21 ++++- .../binding/interaction/PropertyInteractor.java | 35 +++++++ .../resources/DomainObjectResourceServerside.java | 12 ++- .../viewer/resources/DomainResourceHelper.java | 12 +-- .../resources/ObjectAdapterAccessHelper.java | 105 ++++++++++----------- 9 files changed, 261 insertions(+), 73 deletions(-) diff --git a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/ActionInteractor.java b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/ActionInteractor.java new file mode 100644 index 0000000..3136316 --- /dev/null +++ b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/ActionInteractor.java @@ -0,0 +1,36 @@ +package org.apache.isis.viewer.common.model.binding.interaction; + +import org.apache.isis.applib.annotation.Where; +import org.apache.isis.core.commons.internal.base._Either; +import org.apache.isis.core.metamodel.spec.feature.ObjectAction; +import org.apache.isis.viewer.common.model.binding.interaction.InteractionResponse.Veto; +import org.apache.isis.viewer.common.model.binding.interaction.ObjectInteractor.AccessIntent; + +import lombok.val; + +public class ActionInteractor extends MemberInteractor { + + public ActionInteractor(ObjectInteractor objectInteractor) { + super(objectInteractor); + } + + public _Either<ObjectAction, InteractionResponse> getActionThatIsVisibleForIntent( + final String actionId, + final Where where, + final AccessIntent intent) { + + val managedObject = objectInteractor.getManagedObject(); + + val spec = managedObject.getSpecification(); + val action = spec.getObjectAction(actionId).orElse(null); + + if(action==null) { + return _Either.right(InteractionResponse.failed(Veto.NOT_FOUND)); + } + + return super.memberThatIsVisibleForIntent( + MemberType.ACTION, + action, where, intent); + } + +} diff --git a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/CollectionInteractor.java b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/CollectionInteractor.java new file mode 100644 index 0000000..1459243 --- /dev/null +++ b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/CollectionInteractor.java @@ -0,0 +1,35 @@ +package org.apache.isis.viewer.common.model.binding.interaction; + +import org.apache.isis.applib.annotation.Where; +import org.apache.isis.core.commons.internal.base._Either; +import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation; +import org.apache.isis.viewer.common.model.binding.interaction.InteractionResponse.Veto; +import org.apache.isis.viewer.common.model.binding.interaction.ObjectInteractor.AccessIntent; + +import lombok.val; + +public class CollectionInteractor extends MemberInteractor { + + public CollectionInteractor(ObjectInteractor objectInteractor) { + super(objectInteractor); + } + + public _Either<OneToManyAssociation, InteractionResponse> getPropertyThatIsVisibleForIntent( + final String collectionId, + final Where where, + final AccessIntent intent) { + + val managedObject = objectInteractor.getManagedObject(); + + val spec = managedObject.getSpecification(); + val collection = spec.getAssociation(collectionId).orElse(null); + if(collection==null || !collection.isOneToOneAssociation()) { + return _Either.right(InteractionResponse.failed(Veto.NOT_FOUND)); + } + + return super.memberThatIsVisibleForIntent( + MemberType.COLLECTION, + (OneToManyAssociation) collection, where, intent); + } + +} diff --git a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/InteractionResponse.java b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/InteractionResponse.java index 49820b8..feee940 100644 --- a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/InteractionResponse.java +++ b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/InteractionResponse.java @@ -20,16 +20,25 @@ package org.apache.isis.viewer.common.model.binding.interaction; import lombok.AccessLevel; import lombok.Getter; +import lombok.NonNull; import lombok.RequiredArgsConstructor; @RequiredArgsConstructor(staticName = "of", access = AccessLevel.PRIVATE) public class InteractionResponse { - private final static InteractionResponse SUCCESS = of(null); + public static enum Veto { + NOT_FOUND, + HIDDEN, + FORBIDDEN, + UNAUTHORIZED, + } + + private final static InteractionResponse SUCCESS = of(null, null); + @Getter private final Veto veto; @Getter private final String failureMessage; public boolean isSuccess() { - return failureMessage==null; + return veto==null; } public boolean isFailure() { @@ -38,8 +47,12 @@ public class InteractionResponse { // -- FACTORIES - public static InteractionResponse failed(String reason) { - return of(reason); + public static InteractionResponse failed(@NonNull Veto veto) { + return of(veto, "unspecified"); + } + + public static InteractionResponse failed(@NonNull Veto veto, String reason) { + return of(veto, reason); } public static InteractionResponse success() { diff --git a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/MemberInteractor.java b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/MemberInteractor.java new file mode 100644 index 0000000..a9168d0 --- /dev/null +++ b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/MemberInteractor.java @@ -0,0 +1,57 @@ +package org.apache.isis.viewer.common.model.binding.interaction; + +import org.apache.isis.applib.annotation.Where; +import org.apache.isis.core.commons.internal.base._Either; +import org.apache.isis.core.metamodel.consent.Consent; +import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy; +import org.apache.isis.core.metamodel.spec.feature.ObjectMember; +import org.apache.isis.viewer.common.model.binding.interaction.InteractionResponse.Veto; +import org.apache.isis.viewer.common.model.binding.interaction.ObjectInteractor.AccessIntent; + +import lombok.RequiredArgsConstructor; +import lombok.val; + +@RequiredArgsConstructor +public class MemberInteractor { + + // only used to create failure messages + static enum MemberType { + PROPERTY, + COLLECTION, + ACTION + } + + protected final ObjectInteractor objectInteractor; + + public <T extends ObjectMember> + _Either<T, InteractionResponse> memberThatIsVisibleForIntent( + final MemberType memberType, + final T objectMember, + final Where where, + final AccessIntent intent) { + + val managedObject = objectInteractor.getManagedObject(); + val visibilityConsent = + objectMember.isVisible( + managedObject, InteractionInitiatedBy.USER, where); + if (visibilityConsent.isVetoed()) { + val memberId = objectMember.getId(); + return _Either.right(InteractionResponse.failed( + Veto.HIDDEN, + String.format("%s '%s' either does not exist, is disabled or is not visible", + memberId, + memberType.name().toLowerCase()))); + } + if (intent.isMutate()) { + final Consent usabilityConsent = objectMember.isUsable( + managedObject, InteractionInitiatedBy.USER, where); + if (usabilityConsent.isVetoed()) { + return _Either.right(InteractionResponse.failed( + Veto.FORBIDDEN, + usabilityConsent.getReason())); + } + } + return _Either.left(objectMember); + } + +} diff --git a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/ObjectInteractor.java b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/ObjectInteractor.java index 8693986..105a4db 100644 --- a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/ObjectInteractor.java +++ b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/ObjectInteractor.java @@ -29,7 +29,9 @@ import org.apache.isis.core.metamodel.spec.feature.ObjectAction; import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation; import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation; import org.apache.isis.viewer.common.model.binding.UiComponentFactory; +import org.apache.isis.viewer.common.model.binding.interaction.InteractionResponse.Veto; +import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.val; @@ -44,6 +46,7 @@ public class ObjectInteractor { } } + @Getter private final ManagedObject managedObject; public String getTitle() { @@ -80,7 +83,7 @@ public class ObjectInteractor { val consent = property.isAssociationValid(managedObject, proposedNewValue, InteractionInitiatedBy.USER); if (consent.isVetoed()) { - return InteractionResponse.failed(consent.getReason()); + return InteractionResponse.failed(Veto.UNAUTHORIZED, consent.getReason()); } property.set(managedObject, proposedNewValue, InteractionInitiatedBy.USER); @@ -124,6 +127,22 @@ public class ObjectInteractor { .filter(collection->Objects.equals(id, collection.getId())) .findFirst(); } + + public MemberInteractor getMemberInteractor() { + return new MemberInteractor(this); + } + + public ActionInteractor getActionInteractor() { + return new ActionInteractor(this); + } + + public PropertyInteractor getPropertyInteractor() { + return new PropertyInteractor(this); + } + + public CollectionInteractor getCollectionInteractor() { + return new CollectionInteractor(this); + } } diff --git a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/PropertyInteractor.java b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/PropertyInteractor.java new file mode 100644 index 0000000..83352d5 --- /dev/null +++ b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/PropertyInteractor.java @@ -0,0 +1,35 @@ +package org.apache.isis.viewer.common.model.binding.interaction; + +import org.apache.isis.applib.annotation.Where; +import org.apache.isis.core.commons.internal.base._Either; +import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation; +import org.apache.isis.viewer.common.model.binding.interaction.InteractionResponse.Veto; +import org.apache.isis.viewer.common.model.binding.interaction.ObjectInteractor.AccessIntent; + +import lombok.val; + +public class PropertyInteractor extends MemberInteractor { + + public PropertyInteractor(ObjectInteractor objectInteractor) { + super(objectInteractor); + } + + public _Either<OneToOneAssociation, InteractionResponse> getPropertyThatIsVisibleForIntent( + final String propertyId, + final Where where, + final AccessIntent intent) { + + val managedObject = objectInteractor.getManagedObject(); + + val spec = managedObject.getSpecification(); + val property = spec.getAssociation(propertyId).orElse(null); + if(property==null || !property.isOneToOneAssociation()) { + return _Either.right(InteractionResponse.failed(Veto.NOT_FOUND)); + } + + return super.memberThatIsVisibleForIntent( + MemberType.PROPERTY, + (OneToOneAssociation)property, where, intent); + } + +} diff --git a/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/DomainObjectResourceServerside.java b/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/DomainObjectResourceServerside.java index f767583..daf605e 100644 --- a/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/DomainObjectResourceServerside.java +++ b/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/DomainObjectResourceServerside.java @@ -451,7 +451,7 @@ public class DomainObjectResourceServerside extends ResourceAbstract implements val objectAdapter = getObjectAdapterElseThrowNotFound(domainType, instanceId); val domainResourceHelper = DomainResourceHelper.ofObjectResource(resourceContext, objectAdapter); - val accessHelper = new ObjectAdapterAccessHelper(resourceContext, objectAdapter); + val accessHelper = ObjectAdapterAccessHelper.of(resourceContext, objectAdapter); val property = accessHelper.getPropertyThatIsVisibleForIntent(propertyId, ObjectInteractor.AccessIntent.MUTATE); @@ -460,6 +460,8 @@ public class DomainObjectResourceServerside extends ResourceAbstract implements .parseAsMapWithSingleValue(Util.asStringUtf8(body)); val objectInteractor = ObjectInteractor.bind(objectAdapter); + + val iResponse = objectInteractor.modifyProperty(property, proposedNewValue); if (iResponse.isFailure()) { throw RestfulObjectsApplicationException @@ -489,7 +491,7 @@ public class DomainObjectResourceServerside extends ResourceAbstract implements val objectAdapter = getObjectAdapterElseThrowNotFound(domainType, instanceId); val domainResourceHelper = DomainResourceHelper.ofObjectResource(resourceContext, objectAdapter); - val accessHelper = new ObjectAdapterAccessHelper(resourceContext, objectAdapter); + val accessHelper = ObjectAdapterAccessHelper.of(resourceContext, objectAdapter); val property = accessHelper.getPropertyThatIsVisibleForIntent( propertyId, ObjectInteractor.AccessIntent.MUTATE); @@ -551,7 +553,7 @@ public class DomainObjectResourceServerside extends ResourceAbstract implements val objectAdapter = getObjectAdapterElseThrowNotFound(domainType, instanceId); val domainResourceHelper = DomainResourceHelper.ofObjectResource(resourceContext, objectAdapter); - final ObjectAdapterAccessHelper accessHelper = new ObjectAdapterAccessHelper(resourceContext, objectAdapter); + final ObjectAdapterAccessHelper accessHelper = ObjectAdapterAccessHelper.of(resourceContext, objectAdapter); final OneToManyAssociation collection = accessHelper.getCollectionThatIsVisibleForIntent( collectionId, ObjectInteractor.AccessIntent.MUTATE); @@ -590,7 +592,7 @@ public class DomainObjectResourceServerside extends ResourceAbstract implements val objectAdapter = getObjectAdapterElseThrowNotFound(domainType, instanceId); val domainResourceHelper = DomainResourceHelper.ofObjectResource(resourceContext, objectAdapter); - final ObjectAdapterAccessHelper accessHelper = new ObjectAdapterAccessHelper(resourceContext, objectAdapter); + final ObjectAdapterAccessHelper accessHelper = ObjectAdapterAccessHelper.of(resourceContext, objectAdapter); final OneToManyAssociation collection = accessHelper.getCollectionThatIsVisibleForIntent( collectionId, ObjectInteractor.AccessIntent.MUTATE); @@ -629,7 +631,7 @@ public class DomainObjectResourceServerside extends ResourceAbstract implements val objectAdapter = getObjectAdapterElseThrowNotFound(domainType, instanceId); val domainResourceHelper = DomainResourceHelper.ofObjectResource(resourceContext, objectAdapter); - final ObjectAdapterAccessHelper accessHelper = new ObjectAdapterAccessHelper(resourceContext, objectAdapter); + final ObjectAdapterAccessHelper accessHelper = ObjectAdapterAccessHelper.of(resourceContext, objectAdapter); final OneToManyAssociation collection = accessHelper.getCollectionThatIsVisibleForIntent( collectionId, ObjectInteractor.AccessIntent.MUTATE); diff --git a/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/DomainResourceHelper.java b/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/DomainResourceHelper.java index b82338d..279e5ab 100644 --- a/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/DomainResourceHelper.java +++ b/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/DomainResourceHelper.java @@ -107,7 +107,7 @@ class DomainResourceHelper { final String propertyId, final MemberReprMode memberMode) { - ObjectAdapterAccessHelper accessHelper = new ObjectAdapterAccessHelper(resourceContext, objectAdapter); + ObjectAdapterAccessHelper accessHelper = ObjectAdapterAccessHelper.of(resourceContext, objectAdapter); final OneToOneAssociation property = accessHelper.getPropertyThatIsVisibleForIntent(propertyId, ObjectInteractor.AccessIntent.ACCESS); @@ -125,7 +125,7 @@ class DomainResourceHelper { final String collectionId, final MemberReprMode memberMode) { - ObjectAdapterAccessHelper accessHelper = new ObjectAdapterAccessHelper(resourceContext, objectAdapter); + ObjectAdapterAccessHelper accessHelper = ObjectAdapterAccessHelper.of(resourceContext, objectAdapter); final OneToManyAssociation collection = accessHelper.getCollectionThatIsVisibleForIntent(collectionId, ObjectInteractor.AccessIntent.ACCESS); @@ -141,7 +141,7 @@ class DomainResourceHelper { */ public Response actionPrompt(final String actionId) { - ObjectAdapterAccessHelper accessHelper = new ObjectAdapterAccessHelper(resourceContext, objectAdapter); + ObjectAdapterAccessHelper accessHelper = ObjectAdapterAccessHelper.of(resourceContext, objectAdapter); final ObjectAction action = accessHelper.getObjectActionThatIsVisibleForIntent(actionId, ObjectInteractor.AccessIntent.ACCESS); @@ -161,7 +161,7 @@ class DomainResourceHelper { */ public Response invokeActionQueryOnly(final String actionId, final JsonRepresentation arguments) { - final ObjectAdapterAccessHelper accessHelper = new ObjectAdapterAccessHelper(resourceContext, objectAdapter); + final ObjectAdapterAccessHelper accessHelper = ObjectAdapterAccessHelper.of(resourceContext, objectAdapter); final ObjectAction action = accessHelper.getObjectActionThatIsVisibleForIntent(actionId, ObjectInteractor.AccessIntent.MUTATE); @@ -185,7 +185,7 @@ class DomainResourceHelper { */ public Response invokeActionIdempotent(final String actionId, final JsonRepresentation arguments) { - final ObjectAdapterAccessHelper accessHelper = new ObjectAdapterAccessHelper(resourceContext, objectAdapter); + final ObjectAdapterAccessHelper accessHelper = ObjectAdapterAccessHelper.of(resourceContext, objectAdapter); final ObjectAction action = accessHelper.getObjectActionThatIsVisibleForIntent(actionId, ObjectInteractor.AccessIntent.MUTATE); @@ -203,7 +203,7 @@ class DomainResourceHelper { */ public Response invokeAction(final String actionId, final JsonRepresentation arguments) { - ObjectAdapterAccessHelper accessHelper = new ObjectAdapterAccessHelper(resourceContext, objectAdapter); + ObjectAdapterAccessHelper accessHelper = ObjectAdapterAccessHelper.of(resourceContext, objectAdapter); final ObjectAction action = accessHelper.getObjectActionThatIsVisibleForIntent(actionId, ObjectInteractor.AccessIntent.MUTATE); diff --git a/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/ObjectAdapterAccessHelper.java b/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/ObjectAdapterAccessHelper.java index b8b8b2f..2785cee 100644 --- a/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/ObjectAdapterAccessHelper.java +++ b/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/ObjectAdapterAccessHelper.java @@ -19,28 +19,30 @@ package org.apache.isis.viewer.restfulobjects.viewer.resources; import org.apache.isis.applib.annotation.Where; -import org.apache.isis.core.metamodel.consent.Consent; -import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy; import org.apache.isis.core.metamodel.spec.ManagedObject; import org.apache.isis.core.metamodel.spec.feature.ObjectAction; -import org.apache.isis.core.metamodel.spec.feature.ObjectMember; import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation; import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation; +import org.apache.isis.viewer.common.model.binding.interaction.InteractionResponse; +import org.apache.isis.viewer.common.model.binding.interaction.ObjectInteractor; import org.apache.isis.viewer.common.model.binding.interaction.ObjectInteractor.AccessIntent; import org.apache.isis.viewer.restfulobjects.applib.RestfulResponse; import org.apache.isis.viewer.restfulobjects.rendering.IResourceContext; import org.apache.isis.viewer.restfulobjects.rendering.RestfulObjectsApplicationException; import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.MemberType; +import lombok.RequiredArgsConstructor; import lombok.val; /** * Utility class that encapsulates the logic for checking access to the specified * {@link ManagedObject}'s members. */ +@RequiredArgsConstructor public class ObjectAdapterAccessHelper { - public static RestfulObjectsApplicationException notFoundException(final String memberId, final MemberType memberType) { + public static RestfulObjectsApplicationException notFoundException( + final String memberId, final MemberType memberType) { final String memberTypeStr = memberType.name().toLowerCase(); return RestfulObjectsApplicationException.createWithMessage( RestfulResponse.HttpStatusCode.NOT_FOUND, @@ -48,78 +50,67 @@ public class ObjectAdapterAccessHelper { memberTypeStr, memberId); } - - private final ManagedObject objectAdapter; - private final IResourceContext resourceContext; - - public ObjectAdapterAccessHelper(IResourceContext resourceContext, ManagedObject objectAdapter) { - this.objectAdapter = objectAdapter; - this.resourceContext = resourceContext; + + public static ObjectAdapterAccessHelper of( + final IResourceContext resourceContext, + final ManagedObject managedObject) { + return new ObjectAdapterAccessHelper( + ObjectInteractor.bind(managedObject), + resourceContext.getWhere()); } + private final ObjectInteractor objectInteractor; + private final Where where; + public OneToOneAssociation getPropertyThatIsVisibleForIntent( final String propertyId, final AccessIntent intent) { + + val propertyInteractor = objectInteractor.getPropertyInteractor(); + + val check = propertyInteractor.getPropertyThatIsVisibleForIntent(propertyId, where, intent); + check.right() + .ifPresent(failure->handleFailure(failure, propertyId, MemberType.PROPERTY)); - val spec = objectAdapter.getSpecification(); - val association = spec.getAssociation(propertyId) - .orElseThrow(()->notFoundException(propertyId, MemberType.PROPERTY)); - - if (!association.isOneToOneAssociation()) { - throw notFoundException(propertyId, MemberType.PROPERTY); - } - - final OneToOneAssociation property = (OneToOneAssociation) association; - return memberThatIsVisibleForIntent(property, MemberType.PROPERTY, intent); + return check.leftIfAny(); } public OneToManyAssociation getCollectionThatIsVisibleForIntent( final String collectionId, final AccessIntent intent) { - - val spec = objectAdapter.getSpecification(); - val association = spec.getAssociation(collectionId) - .orElseThrow(()->notFoundException(collectionId, MemberType.COLLECTION)); - if (!association.isOneToManyAssociation()) { - throw notFoundException(collectionId, MemberType.COLLECTION); - } + val propertyInteractor = objectInteractor.getCollectionInteractor(); - final OneToManyAssociation collection = (OneToManyAssociation) association; - return memberThatIsVisibleForIntent(collection, MemberType.COLLECTION, intent); + val check = propertyInteractor.getPropertyThatIsVisibleForIntent(collectionId, where, intent); + check.right() + .ifPresent(failure->handleFailure(failure, collectionId, MemberType.COLLECTION)); + + return check.leftIfAny(); } public ObjectAction getObjectActionThatIsVisibleForIntent( final String actionId, final AccessIntent intent) { - val spec = objectAdapter.getSpecification(); - val action = spec.getObjectAction(actionId) - .orElseThrow(()->notFoundException(actionId, MemberType.ACTION)); + val actionInteractor = objectInteractor.getActionInteractor(); + + val check = actionInteractor.getActionThatIsVisibleForIntent(actionId, where, intent); + check.right() + .ifPresent(failure->handleFailure(failure, actionId, MemberType.ACTION)); - return memberThatIsVisibleForIntent(action, MemberType.ACTION, intent); + return check.leftIfAny(); } - public <T extends ObjectMember> T memberThatIsVisibleForIntent( - final T objectMember, final MemberType memberType, final AccessIntent intent) { - - final Where where = resourceContext.getWhere(); - - final String memberId = objectMember.getId(); - final Consent visibilityConsent = - objectMember.isVisible( - objectAdapter, InteractionInitiatedBy.USER, where); - if (visibilityConsent.isVetoed()) { - throw notFoundException(memberId, memberType); - } - if (intent.isMutate()) { - final Consent usabilityConsent = objectMember.isUsable( - objectAdapter, InteractionInitiatedBy.USER, where - ); - if (usabilityConsent.isVetoed()) { - throw RestfulObjectsApplicationException.createWithMessage(RestfulResponse.HttpStatusCode.FORBIDDEN, - usabilityConsent.getReason()); - } + private void handleFailure(final InteractionResponse failure, String memberId, MemberType memberType) { + switch(failure.getVeto()) { + case NOT_FOUND: + case HIDDEN: + throw RestfulObjectsApplicationException + .createWithMessage(RestfulResponse.HttpStatusCode.NOT_FOUND, + failure.getFailureMessage()); + case UNAUTHORIZED: + case FORBIDDEN: + throw RestfulObjectsApplicationException + .createWithMessage(RestfulResponse.HttpStatusCode.FORBIDDEN, + failure.getFailureMessage()); } - return objectMember; } - - + }