From 072d32f2e0cb608b37bea83c79553abd89f8663f Mon Sep 17 00:00:00 2001 From: brinn <brinn> Date: Thu, 10 Feb 2011 20:11:19 +0000 Subject: [PATCH] fix: dependency violations refactor: authorization checking in DSS to better separate responsibilities SVN: 19888 --- .../generic/server/AbstractDssServiceRpc.java | 24 +---- .../dss/generic/server/DataStoreServer.java | 4 +- .../server/DatasetSessionAuthorizer.java | 93 +++++++++++++++++++ .../DssServiceRpcAuthorizationAdvisor.java | 66 +++++++++++-- .../server/api/v1/DssServiceRpcGeneric.java | 2 +- .../api/v1/DssServiceRpcGenericLogger.java | 15 +-- .../{ => internal}/AuthorizationGuard.java | 4 +- .../{ => internal}/DataSetAccessGuard.java | 9 +- .../DataSetCodeStringPredicate.java | 24 +++-- .../DataSetFileDTOPredicate.java | 28 ++++-- .../DssSessionAuthorizationHolder.java | 77 +++++++++++++++ .../IAuthorizationGuardPredicate.java | 4 +- .../IDssServiceRpcGenericInternal.java | 9 +- .../internal/IDssSessionAuthorizer.java | 64 +++++++++++++ .../{ => internal}/NewDataSetPredicate.java | 27 ++++-- .../shared/api/v1/IDssServiceRpcGeneric.java | 10 +- .../source/java/dssApplicationContext.xml | 2 +- .../client/api/v1/impl/DssComponentTest.java | 56 ++++++++--- .../generic/server/DssServiceRpcV1Test.java | 9 +- .../api/v1/DssServiceRpcGenericTest.java | 8 ++ screening/build/build.xml | 8 +- screening/resource/dependency-structure.ddf | 4 +- .../server/DssServiceRpcScreening.java | 1 - .../internal}/DatasetIdentifierPredicate.java | 25 ++--- .../SingleDataSetIdentifierPredicate.java | 25 +++-- .../api/v1/IDssServiceRpcScreening.java | 8 +- .../server/logic/ScreeningApiImpl.java | 2 +- .../ExperimentIdentifierPredicate.java | 4 +- .../PlateIdentifierPredicate.java | 4 +- ...ateWellReferenceWithDatasetsValidator.java | 4 +- .../ScreeningExperimentValidator.java | 4 +- .../ScreeningPlateListReadOnlyPredicate.java | 4 +- .../ScreeningPlateValidator.java | 4 +- .../WellIdentifierPredicate.java | 4 +- .../shared/api/v1/IScreeningApiServer.java | 14 +-- .../server/DssServiceRpcScreeningTest.java | 61 +++++++++--- 36 files changed, 550 insertions(+), 161 deletions(-) create mode 100644 datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DatasetSessionAuthorizer.java rename datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/{ => internal}/AuthorizationGuard.java (92%) rename datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/{ => internal}/DataSetAccessGuard.java (83%) rename datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/{ => internal}/DataSetCodeStringPredicate.java (61%) rename datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/{ => internal}/DataSetFileDTOPredicate.java (55%) create mode 100644 datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/internal/DssSessionAuthorizationHolder.java rename datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/{ => internal}/IAuthorizationGuardPredicate.java (94%) rename datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/{ => internal}/IDssServiceRpcGenericInternal.java (85%) create mode 100644 datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/internal/IDssSessionAuthorizer.java rename datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/{ => internal}/NewDataSetPredicate.java (75%) rename screening/source/java/ch/systemsx/cisd/openbis/dss/screening/shared/api/{v1 => authorization/internal}/DatasetIdentifierPredicate.java (75%) rename screening/source/java/ch/systemsx/cisd/openbis/dss/screening/shared/api/{v1 => authorization/internal}/SingleDataSetIdentifierPredicate.java (55%) rename screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/{ => internal}/ExperimentIdentifierPredicate.java (96%) rename screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/{ => internal}/PlateIdentifierPredicate.java (97%) rename screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/{ => internal}/PlateWellReferenceWithDatasetsValidator.java (95%) rename screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/{ => internal}/ScreeningExperimentValidator.java (93%) rename screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/{ => internal}/ScreeningPlateListReadOnlyPredicate.java (97%) rename screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/{ => internal}/ScreeningPlateValidator.java (94%) rename screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/{ => internal}/WellIdentifierPredicate.java (93%) diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/AbstractDssServiceRpc.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/AbstractDssServiceRpc.java index aa43628d42e..d3f2e494707 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/AbstractDssServiceRpc.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/AbstractDssServiceRpc.java @@ -37,7 +37,6 @@ import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService; import ch.systemsx.cisd.openbis.dss.generic.shared.utils.DatasetLocationUtil; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseInstance; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData; -import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SpaceIdentifier; /** * Abstract superclass of DssServiceRpc implementations. @@ -127,7 +126,7 @@ public abstract class AbstractDssServiceRpc<T> extends AbstractServiceWithLogger * Check with openBIS if the user with the given sessionToken is allowed to access the data set * specified by the dataSetCode. */ - public boolean isDatasetAccessible(String sessionToken, String dataSetCode) + protected boolean isDatasetAccessible(String sessionToken, String dataSetCode) { boolean access; if (operationLog.isInfoEnabled()) @@ -148,27 +147,6 @@ public abstract class AbstractDssServiceRpc<T> extends AbstractServiceWithLogger return access; } - public boolean isSpaceWriteable(String sessionToken, SpaceIdentifier spaceId) - { - boolean access; - if (operationLog.isInfoEnabled()) - { - operationLog.info(String.format("Check access to the space '%s' on openBIS server.", - spaceId)); - } - - try - { - openBISService.checkSpaceAccess(sessionToken, spaceId); - access = true; - } catch (UserFailureException ex) - { - access = false; - } - - return access; - } - protected File getRootDirectory(String datasetCode) { List<ExternalData> list = getOpenBISService().listDataSetsByCode(Arrays.asList(datasetCode)); diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreServer.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreServer.java index d5bd514bf4f..d31d5ba2492 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreServer.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreServer.java @@ -62,7 +62,8 @@ import ch.systemsx.cisd.openbis.dss.generic.server.ConfigParameters.PluginServle import ch.systemsx.cisd.openbis.dss.generic.server.api.v1.DssServiceRpcGeneric; import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService; import ch.systemsx.cisd.openbis.dss.generic.shared.ServiceProvider; -import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.IDssServiceRpcGenericInternal; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal.DssSessionAuthorizationHolder; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal.IDssServiceRpcGenericInternal; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.DataStoreApiUrlUtilities; import ch.systemsx.cisd.openbis.dss.generic.shared.utils.DssPropertyParametersUtil; import ch.systemsx.cisd.openbis.generic.shared.IServer; @@ -85,6 +86,7 @@ public class DataStoreServer public void init() throws ServletException { target = ServiceProvider.getDataStoreServer(); + DssSessionAuthorizationHolder.setAuthorizer(new DatasetSessionAuthorizer()); } // Code copied from org.springframework.web.context.support.HttpRequestHandlerServlet diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DatasetSessionAuthorizer.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DatasetSessionAuthorizer.java new file mode 100644 index 00000000000..1bd830546f6 --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DatasetSessionAuthorizer.java @@ -0,0 +1,93 @@ +/* + * Copyright 2011 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.openbis.dss.generic.server; + +import java.util.List; + +import ch.systemsx.cisd.common.exceptions.Status; +import ch.systemsx.cisd.common.exceptions.UserFailureException; +import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService; +import ch.systemsx.cisd.openbis.dss.generic.shared.ServiceProvider; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal.IDssSessionAuthorizer; +import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SpaceIdentifier; + +/** + * Implementation of {@link IDssSessionAuthorizer} that asks the openBIS application server to + * check the data set codes. + * + * @author Bernd Rinn + */ +public class DatasetSessionAuthorizer implements IDssSessionAuthorizer +{ + + public Status checkDatasetAccess(String sessionToken, List<String> datasetCodes) + { + final IEncapsulatedOpenBISService openBISService = ServiceProvider.getOpenBISService(); + + try + { + openBISService.checkDataSetCollectionAccess(sessionToken, datasetCodes); + return Status.OK; + } catch (UserFailureException ex) + { + return Status.createError(ex.getMessage()); + } + } + + public Status checkDatasetAccess(String sessionToken, String datasetCode) + { + final IEncapsulatedOpenBISService openBISService = ServiceProvider.getOpenBISService(); + + try + { + openBISService.checkDataSetAccess(sessionToken, datasetCode); + return Status.OK; + } catch (UserFailureException ex) + { + return Status.createError(ex.getMessage()); + } + } + + public Status checkSpaceWriteable(String sessionToken, SpaceIdentifier spaceId) + { + final IEncapsulatedOpenBISService openBISService = ServiceProvider.getOpenBISService(); + + try + { + openBISService.checkSpaceAccess(sessionToken, spaceId); + return Status.OK; + } catch (UserFailureException ex) + { + return Status.createError(ex.getMessage()); + } + } + + public Status checkInstanceAdminAuthorization(String sessionToken) + { + final IEncapsulatedOpenBISService openBISService = ServiceProvider.getOpenBISService(); + + try + { + openBISService.checkInstanceAdminAuthorization(sessionToken); + return Status.OK; + } catch (UserFailureException ex) + { + return Status.createError(ex.getMessage()); + } + } + +} diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DssServiceRpcAuthorizationAdvisor.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DssServiceRpcAuthorizationAdvisor.java index dc99cbe01e1..46ee9bf5aa3 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DssServiceRpcAuthorizationAdvisor.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DssServiceRpcAuthorizationAdvisor.java @@ -16,6 +16,7 @@ package ch.systemsx.cisd.openbis.dss.generic.server; +import java.lang.reflect.Method; import java.util.List; import org.aopalliance.intercept.MethodInterceptor; @@ -24,6 +25,7 @@ import org.apache.log4j.Logger; import org.springframework.aop.support.DefaultPointcutAdvisor; import org.springframework.aop.support.annotation.AnnotationMatchingPointcut; +import ch.systemsx.cisd.common.exceptions.AuthorizationFailureException; import ch.systemsx.cisd.common.exceptions.Status; import ch.systemsx.cisd.common.logging.LogCategory; import ch.systemsx.cisd.common.logging.LogFactory; @@ -31,9 +33,11 @@ import ch.systemsx.cisd.common.utilities.AnnotationUtils; import ch.systemsx.cisd.common.utilities.AnnotationUtils.Parameter; import ch.systemsx.cisd.common.utilities.ClassUtils; import ch.systemsx.cisd.common.utilities.MethodUtils; -import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.AuthorizationGuard; -import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.DataSetAccessGuard; -import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.IAuthorizationGuardPredicate; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal.AuthorizationGuard; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal.DataSetAccessGuard; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal.DssSessionAuthorizationHolder; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal.IAuthorizationGuardPredicate; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal.IDssSessionAuthorizer; /** * The advisor for authorization in the DSS RPC interfaces. @@ -47,9 +51,9 @@ import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.IAuthorizat * code (second argument)</li> * </ul> * <p> - * It does this check by invoking the method - * {@link AbstractDssServiceRpc#isDatasetAccessible(String, String)} on the receiver of the method - * containing the join point. + * It does this check by invoking method on {@link IDssSessionAuthorizer} which it gets from + * {@link DssSessionAuthorizationHolder}. The correct authorizer is expected to have been set in + * the holder at programm startup. * <p> * Though it is not necessary to subclass DefaultPointcutAdvisor for the implementation, we subclass * here because to make the configuration in spring a bit simpler. @@ -60,6 +64,9 @@ public class DssServiceRpcAuthorizationAdvisor extends DefaultPointcutAdvisor { private static final long serialVersionUID = 1L; + private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION, + DssServiceRpcAuthorizationAdvisor.class); + private static final Logger authorizationLog = LogFactory.getLogger(LogCategory.AUTH, DssServiceRpcAuthorizationAdvisor.class); @@ -99,10 +106,18 @@ public class DssServiceRpcAuthorizationAdvisor extends DefaultPointcutAdvisor List<Parameter<AuthorizationGuard>> annotatedParameters = AnnotationUtils.getAnnotatedParameters(methodInvocation.getMethod(), AuthorizationGuard.class); + final boolean requiresInstanceAdmin = + checkRequiresInstanceAdmin(methodInvocation.getMethod(), sessionToken); // At least one of the parameters must be annotated - assert annotatedParameters.size() > 0 : "No guard defined"; + assert requiresInstanceAdmin || annotatedParameters.size() > 0 : "No guard defined"; + + if (requiresInstanceAdmin) + { + // An instance admin is allowed to work on all data sets. + return methodInvocation.proceed(); + } - Object recv = methodInvocation.getThis(); + final Object recv = methodInvocation.getThis(); for (Parameter<AuthorizationGuard> param : annotatedParameters) { @@ -120,13 +135,46 @@ public class DssServiceRpcAuthorizationAdvisor extends DefaultPointcutAdvisor errorMessage = status.tryGetErrorMessage(); } - throw new IllegalArgumentException(errorMessage); + throw new AuthorizationFailureException(errorMessage); } } return methodInvocation.proceed(); } + private boolean checkRequiresInstanceAdmin(final Method method, final String sessionToken) + { + final DataSetAccessGuard guard = method.getAnnotation(DataSetAccessGuard.class); + final boolean requiresInstanceAdmin = + (guard != null) ? guard.requiresInstanceAdmin() : false; + if (operationLog.isInfoEnabled()) + { + operationLog.info("Check instance admin privileges."); + } + + if (requiresInstanceAdmin) + { + final Status status = + DssSessionAuthorizationHolder.getAuthorizer() + .checkInstanceAdminAuthorization(sessionToken); + if (status != Status.OK) + { + authorizationLog.info(String.format( + "[SESSION:'%s']: Authorization failure while " + + "invoking method '%s', user is not an instance admin.", + sessionToken, MethodUtils.describeMethod(method))); + String errorMessage = "You are not an instance administrator."; + if (null != status.tryGetErrorMessage()) + { + errorMessage = status.tryGetErrorMessage(); + } + + throw new AuthorizationFailureException(errorMessage); + } + } + return requiresInstanceAdmin; + } + /** * Because the predicate is being invoked in a context in which its types are not known, * there is no way to do this in a statically type-safe way. diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/api/v1/DssServiceRpcGeneric.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/api/v1/DssServiceRpcGeneric.java index 6dcfbfd5ae7..1dcdc77e995 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/api/v1/DssServiceRpcGeneric.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/api/v1/DssServiceRpcGeneric.java @@ -27,7 +27,7 @@ import ch.systemsx.cisd.common.spring.IInvocationLoggerContext; import ch.systemsx.cisd.etlserver.api.v1.PutDataSetService; import ch.systemsx.cisd.openbis.dss.generic.server.AbstractDssServiceRpc; import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService; -import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.IDssServiceRpcGenericInternal; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal.IDssServiceRpcGenericInternal; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.DataSetFileDTO; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.FileInfoDssBuilder; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.FileInfoDssDTO; diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/api/v1/DssServiceRpcGenericLogger.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/api/v1/DssServiceRpcGenericLogger.java index 976b6623237..b5ec58f00c4 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/api/v1/DssServiceRpcGenericLogger.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/api/v1/DssServiceRpcGenericLogger.java @@ -21,12 +21,11 @@ import java.io.InputStream; import ch.systemsx.cisd.base.exceptions.IOExceptionUnchecked; import ch.systemsx.cisd.common.spring.IInvocationLoggerContext; -import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.IDssServiceRpcGenericInternal; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal.IDssServiceRpcGenericInternal; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.DataSetFileDTO; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.FileInfoDssDTO; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.NewDataSetDTO; import ch.systemsx.cisd.openbis.generic.shared.AbstractServerLogger; -import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SpaceIdentifier; /** * @@ -96,18 +95,6 @@ public class DssServiceRpcGenericLogger extends AbstractServerLogger implements return null; } - public boolean isDatasetAccessible(String sessionToken, String dataSetCode) - { - // server already logs - return false; - } - - public boolean isSpaceWriteable(String sessionToken, SpaceIdentifier spaceId) - { - // server already logs - return false; - } - public void setStoreDirectory(File aFile) { } diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/AuthorizationGuard.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/internal/AuthorizationGuard.java similarity index 92% rename from datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/AuthorizationGuard.java rename to datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/internal/AuthorizationGuard.java index 89d1759696c..7462d2c4b8f 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/AuthorizationGuard.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/internal/AuthorizationGuard.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization; +package ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; @@ -24,6 +24,8 @@ import java.lang.annotation.Target; /** * Parameter annotation to specify which authorization class should be used to check user access. + * <p> + * <i>This is an internal class. Do not use it as a user of the API.</i> * * @author Chandrasekhar Ramakrishnan */ diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/DataSetAccessGuard.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/internal/DataSetAccessGuard.java similarity index 83% rename from datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/DataSetAccessGuard.java rename to datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/internal/DataSetAccessGuard.java index adcbb47f83b..0f7394695da 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/DataSetAccessGuard.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/internal/DataSetAccessGuard.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization; +package ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; @@ -25,6 +25,8 @@ import java.lang.annotation.Target; /** * Annotation for service methods to automagically check that the user invoking the method has * access to the data set. + * <p> + * <i>This is an internal class. Do not use it as a user of the API.</i> * * @author Chandrasekhar Ramakrishnan */ @@ -33,5 +35,8 @@ import java.lang.annotation.Target; @Inherited public @interface DataSetAccessGuard { - + /** + * If calling this method requires instance admin privileges. + */ + boolean requiresInstanceAdmin() default false; } diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/DataSetCodeStringPredicate.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/internal/DataSetCodeStringPredicate.java similarity index 61% rename from datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/DataSetCodeStringPredicate.java rename to datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/internal/DataSetCodeStringPredicate.java index 3906b6c795e..492e0ba9235 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/DataSetCodeStringPredicate.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/internal/DataSetCodeStringPredicate.java @@ -14,29 +14,39 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization; +package ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal; + +import org.apache.log4j.Logger; import ch.systemsx.cisd.common.exceptions.Status; import ch.systemsx.cisd.common.exceptions.UserFailureException; +import ch.systemsx.cisd.common.logging.LogCategory; +import ch.systemsx.cisd.common.logging.LogFactory; /** * Predicate for checking that the current user has access to a data set specified by code. + * <p> + * <i>This is an internal class. Do not use it as a user of the API.</i> * * @author Chandrasekhar Ramakrishnan */ public class DataSetCodeStringPredicate implements IAuthorizationGuardPredicate<IDssServiceRpcGenericInternal, String> { + static protected final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION, + DataSetCodeStringPredicate.class); + public Status evaluate(IDssServiceRpcGenericInternal receiver, String sessionToken, - String dataSetCode) throws UserFailureException + String datasetCode) throws UserFailureException { - if (receiver.isDatasetAccessible(sessionToken, dataSetCode)) + if (operationLog.isInfoEnabled()) { - return Status.OK; - } else - { - return Status.createError("Data set (" + dataSetCode + ") does not exist."); + operationLog.info(String.format("Check access to the data set '%s' on openBIS server.", + datasetCode)); } + + return DssSessionAuthorizationHolder.getAuthorizer().checkDatasetAccess(sessionToken, + datasetCode); } } diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/DataSetFileDTOPredicate.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/internal/DataSetFileDTOPredicate.java similarity index 55% rename from datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/DataSetFileDTOPredicate.java rename to datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/internal/DataSetFileDTOPredicate.java index 3317fc860f5..b83118343ab 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/DataSetFileDTOPredicate.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/internal/DataSetFileDTOPredicate.java @@ -14,32 +14,42 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization; +package ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal; + +import org.apache.log4j.Logger; import ch.systemsx.cisd.common.exceptions.Status; import ch.systemsx.cisd.common.exceptions.UserFailureException; +import ch.systemsx.cisd.common.logging.LogCategory; +import ch.systemsx.cisd.common.logging.LogFactory; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.DataSetFileDTO; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.IDssServiceRpcGeneric; /** * Predicate for checking that the current user has access to a data set specified by a * DataSetFileDTO + * <p> + * <i>This is an internal class. Do not use it as a user of the API.</i> * * @author Chandrasekhar Ramakrishnan */ public class DataSetFileDTOPredicate implements - IAuthorizationGuardPredicate<IDssServiceRpcGenericInternal, DataSetFileDTO> + IAuthorizationGuardPredicate<IDssServiceRpcGeneric, DataSetFileDTO> { - public Status evaluate(IDssServiceRpcGenericInternal receiver, String sessionToken, + static protected final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION, + DataSetFileDTOPredicate.class); + + public Status evaluate(IDssServiceRpcGeneric receiver, String sessionToken, DataSetFileDTO dataSetFile) throws UserFailureException { - if (receiver.isDatasetAccessible(sessionToken, dataSetFile.getDataSetCode())) + if (operationLog.isInfoEnabled()) { - return Status.OK; - } else - { - return Status.createError("Data set (" + dataSetFile.getDataSetCode() - + ") does not exist."); + operationLog.info(String.format( + "Check access to the data set file '%s' on openBIS server.", dataSetFile)); } + + return DssSessionAuthorizationHolder.getAuthorizer().checkDatasetAccess(sessionToken, + dataSetFile.getDataSetCode()); } } diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/internal/DssSessionAuthorizationHolder.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/internal/DssSessionAuthorizationHolder.java new file mode 100644 index 00000000000..794c9186ee0 --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/internal/DssSessionAuthorizationHolder.java @@ -0,0 +1,77 @@ +/* + * Copyright 2011 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal; + +import java.util.List; + +import ch.systemsx.cisd.common.exceptions.Status; +import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SpaceIdentifier; + +/** + * Holder object for {@link IDssSessionAuthorizer}. + * <p> + * <i>This is an internal class. Do not use it as a user of the API.</i> + * + * @author Bernd Rinn + */ +public class DssSessionAuthorizationHolder +{ + + private static IDssSessionAuthorizer authorizer = new IDssSessionAuthorizer() + { + public Status checkDatasetAccess(String sessionToken, + List<String> datasetCodes) + { + return Status.createError("Data set authorizer not set."); + } + + public Status checkDatasetAccess(String sessionToken, String datasetCode) + { + return Status.createError("Data set authorizer not set."); + } + + public Status checkSpaceWriteable(String sessionToken, SpaceIdentifier spaceId) + { + return Status.createError("Data set authorizer not set."); + } + + public Status checkInstanceAdminAuthorization(String sessionToken) + { + return Status.createError("Data set authorizer not set."); + } + }; + + /** + * Returns the authorizer that can be used to check whether a session is authorized to access a + * data set code. + */ + public static IDssSessionAuthorizer getAuthorizer() + { + return authorizer; + } + + /** + * Sets the authorizer. + * <p> + * <i>Only set this method once at program startup.</i> + */ + public static void setAuthorizer(IDssSessionAuthorizer authorizer) + { + DssSessionAuthorizationHolder.authorizer = authorizer; + } + +} diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/IAuthorizationGuardPredicate.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/internal/IAuthorizationGuardPredicate.java similarity index 94% rename from datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/IAuthorizationGuardPredicate.java rename to datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/internal/IAuthorizationGuardPredicate.java index b31739a7812..b31c748265d 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/IAuthorizationGuardPredicate.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/internal/IAuthorizationGuardPredicate.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization; +package ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal; import ch.systemsx.cisd.common.exceptions.Status; import ch.systemsx.cisd.common.exceptions.UserFailureException; @@ -24,6 +24,8 @@ import ch.systemsx.cisd.common.exceptions.UserFailureException; * <p> * Predicates should return Status.OK if the user is authorized for the action; they should return a * status with an appropriate error message if the user is not authorized. + * <p> + * <i>This is an internal class. Do not use it as a user of the API.</i> * * @author Chandrasekhar Ramakrishnan */ diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/IDssServiceRpcGenericInternal.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/internal/IDssServiceRpcGenericInternal.java similarity index 85% rename from datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/IDssServiceRpcGenericInternal.java rename to datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/internal/IDssServiceRpcGenericInternal.java index c84a710d73e..9756e1c581c 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/IDssServiceRpcGenericInternal.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/internal/IDssServiceRpcGenericInternal.java @@ -14,13 +14,12 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization; +package ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal; import java.io.File; import ch.systemsx.cisd.openbis.dss.generic.server.DataStoreServer; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.IDssServiceRpcGeneric; -import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SpaceIdentifier; /** * The IDssServiceRpcGeneric interface extended with methods that are internal to the DSS server. @@ -28,6 +27,8 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SpaceIdentifier; * This interface is necessary because the implementation of IDssServiceRpcGeneric that is visible * to the {@link DataStoreServer} is a proxy. The methods here are used internally, but need to be * known to the proxy as well. (See the dssApplicationContext.xml file as well.) + * <p> + * <i>This is an internal class. Do not use it as a user of the API.</i> * * @author Chandrasekhar Ramakrishnan */ @@ -36,8 +37,4 @@ public interface IDssServiceRpcGenericInternal extends IDssServiceRpcGeneric public void setStoreDirectory(File aFile); public void setIncomingDirectory(File aFile); - - public boolean isDatasetAccessible(String sessionToken, String dataSetCode); - - public boolean isSpaceWriteable(String sessionToken, SpaceIdentifier spaceId); } diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/internal/IDssSessionAuthorizer.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/internal/IDssSessionAuthorizer.java new file mode 100644 index 00000000000..4caaf333259 --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/internal/IDssSessionAuthorizer.java @@ -0,0 +1,64 @@ +/* + * Copyright 2011 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal; + +import java.util.List; + +import ch.systemsx.cisd.common.exceptions.Status; +import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SpaceIdentifier; + +/** + * Role that allows to authorize calls in DSS for a given session. + * <p> + * <i>This is an internal class. Do not use it as a user of the API.</i> + * + * @author Bernd Rinn + */ +public interface IDssSessionAuthorizer +{ + /** + * Checks whether the session identified by <var>sessionToken</var> is authorized to access the + * given <var>datasetCode</var>. + * + * @return {@link Status#OK} if the access is granted, an error status otherwise. + */ + public Status checkDatasetAccess(String sessionToken, String datasetCode); + + /** + * Checks whether the session identified by <var>sessionToken</var> is authorized to access the + * given <var>datasetCodes</var>. + * + * @return {@link Status#OK} if the access is granted, an error status otherwise. + */ + public Status checkDatasetAccess(String sessionToken, List<String> datasetCodes); + + /** + * Checks whether the session identified by <var>sessionToken</var> is authorized to write to + * the given <var>spaceId</var>. + * + * @return {@link Status#OK} if the access is granted, an error status otherwise. + */ + public Status checkSpaceWriteable(String sessionToken, SpaceIdentifier spaceId); + + /** + * Checks whether the session identified by <var>sessionToken</var> has openBIS instance admin + * privileges. + * + * @return {@link Status#OK} if the access is granted, an error status otherwise. + */ + public Status checkInstanceAdminAuthorization(String sessionToken); +} diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/NewDataSetPredicate.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/internal/NewDataSetPredicate.java similarity index 75% rename from datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/NewDataSetPredicate.java rename to datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/internal/NewDataSetPredicate.java index 158f9f53c1b..f5567625d73 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/NewDataSetPredicate.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/internal/NewDataSetPredicate.java @@ -14,10 +14,15 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization; +package ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal; + +import org.apache.log4j.Logger; import ch.systemsx.cisd.common.exceptions.Status; import ch.systemsx.cisd.common.exceptions.UserFailureException; +import ch.systemsx.cisd.common.logging.LogCategory; +import ch.systemsx.cisd.common.logging.LogFactory; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.IDssServiceRpcGeneric; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.NewDataSetDTO; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.NewDataSetDTO.DataSetOwner; import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier; @@ -29,23 +34,29 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SpaceIdentifier; /** * Predicate for checking that the new data set can be registered (i.e., user has access to the * space for the new data set). + * <p> + * <i>This is an internal class. Do not use it as a user of the API.</i> * * @author Chandrasekhar Ramakrishnan */ public class NewDataSetPredicate implements - IAuthorizationGuardPredicate<IDssServiceRpcGenericInternal, NewDataSetDTO> + IAuthorizationGuardPredicate<IDssServiceRpcGeneric, NewDataSetDTO> { - public Status evaluate(IDssServiceRpcGenericInternal receiver, String sessionToken, + static protected final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION, + NewDataSetPredicate.class); + + public Status evaluate(IDssServiceRpcGeneric receiver, String sessionToken, NewDataSetDTO newDataSet) throws UserFailureException { SpaceIdentifier spaceId = getSpaceIdentifier(newDataSet); - if (receiver.isSpaceWriteable(sessionToken, spaceId)) + if (operationLog.isInfoEnabled()) { - return Status.OK; - } else - { - return Status.createError("Space (" + spaceId + ") is not writeable."); + operationLog.info(String.format("Check write access to space '%s' on openBIS server.", + spaceId)); } + + return DssSessionAuthorizationHolder.getAuthorizer().checkSpaceWriteable(sessionToken, + spaceId); } private SpaceIdentifier getSpaceIdentifier(NewDataSetDTO newDataSet) diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/v1/IDssServiceRpcGeneric.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/v1/IDssServiceRpcGeneric.java index 7976c9bf308..a462653c788 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/v1/IDssServiceRpcGeneric.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/v1/IDssServiceRpcGeneric.java @@ -20,11 +20,11 @@ import java.io.InputStream; import ch.systemsx.cisd.base.exceptions.IOExceptionUnchecked; import ch.systemsx.cisd.common.api.IRpcService; -import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.AuthorizationGuard; -import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.DataSetAccessGuard; -import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.DataSetCodeStringPredicate; -import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.DataSetFileDTOPredicate; -import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.NewDataSetPredicate; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal.AuthorizationGuard; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal.DataSetAccessGuard; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal.DataSetCodeStringPredicate; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal.DataSetFileDTOPredicate; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal.NewDataSetPredicate; /** * Generic functionality for interacting with the DSS. diff --git a/datastore_server/source/java/dssApplicationContext.xml b/datastore_server/source/java/dssApplicationContext.xml index 3f1e65f2a68..29ade5ec5b3 100644 --- a/datastore_server/source/java/dssApplicationContext.xml +++ b/datastore_server/source/java/dssApplicationContext.xml @@ -79,7 +79,7 @@ <bean class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces"> <list> - <value>ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.IDssServiceRpcGenericInternal</value> + <value>ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal.IDssServiceRpcGenericInternal</value> </list> </property> <property name="interceptorNames"> diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/client/api/v1/impl/DssComponentTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/client/api/v1/impl/DssComponentTest.java index 402125ec804..5e132b557af 100644 --- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/client/api/v1/impl/DssComponentTest.java +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/client/api/v1/impl/DssComponentTest.java @@ -32,6 +32,7 @@ import org.springframework.aop.TargetSource; import org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.beans.factory.support.StaticListableBeanFactory; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -42,14 +43,19 @@ import ch.systemsx.cisd.common.api.IRpcService; import ch.systemsx.cisd.common.api.IRpcServiceFactory; import ch.systemsx.cisd.common.api.RpcServiceInterfaceDTO; import ch.systemsx.cisd.common.api.RpcServiceInterfaceVersionDTO; +import ch.systemsx.cisd.common.exceptions.AuthorizationFailureException; import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException; +import ch.systemsx.cisd.common.exceptions.UserFailureException; import ch.systemsx.cisd.common.spring.IInvocationLoggerContext; import ch.systemsx.cisd.openbis.dss.client.api.v1.IDataSetDss; import ch.systemsx.cisd.openbis.dss.generic.server.AbstractDssServiceRpc; +import ch.systemsx.cisd.openbis.dss.generic.server.DatasetSessionAuthorizer; import ch.systemsx.cisd.openbis.dss.generic.server.DssServiceRpcAuthorizationAdvisor; import ch.systemsx.cisd.openbis.dss.generic.server.api.v1.DssServiceRpcGeneric; import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService; -import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.IDssServiceRpcGenericInternal; +import ch.systemsx.cisd.openbis.dss.generic.shared.ServiceProvider; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal.DssSessionAuthorizationHolder; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal.IDssServiceRpcGenericInternal; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.DataSetFileDTO; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.DataStoreApiUrlUtilities; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.FileInfoDssBuilder; @@ -73,13 +79,15 @@ public class DssComponentTest extends AbstractFileSystemTestCase private IGeneralInformationService openBisService; + private IEncapsulatedOpenBISService etlService; + private IRpcServiceFactory dssServiceFactory; private DssComponent dssComponent; private File randomDataFile; - private static final String DUMMY_SESSSION_TOKEN = "DummySessionToken"; + private static final String DUMMY_SESSION_TOKEN = "DummySessionToken"; private static final String DUMMY_DSS_DOWNLOAD_URL = "http://localhost/" + GenericSharedConstants.DATA_STORE_SERVER_WEB_APPLICATION_NAME; @@ -127,11 +135,16 @@ public class DssComponentTest extends AbstractFileSystemTestCase public void setUp() throws IOException { super.setUp(); + DssSessionAuthorizationHolder.setAuthorizer(new DatasetSessionAuthorizer()); + final StaticListableBeanFactory applicationContext = new StaticListableBeanFactory(); + ServiceProvider.setBeanFactory(applicationContext); context = new Mockery(); openBisService = context.mock(IGeneralInformationService.class); dssServiceFactory = context.mock(IRpcServiceFactory.class); dssComponent = new DssComponent(openBisService, dssServiceFactory, null); randomDataFile = getFileWithRandomData(1); + etlService = context.mock(IEncapsulatedOpenBISService.class); + applicationContext.addBean("openBIS-service", etlService); } @AfterMethod @@ -177,7 +190,7 @@ public class DssComponentTest extends AbstractFileSystemTestCase public void testListDataSetFilesNoLogin() throws IOException { dssComponent = - new DssComponent(openBisService, dssServiceFactory, DUMMY_SESSSION_TOKEN); + new DssComponent(openBisService, dssServiceFactory, DUMMY_SESSION_TOKEN); setupExpectationsNoLogin(); IDataSetDss dataSetProxy = dssComponent.getDataSet(DUMMY_DATA_SET_CODE); FileInfoDssDTO[] fileInfos = dataSetProxy.listFiles("/", true); @@ -196,9 +209,9 @@ public class DssComponentTest extends AbstractFileSystemTestCase IDataSetDss dataSetProxy = dssComponent.getDataSet(DUMMY_DATA_SET_CODE); dataSetProxy.listFiles("/", true); fail("Unauthorized access to data set should have thrown an exception."); - } catch (IllegalArgumentException ex) + } catch (AuthorizationFailureException ex) { - assertEquals("Data set (" + DUMMY_DATA_SET_CODE + ") does not exist.", ex.getMessage()); + assertEquals("Authorization failure: Not allowed.", ex.getMessage()); } context.assertIsSatisfied(); @@ -237,7 +250,7 @@ public class DssComponentTest extends AbstractFileSystemTestCase @Test public void testLinkToContentsEarlierVersion() throws IOException { - setupExpectations(true, true); + setupExpectations(null, true); dssComponent.login("foo", "bar"); IDataSetDss dataSetProxy = dssComponent.getDataSet(DUMMY_DATA_SET_CODE); @@ -256,7 +269,7 @@ public class DssComponentTest extends AbstractFileSystemTestCase @Test public void testUnsupportedInterface() throws IOException { - setupExpectations("Some Server Interface", true, true, false); + setupExpectations("Some Server Interface", true, null, false); dssComponent.login("foo", "bar"); try @@ -309,12 +322,12 @@ public class DssComponentTest extends AbstractFileSystemTestCase setupExpectations(true); } - private void setupExpectations(boolean isDataSetAccessible) throws IOException + private void setupExpectations(Boolean isDataSetAccessible) throws IOException { setupExpectations(IDssServiceRpcGeneric.DSS_SERVICE_NAME, true, isDataSetAccessible, false); } - private void setupExpectations(boolean isDataSetAccessible, boolean returnEarlierVersion) + private void setupExpectations(Boolean isDataSetAccessible, boolean returnEarlierVersion) throws IOException { setupExpectations(IDssServiceRpcGeneric.DSS_SERVICE_NAME, true, isDataSetAccessible, @@ -327,7 +340,7 @@ public class DssComponentTest extends AbstractFileSystemTestCase } private void setupExpectations(String serviceName, final boolean needsLogin, - boolean isDataSetAccessible, boolean returnEarlierVersion) throws IOException + final Boolean isDataSetAccessible, boolean returnEarlierVersion) throws IOException { final SessionContextDTO session = getDummySession(); @@ -358,13 +371,28 @@ public class DssComponentTest extends AbstractFileSystemTestCase ifaces.add(iface); + if (isDataSetAccessible != null) + { + context.checking(new Expectations() + { + { + atLeast(1).of(etlService).checkDataSetAccess(DUMMY_SESSION_TOKEN, + DUMMY_DATA_SET_CODE); + if (isDataSetAccessible == false) + { + will(throwException(new UserFailureException("Not allowed."))); + } + } + }); + } + dssServiceV1_0 = getAdvisedDssService(new MockDssServiceRpcV1_0(null, fileInfos, - new FileInputStream(randomDataFile), isDataSetAccessible)); + new FileInputStream(randomDataFile), isDataSetAccessible == null ? true : isDataSetAccessible)); dssServiceV1_1 = getAdvisedDssService(new MockDssServiceRpcV1_1(null, fileInfos, - new FileInputStream(randomDataFile), isDataSetAccessible)); + new FileInputStream(randomDataFile), isDataSetAccessible == null ? true : isDataSetAccessible)); context.checking(new Expectations() { @@ -396,7 +424,7 @@ public class DssComponentTest extends AbstractFileSystemTestCase private SessionContextDTO getDummySession() { final SessionContextDTO session = new SessionContextDTO(); - session.setSessionToken(DUMMY_SESSSION_TOKEN); + session.setSessionToken(DUMMY_SESSION_TOKEN); return session; } @@ -502,7 +530,7 @@ public class DssComponentTest extends AbstractFileSystemTestCase } @Override - public boolean isDatasetAccessible(String sessionToken, String dataSetCode) + protected boolean isDatasetAccessible(String sessionToken, String dataSetCode) { return isDataSetAccessible; } diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/DssServiceRpcV1Test.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/DssServiceRpcV1Test.java index cda5e6076e1..f5de25a1b88 100644 --- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/DssServiceRpcV1Test.java +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/DssServiceRpcV1Test.java @@ -33,6 +33,7 @@ import org.aopalliance.intercept.MethodInvocation; import org.jmock.Expectations; import org.jmock.Mockery; import org.springframework.aop.framework.ProxyFactory; +import org.springframework.beans.factory.support.StaticListableBeanFactory; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -58,7 +59,9 @@ import ch.systemsx.cisd.etlserver.validation.IDataSetValidator; import ch.systemsx.cisd.openbis.dss.generic.server.DssServiceRpcAuthorizationAdvisor.DssServiceRpcAuthorizationMethodInterceptor; import ch.systemsx.cisd.openbis.dss.generic.server.api.v1.DssServiceRpcGeneric; import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService; -import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.IDssServiceRpcGenericInternal; +import ch.systemsx.cisd.openbis.dss.generic.shared.ServiceProvider; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal.DssSessionAuthorizationHolder; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal.IDssServiceRpcGenericInternal; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.DataSetFileDTO; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.FileInfoDssBuilder; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.FileInfoDssDTO; @@ -129,8 +132,12 @@ public class DssServiceRpcV1Test extends AbstractFileSystemTestCase public void setUp() throws IOException { super.setUp(); + DssSessionAuthorizationHolder.setAuthorizer(new DatasetSessionAuthorizer()); + final StaticListableBeanFactory applicationContext = new StaticListableBeanFactory(); + ServiceProvider.setBeanFactory(applicationContext); context = new Mockery(); openBisService = context.mock(IEncapsulatedOpenBISService.class); + applicationContext.addBean("openBIS-service", openBisService); mailClient = context.mock(IMailClient.class); codeExtractor = new DefaultDataSetInfoExtractor(new Properties()); diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/api/v1/DssServiceRpcGenericTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/api/v1/DssServiceRpcGenericTest.java index e8f33bec83f..bf011541c11 100644 --- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/api/v1/DssServiceRpcGenericTest.java +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/api/v1/DssServiceRpcGenericTest.java @@ -22,13 +22,17 @@ import java.util.Arrays; import org.jmock.Expectations; import org.jmock.Mockery; import org.springframework.aop.framework.ProxyFactoryBean; +import org.springframework.beans.factory.support.StaticListableBeanFactory; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import ch.systemsx.cisd.base.tests.AbstractFileSystemTestCase; +import ch.systemsx.cisd.openbis.dss.generic.server.DatasetSessionAuthorizer; import ch.systemsx.cisd.openbis.dss.generic.server.DssServiceRpcAuthorizationAdvisor; import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService; +import ch.systemsx.cisd.openbis.dss.generic.shared.ServiceProvider; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal.DssSessionAuthorizationHolder; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.FileInfoDssDTO; import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.IDssServiceRpcGeneric; import ch.systemsx.cisd.openbis.dss.generic.shared.utils.DatasetLocationUtil; @@ -55,8 +59,12 @@ public class DssServiceRpcGenericTest extends AbstractFileSystemTestCase @BeforeMethod public void beforeMethod() { + DssSessionAuthorizationHolder.setAuthorizer(new DatasetSessionAuthorizer()); + final StaticListableBeanFactory applicationContext = new StaticListableBeanFactory(); + ServiceProvider.setBeanFactory(applicationContext); context = new Mockery(); service = context.mock(IEncapsulatedOpenBISService.class); + applicationContext.addBean("openBIS-service", service); ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean(); proxyFactoryBean.setInterfaces(new Class[] {IDssServiceRpcGeneric.class}); DssServiceRpcGeneric nakedDssService = new DssServiceRpcGeneric(service); diff --git a/screening/build/build.xml b/screening/build/build.xml index 1fadeca8598..fa92902673d 100644 --- a/screening/build/build.xml +++ b/screening/build/build.xml @@ -347,12 +347,12 @@ <include name="ch/systemsx/cisd/openbis/dss/client/api/v1/**/*.class" /> <include name="ch/systemsx/cisd/openbis/dss/generic/shared/api/v1/**/*.class" /> <include name="ch/systemsx/cisd/openbis/dss/generic/shared/api/authorization/**/*.class" /> - <include name="ch/systemsx/cisd/openbis/dss/screening/shared/api/v1/**/*.class" /> + <include name="ch/systemsx/cisd/openbis/dss/screening/shared/api/**/*.class" /> <include name="ch/systemsx/cisd/openbis/generic/shared/basic/**/*.class" /> - <include name="ch/systemsx/cisd/openbis/generic/shared/api/v1/**/*.class" /> + <include name="ch/systemsx/cisd/openbis/generic/shared/api/**/*.class" /> <include name="ch/systemsx/cisd/openbis/generic/shared/authorization/annotation/**/*.class" /> - <include name="ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/**/*.class" /> - <include name="ch/systemsx/cisd/openbis/plugin/screening/client/api/v1/**/*.class" /> + <include name="ch/systemsx/cisd/openbis/plugin/screening/shared/api/**/*.class" /> + <include name="ch/systemsx/cisd/openbis/plugin/screening/client/api/**/*.class" /> <include name="ch/systemsx/cisd/openbis/plugin/screening/client/cli/**/*.class" /> <include name="${build.info.filename}" /> </fileset> diff --git a/screening/resource/dependency-structure.ddf b/screening/resource/dependency-structure.ddf index e274815fcf6..1d5366d2a5f 100644 --- a/screening/resource/dependency-structure.ddf +++ b/screening/resource/dependency-structure.ddf @@ -7,10 +7,10 @@ [screening_openbis] = ${screening}.* -[dss_authorization] = ${root}.dss.generic.shared.api.authorization.* +[dss_authorization] = ${root}.dss.generic.shared.api.authorization.internal.* ${root}.dss.screening.shared.api.authorization.internal.* [dss_api] = ${root}.dss.screening.shared.api.v1.** ${root}.dss.client.api.v1.** ${root}.dss.generic.shared.api.v1.** [dss] = ${root}.dss.* ch.systemsx.cisd.etlserver.* excluding [dss_api] [dss_authorization] -check sets [screening_openbis] [dss] +check sets [screening_openbis] [dss] [dss_api] [dss_authorization] check [screening_openbis] independentOf [dss] diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreening.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreening.java index 80a853c2622..6494c911cb0 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreening.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreening.java @@ -642,7 +642,6 @@ public class DssServiceRpcScreening extends AbstractDssServiceRpc<IDssServiceRpc List<IDatasetIdentifier> dataSetIdentifiers, String channel, IImageTransformerFactory transformerFactory) { - getOpenBISService().checkInstanceAdminAuthorization(sessionToken); for (IDatasetIdentifier datasetIdentifier : dataSetIdentifiers) { ImgDatasetDTO dataset = getImagingDataset(datasetIdentifier); diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/shared/api/v1/DatasetIdentifierPredicate.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/shared/api/authorization/internal/DatasetIdentifierPredicate.java similarity index 75% rename from screening/source/java/ch/systemsx/cisd/openbis/dss/screening/shared/api/v1/DatasetIdentifierPredicate.java rename to screening/source/java/ch/systemsx/cisd/openbis/dss/screening/shared/api/authorization/internal/DatasetIdentifierPredicate.java index f739a2afb35..958e1d19af2 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/shared/api/v1/DatasetIdentifierPredicate.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/shared/api/authorization/internal/DatasetIdentifierPredicate.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.dss.screening.shared.api.v1; +package ch.systemsx.cisd.openbis.dss.screening.shared.api.authorization.internal; import java.util.ArrayList; import java.util.List; @@ -25,18 +25,19 @@ import ch.systemsx.cisd.common.exceptions.Status; import ch.systemsx.cisd.common.exceptions.UserFailureException; import ch.systemsx.cisd.common.logging.LogCategory; import ch.systemsx.cisd.common.logging.LogFactory; -import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService; -import ch.systemsx.cisd.openbis.dss.generic.shared.ServiceProvider; -import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.IAuthorizationGuardPredicate; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal.DssSessionAuthorizationHolder; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal.IAuthorizationGuardPredicate; +import ch.systemsx.cisd.openbis.dss.screening.shared.api.v1.IDssServiceRpcScreening; import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IDatasetIdentifier; /** * Predicate that checks if the user has access to a collection of data set identifiers. + * <p> + * <i>This is an internal class. Do not use it as a user of the API.</i> * * @author Chandrasekhar Ramakrishnan */ -public class DatasetIdentifierPredicate - implements +public class DatasetIdentifierPredicate implements IAuthorizationGuardPredicate<IDssServiceRpcScreening, List<? extends IDatasetIdentifier>> { @@ -46,22 +47,14 @@ public class DatasetIdentifierPredicate public Status evaluate(IDssServiceRpcScreening receiver, String sessionToken, List<? extends IDatasetIdentifier> datasetIdentifiers) throws UserFailureException { - final IEncapsulatedOpenBISService openBISService = ServiceProvider.getOpenBISService(); if (operationLog.isInfoEnabled()) { operationLog.info(String.format( "Check access to the data sets '%s' on openBIS server.", datasetIdentifiers)); } - try - { - openBISService.checkDataSetCollectionAccess(sessionToken, - getDatasetCodes(datasetIdentifiers)); - return Status.OK; - } catch (UserFailureException ex) - { - return Status.createError(ex.getMessage()); - } + return DssSessionAuthorizationHolder.getAuthorizer().checkDatasetAccess( + sessionToken, getDatasetCodes(datasetIdentifiers)); } private List<String> getDatasetCodes(List<? extends IDatasetIdentifier> datasetIdentifiers) diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/shared/api/v1/SingleDataSetIdentifierPredicate.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/shared/api/authorization/internal/SingleDataSetIdentifierPredicate.java similarity index 55% rename from screening/source/java/ch/systemsx/cisd/openbis/dss/screening/shared/api/v1/SingleDataSetIdentifierPredicate.java rename to screening/source/java/ch/systemsx/cisd/openbis/dss/screening/shared/api/authorization/internal/SingleDataSetIdentifierPredicate.java index 44fc0f5633c..24f9116aaae 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/shared/api/v1/SingleDataSetIdentifierPredicate.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/shared/api/authorization/internal/SingleDataSetIdentifierPredicate.java @@ -14,17 +14,23 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.dss.screening.shared.api.v1; +package ch.systemsx.cisd.openbis.dss.screening.shared.api.authorization.internal; -import java.util.Collections; +import org.apache.log4j.Logger; import ch.systemsx.cisd.common.exceptions.Status; import ch.systemsx.cisd.common.exceptions.UserFailureException; -import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.IAuthorizationGuardPredicate; +import ch.systemsx.cisd.common.logging.LogCategory; +import ch.systemsx.cisd.common.logging.LogFactory; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal.DssSessionAuthorizationHolder; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal.IAuthorizationGuardPredicate; +import ch.systemsx.cisd.openbis.dss.screening.shared.api.v1.IDssServiceRpcScreening; import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IDatasetIdentifier; /** * A predicate for testing a single data set identifier. + * <p> + * <i>This is an internal class. Do not use it as a user of the API.</i> * * @author Franz-Josef Elmer */ @@ -32,13 +38,20 @@ public class SingleDataSetIdentifierPredicate implements IAuthorizationGuardPredicate<IDssServiceRpcScreening, IDatasetIdentifier> { - private static final DatasetIdentifierPredicate PREDICATE = new DatasetIdentifierPredicate(); + static protected final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION, + DatasetIdentifierPredicate.class); public Status evaluate(IDssServiceRpcScreening receiver, String sessionToken, IDatasetIdentifier datasetIdentifier) throws UserFailureException { - return PREDICATE.evaluate(receiver, sessionToken, - Collections.singletonList(datasetIdentifier)); + if (operationLog.isInfoEnabled()) + { + operationLog.info(String.format( + "Check access to the data set '%s' on openBIS server.", datasetIdentifier)); + } + + return DssSessionAuthorizationHolder.getAuthorizer().checkDatasetAccess( + sessionToken, datasetIdentifier.getDatasetCode()); } } diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/shared/api/v1/IDssServiceRpcScreening.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/shared/api/v1/IDssServiceRpcScreening.java index 0b7a2f9d1e0..1ce2f1ed6ed 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/shared/api/v1/IDssServiceRpcScreening.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/screening/shared/api/v1/IDssServiceRpcScreening.java @@ -22,8 +22,10 @@ import java.util.List; import ch.systemsx.cisd.base.image.IImageTransformerFactory; import ch.systemsx.cisd.common.api.IRpcService; import ch.systemsx.cisd.common.api.MinimalMinorVersion; -import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.AuthorizationGuard; -import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.DataSetAccessGuard; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal.AuthorizationGuard; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal.DataSetAccessGuard; +import ch.systemsx.cisd.openbis.dss.screening.shared.api.authorization.internal.DatasetIdentifierPredicate; +import ch.systemsx.cisd.openbis.dss.screening.shared.api.authorization.internal.SingleDataSetIdentifierPredicate; import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.FeatureVectorDataset; import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.FeatureVectorDatasetReference; import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.FeatureVectorDatasetWellReference; @@ -307,7 +309,7 @@ public interface IDssServiceRpcScreening extends IRpcService * @since 1.4 */ @MinimalMinorVersion(4) - @DataSetAccessGuard + @DataSetAccessGuard(requiresInstanceAdmin = true) public void saveImageTransformerFactory( String sessionToken, @AuthorizationGuard(guardClass = DatasetIdentifierPredicate.class) List<IDatasetIdentifier> dataSetIdentifiers, diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/ScreeningApiImpl.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/ScreeningApiImpl.java index 229c378fa3a..9f68eaad7c8 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/ScreeningApiImpl.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/ScreeningApiImpl.java @@ -67,7 +67,7 @@ import ch.systemsx.cisd.openbis.generic.shared.util.SpaceCodeHelper; import ch.systemsx.cisd.openbis.plugin.screening.server.IScreeningBusinessObjectFactory; import ch.systemsx.cisd.openbis.plugin.screening.server.dataaccess.IScreeningQuery; import ch.systemsx.cisd.openbis.plugin.screening.server.dataaccess.PlateGeometryContainer; -import ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization.ScreeningExperimentValidator; +import ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization.internal.ScreeningExperimentValidator; import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.DatasetIdentifier; import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ExperimentIdentifier; import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.FeatureVectorDatasetReference; diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/ExperimentIdentifierPredicate.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/internal/ExperimentIdentifierPredicate.java similarity index 96% rename from screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/ExperimentIdentifierPredicate.java rename to screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/internal/ExperimentIdentifierPredicate.java index f775a7c38e2..69bf323f771 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/ExperimentIdentifierPredicate.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/internal/ExperimentIdentifierPredicate.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization; +package ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization.internal; import java.util.List; @@ -29,6 +29,8 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ExperimentIde /** * A predicate for {@link ExperimentIdentifier}. + * <p> + * <i>This is an internal class. Do not use it as a user of the API.</i> * * @author Bernd Rinn */ diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/PlateIdentifierPredicate.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/internal/PlateIdentifierPredicate.java similarity index 97% rename from screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/PlateIdentifierPredicate.java rename to screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/internal/PlateIdentifierPredicate.java index 51c86ff8a62..c6354b780fd 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/PlateIdentifierPredicate.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/internal/PlateIdentifierPredicate.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization; +package ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization.internal; import java.util.List; @@ -31,6 +31,8 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.PlateIdentifi /** * A predicate for {@link PlateIdentifier}. + * <p> + * <i>This is an internal class. Do not use it as a user of the API.</i> * * @author Piotr Buczek */ diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/PlateWellReferenceWithDatasetsValidator.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/internal/PlateWellReferenceWithDatasetsValidator.java similarity index 95% rename from screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/PlateWellReferenceWithDatasetsValidator.java rename to screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/internal/PlateWellReferenceWithDatasetsValidator.java index b60c5980375..c2e02b88762 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/PlateWellReferenceWithDatasetsValidator.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/internal/PlateWellReferenceWithDatasetsValidator.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization; +package ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization.internal; import java.util.Set; @@ -26,6 +26,8 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.PlateWellRefe /** * A validator for a list of {@link PlateWellReferenceWithDatasets} objects. + * <p> + * <i>This is an internal class. Do not use it as a user of the API.</i> * * @author Bernd Rinn */ diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/ScreeningExperimentValidator.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/internal/ScreeningExperimentValidator.java similarity index 93% rename from screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/ScreeningExperimentValidator.java rename to screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/internal/ScreeningExperimentValidator.java index f7e2a6a6bdd..30ef9dd8dfe 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/ScreeningExperimentValidator.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/internal/ScreeningExperimentValidator.java @@ -1,4 +1,4 @@ -package ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization; +package ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization.internal; import java.util.Set; @@ -11,6 +11,8 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ExperimentIde /** * Filters the experiments for spaces to which the user has permissions. This code works only in the * case of one database instance. + * <p> + * <i>This is an internal class. Do not use it as a user of the API.</i> * * @author Bernd Rinn */ diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/ScreeningPlateListReadOnlyPredicate.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/internal/ScreeningPlateListReadOnlyPredicate.java similarity index 97% rename from screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/ScreeningPlateListReadOnlyPredicate.java rename to screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/internal/ScreeningPlateListReadOnlyPredicate.java index dc0fc3689bb..43f25cecc1f 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/ScreeningPlateListReadOnlyPredicate.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/internal/ScreeningPlateListReadOnlyPredicate.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization; +package ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization.internal; import java.util.List; @@ -32,6 +32,8 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.PlateIdentifi * A predicate for lists of entities which have {@link PlateIdentifier} as their super-class. This * predicate authorizes for read-only access, i.e. it will allow access to shared samples for all * users. + * <p> + * <i>This is an internal class. Do not use it as a user of the API.</i> * * @author Bernd Rinn */ diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/ScreeningPlateValidator.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/internal/ScreeningPlateValidator.java similarity index 94% rename from screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/ScreeningPlateValidator.java rename to screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/internal/ScreeningPlateValidator.java index f02d401405c..20203908cee 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/ScreeningPlateValidator.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/internal/ScreeningPlateValidator.java @@ -1,4 +1,4 @@ -package ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization; +package ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization.internal; import java.util.Set; @@ -11,6 +11,8 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.Plate; /** * Filters only samples from the spaces to which the user has rights. This code works only in the * case of one database instance. + * <p> + * <i>This is an internal class. Do not use it as a user of the API.</i> * * @author Tomasz Pylak */ diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/WellIdentifierPredicate.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/internal/WellIdentifierPredicate.java similarity index 93% rename from screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/WellIdentifierPredicate.java rename to screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/internal/WellIdentifierPredicate.java index 2394b5f5367..c4f50970607 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/WellIdentifierPredicate.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/authorization/internal/WellIdentifierPredicate.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization; +package ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization.internal; import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.DelegatedPredicate; import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.SamplePermIdPredicate; @@ -23,6 +23,8 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.WellIdentifie /** * A predicate for {@link WellIdentifier}. + * <p> + * <i>This is an internal class. Do not use it as a user of the API.</i> * * @author Piotr Buczek */ diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/IScreeningApiServer.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/IScreeningApiServer.java index f0ea5622ab9..fb6809309b3 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/IScreeningApiServer.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/api/v1/IScreeningApiServer.java @@ -28,13 +28,13 @@ import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.ReturnVa import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.RolesAllowed; import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.DataSetCodeCollectionPredicate; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy; -import ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization.ExperimentIdentifierPredicate; -import ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization.PlateIdentifierPredicate; -import ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization.PlateWellReferenceWithDatasetsValidator; -import ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization.ScreeningExperimentValidator; -import ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization.ScreeningPlateListReadOnlyPredicate; -import ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization.ScreeningPlateValidator; -import ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization.WellIdentifierPredicate; +import ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization.internal.ExperimentIdentifierPredicate; +import ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization.internal.PlateIdentifierPredicate; +import ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization.internal.PlateWellReferenceWithDatasetsValidator; +import ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization.internal.ScreeningExperimentValidator; +import ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization.internal.ScreeningPlateListReadOnlyPredicate; +import ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization.internal.ScreeningPlateValidator; +import ch.systemsx.cisd.openbis.plugin.screening.shared.api.authorization.internal.WellIdentifierPredicate; import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ExperimentIdentifier; import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.FeatureVectorDatasetReference; import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IDatasetIdentifier; diff --git a/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreeningTest.java b/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreeningTest.java index d69c21fbed2..b03bdd187bf 100644 --- a/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreeningTest.java +++ b/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreeningTest.java @@ -42,12 +42,15 @@ import ch.systemsx.cisd.base.image.IImageTransformer; import ch.systemsx.cisd.base.image.IImageTransformerFactory; import ch.systemsx.cisd.base.mdarray.MDFloatArray; import ch.systemsx.cisd.bds.hcs.Location; +import ch.systemsx.cisd.common.exceptions.AuthorizationFailureException; +import ch.systemsx.cisd.common.exceptions.UserFailureException; import ch.systemsx.cisd.common.io.ByteArrayBasedContent; import ch.systemsx.cisd.common.io.ConcatenatedFileOutputStreamWriter; import ch.systemsx.cisd.common.io.FileBasedContent; import ch.systemsx.cisd.common.io.IContent; import ch.systemsx.cisd.openbis.dss.etl.AbsoluteImageReference; import ch.systemsx.cisd.openbis.dss.etl.IImagingDatasetLoader; +import ch.systemsx.cisd.openbis.dss.generic.server.DatasetSessionAuthorizer; import ch.systemsx.cisd.openbis.dss.generic.server.DssServiceRpcAuthorizationAdvisor; import ch.systemsx.cisd.openbis.dss.generic.server.DssServiceRpcAuthorizationAdvisor.DssServiceRpcAuthorizationMethodInterceptor; import ch.systemsx.cisd.openbis.dss.generic.server.images.ImageChannelsUtilsTest; @@ -55,6 +58,7 @@ import ch.systemsx.cisd.openbis.dss.generic.server.images.dto.ImageChannelStackR import ch.systemsx.cisd.openbis.dss.generic.server.images.dto.RequestedImageSize; import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService; import ch.systemsx.cisd.openbis.dss.generic.shared.ServiceProvider; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.authorization.internal.DssSessionAuthorizationHolder; import ch.systemsx.cisd.openbis.dss.generic.shared.dto.Size; import ch.systemsx.cisd.openbis.dss.generic.shared.utils.ImageUtil; import ch.systemsx.cisd.openbis.dss.screening.shared.api.v1.IDssServiceRpcScreening; @@ -125,8 +129,6 @@ public class DssServiceRpcScreeningTest extends AssertJUnit private IImagingReadonlyQueryDAO dao; - private StaticListableBeanFactory applicationContext; - private IFeatureVectorDatasetIdentifier featureVectorDatasetIdentifier1; private IFeatureVectorDatasetIdentifier featureVectorDatasetIdentifier2; @@ -144,7 +146,8 @@ public class DssServiceRpcScreeningTest extends AssertJUnit @BeforeMethod public void beforeMethod() { - applicationContext = new StaticListableBeanFactory(); + DssSessionAuthorizationHolder.setAuthorizer(new DatasetSessionAuthorizer()); + final StaticListableBeanFactory applicationContext = new StaticListableBeanFactory(); ServiceProvider.setBeanFactory(applicationContext); context = new Mockery(); service = context.mock(IEncapsulatedOpenBISService.class); @@ -215,7 +218,7 @@ public class DssServiceRpcScreeningTest extends AssertJUnit final List<WellPosition> wellPositions = Arrays.asList(new WellPosition(1, 3)); final String channel = "dapi"; prepareGetHomeDatabaseInstance(); - prepareAssetDataSetsAreAccessible(ds.getPermId()); + prepareAssetDataSetIsAccessible(ds.getPermId()); prepareListDataSetsByCode(); List<PlateImageReference> plateImageReferences = @@ -299,7 +302,7 @@ public class DssServiceRpcScreeningTest extends AssertJUnit { final String channel = CHANNEL_CODE; prepareGetHomeDatabaseInstance(); - prepareAssetDataSetsAreAccessible(DATASET_CODE); + prepareAssetDataSetIsAccessible(DATASET_CODE); prepareListDataSetsByCode(); context.checking(new Expectations() { @@ -405,13 +408,40 @@ public class DssServiceRpcScreeningTest extends AssertJUnit context.assertIsSatisfied(); } + @Test + public void testSaveImageTransformerFactoryForDatasetChannelFailedDueToInvalidAuthorization() + { + final DatasetIdentifier ds1 = new DatasetIdentifier(DATASET_CODE, "url1"); + final DatasetIdentifier ds2 = new DatasetIdentifier("ds2", "url1"); + final String channel = "dapi"; + context.checking(new Expectations() + { + { + one(service).checkInstanceAdminAuthorization(SESSION_TOKEN); + will(throwException(new UserFailureException("You are not an admin."))); + } + }); + + try + { + screeningService.saveImageTransformerFactory(SESSION_TOKEN, + Arrays.<IDatasetIdentifier> asList(ds1, ds2), channel, transformerFactory); + fail("Unauthorized access not detected."); + } catch (AuthorizationFailureException ex) + { + assertEquals("Authorization failure: You are not an admin.", ex.getMessage()); + } + + assertTrue(testMethodInterceptor.methodInvoked); + context.assertIsSatisfied(); + } + @Test public void testSaveImageTransformerFactoryForDatasetChannel() { final DatasetIdentifier ds1 = new DatasetIdentifier(DATASET_CODE, "url1"); final DatasetIdentifier ds2 = new DatasetIdentifier("ds2", "url1"); final String channel = "dapi"; - prepareAssetDataSetsAreAccessible(); context.checking(new Expectations() { { @@ -455,7 +485,6 @@ public class DssServiceRpcScreeningTest extends AssertJUnit public void testSaveImageTransformerFactoryForExperiment() { final DatasetIdentifier ds1 = new DatasetIdentifier(DATASET_CODE, "url1"); - prepareAssetDataSetsAreAccessible(DATASET_CODE); context.checking(new Expectations() { { @@ -608,18 +637,28 @@ public class DssServiceRpcScreeningTest extends AssertJUnit }); } + private void prepareAssetDataSetIsAccessible(final String dsCode) + { + context.checking(new Expectations() + { + { + one(service).checkDataSetAccess(SESSION_TOKEN, dsCode); + } + }); + } + private void prepareAssetDataSetsAreAccessible() { prepareAssetDataSetsAreAccessible("ds1", "ds2"); } - + private void prepareAssetDataSetsAreAccessible(final String... dsCodes) { context.checking(new Expectations() { { - one(service).checkDataSetCollectionAccess(SESSION_TOKEN, - Arrays.asList(dsCodes)); + one(service) + .checkDataSetCollectionAccess(SESSION_TOKEN, Arrays.asList(dsCodes)); } }); } @@ -655,8 +694,8 @@ public class DssServiceRpcScreeningTest extends AssertJUnit @Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { - Object result = super.invoke(methodInvocation); methodInvoked = true; + Object result = super.invoke(methodInvocation); return result; } } -- GitLab