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 index 738c9436897d5e1bf2d0b1e64163ff2a9a8512a9..421343d503f0c7c7e230018d575aa3e741b2a788 100644 --- 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 @@ -178,6 +178,26 @@ public class DatasetSessionAuthorizer implements IDssSessionAuthorizer } } + public Status checkSpacePowerUserAuthorization(String sessionToken) + { + if (operationLog.isInfoEnabled()) + { + operationLog.info(String.format( + "Checking if session '%s' has space power user privileges on " + + "openBIS application server.", sessionToken)); + } + final IEncapsulatedOpenBISService openBISService = ServiceProvider.getOpenBISService(); + + try + { + openBISService.checkSpacePowerUserAuthorization(sessionToken); + return Status.OK; + } catch (UserFailureException ex) + { + return Status.createError(ex.getMessage()); + } + } + /** * Clears all entries from the cache (for unit tests). */ 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 3f3de2f18d5ef359b047c0118eb5b72b739676eb..8705f2f9f5b890429192d2b9effd596ce8fcbdef 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 @@ -42,6 +42,7 @@ import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.authorization.Da import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.authorization.DssSessionAuthorizationHolder; import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.authorization.IAuthorizationGuardPredicate; import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.authorization.IDssSessionAuthorizer; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.authorization.PrivilegeLevel; /** * The advisor for authorization in the DSS RPC interfaces. @@ -213,15 +214,16 @@ public class DssServiceRpcAuthorizationAdvisor extends DefaultPointcutAdvisor manager.lock(dataSetCode); } } - boolean shouldLocksAutomaticallyBeReleased = shouldLocksAutomaticallyBeReleased(methodInvocation.getMethod()); + boolean shouldLocksAutomaticallyBeReleased = + shouldLocksAutomaticallyBeReleased(methodInvocation.getMethod()); try { - final boolean requiresInstanceAdmin = - checkRequiresInstanceAdmin(methodInvocation.getMethod(), sessionToken); // At least one of the parameters must be annotated - assert requiresInstanceAdmin || annotatedParameters.size() > 0 : "No guard defined"; - - if (requiresInstanceAdmin == false) // An instance admin is allowed to work on all data sets. + assert annotatedParameters.size() > 0 : "No guard defined"; + PrivilegeLevel level = getAndCheckPrivilegeLevel(sessionToken, methodInvocation.getMethod()); + + if (level != PrivilegeLevel.INSTANCE_ADMIN) // An instance admin is allowed to work on all + // data sets. { final Object recv = methodInvocation.getThis(); @@ -266,38 +268,45 @@ public class DssServiceRpcAuthorizationAdvisor extends DefaultPointcutAdvisor DataSetAccessGuard guard = method.getAnnotation(DataSetAccessGuard.class); return guard == null ? true : guard.releaseDataSetLocks(); } - - private boolean checkRequiresInstanceAdmin(final Method method, final String sessionToken) + + private PrivilegeLevel getAndCheckPrivilegeLevel(String sessionToken, Method method) { - final DataSetAccessGuard guard = method.getAnnotation(DataSetAccessGuard.class); - final boolean requiresInstanceAdmin = - (guard != null) ? guard.requiresInstanceAdmin() : false; + DataSetAccessGuard guard = method.getAnnotation(DataSetAccessGuard.class); + PrivilegeLevel level = guard == null ? PrivilegeLevel.DEFAULT : guard.privilegeLevel(); if (operationLog.isInfoEnabled()) { - operationLog.info("Check instance admin privileges."); + operationLog.info("Check access for privilege level " + level); } - - if (requiresInstanceAdmin) + IDssSessionAuthorizer authorizer = DssSessionAuthorizationHolder.getAuthorizer(); + Status status; + switch (level) { - final Status status = - DssSessionAuthorizationHolder.getAuthorizer() - .checkInstanceAdminAuthorization(sessionToken); - if (status != Status.OK) + case INSTANCE_ADMIN: + status = authorizer.checkInstanceAdminAuthorization(sessionToken); + break; + case SPACE_POWER_USER: + status = authorizer.checkSpacePowerUserAuthorization(sessionToken); + break; + default: + status = Status.OK; + break; + } + if (status.isError()) + { + authorizationLog.info(String.format( + "[SESSION:'%s']: Authorization failure while " + + "invoking method '%s', user has not " + level + " privilege.", + sessionToken, MethodUtils.describeMethod(method))); + String errorMessage = "You have not " + level + " privilege."; + if (null != status.tryGetErrorMessage()) { - 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); + errorMessage = status.tryGetErrorMessage(); } + + throw new AuthorizationFailureException(errorMessage); + } - return requiresInstanceAdmin; + return level; } /** diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/EncapsulatedOpenBISService.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/EncapsulatedOpenBISService.java index cc58bebb37f47085d0ff4e77c3610637c54535b9..ce3ec7336c42ca3050acfc24d80800e0b5799569 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/EncapsulatedOpenBISService.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/EncapsulatedOpenBISService.java @@ -398,6 +398,11 @@ public final class EncapsulatedOpenBISService implements IEncapsulatedOpenBISSer service.checkInstanceAdminAuthorization(sToken); } + public void checkSpacePowerUserAuthorization(String sessionToken) throws UserFailureException + { + service.checkSpacePowerUserAuthorization(sessionToken); + } + public void checkDataSetAccess(String sToken, String dataSetCode) throws UserFailureException { diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/IEncapsulatedOpenBISService.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/IEncapsulatedOpenBISService.java index 6a287a22ca440b3b00494553d93a134669805208..e77b74317024d1377fabd471fb4ec5f13548e866 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/IEncapsulatedOpenBISService.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/IEncapsulatedOpenBISService.java @@ -85,6 +85,12 @@ public interface IEncapsulatedOpenBISService @ManagedAuthentication public void checkInstanceAdminAuthorization(String sessionToken) throws UserFailureException; + /** + * Checks if the current user has SPACE_POWER_USER access rights. + */ + @ManagedAuthentication + public void checkSpacePowerUserAuthorization(String sessionToken) throws UserFailureException; + /** * Checks if the current user has access rights to a dataset with the specified data set code. */ diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/authorization/DataSetAccessGuard.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/authorization/DataSetAccessGuard.java index 4ab636eb4da38158875eb6ec95f2e2a804c7fb81..0acaaa3d0e5ce0dd01afa62fb4df3cc29e4f0449 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/authorization/DataSetAccessGuard.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/authorization/DataSetAccessGuard.java @@ -36,9 +36,9 @@ import java.lang.annotation.Target; public @interface DataSetAccessGuard { /** - * If calling this method requires instance admin privileges. + * Privilege level. */ - boolean requiresInstanceAdmin() default false; + PrivilegeLevel privilegeLevel() default PrivilegeLevel.DEFAULT; /** * By default locks on data sets are released after method invocation. diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/authorization/DssSessionAuthorizationHolder.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/authorization/DssSessionAuthorizationHolder.java index 52669187b2566a1730351fcf4f1e6d2cf4a91252..de0a967d1b96f0df90aa18482c8566327129a9e0 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/authorization/DssSessionAuthorizationHolder.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/authorization/DssSessionAuthorizationHolder.java @@ -53,6 +53,11 @@ public class DssSessionAuthorizationHolder { return Status.createError("Data set authorizer not set."); } + + public Status checkSpacePowerUserAuthorization(String sessionToken) + { + return Status.createError("Data set authorizer not set."); + } }; /** diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/authorization/IDssSessionAuthorizer.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/authorization/IDssSessionAuthorizer.java index c5c5212dd302f6bd23f2bde10031f974e5383af0..35fdba6e44dd53697eaa0b57be944db4038b6219 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/authorization/IDssSessionAuthorizer.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/authorization/IDssSessionAuthorizer.java @@ -61,4 +61,12 @@ public interface IDssSessionAuthorizer * @return {@link Status#OK} if the access is granted, an error status otherwise. */ public Status checkInstanceAdminAuthorization(String sessionToken); + + /** + * Checks whether the session identified by <var>sessionToken</var> has openBIS space power user + * privileges. + * + * @return {@link Status#OK} if the access is granted, an error status otherwise. + */ + public Status checkSpacePowerUserAuthorization(String sessionToken); } diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/authorization/PrivilegeLevel.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/authorization/PrivilegeLevel.java new file mode 100644 index 0000000000000000000000000000000000000000..bb235813581a8d0d0674ae2dd34ff3527d2f6aa1 --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/authorization/PrivilegeLevel.java @@ -0,0 +1,27 @@ +/* + * 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.internal.authorization; + +/** + * Privilege level of data set access. + * + * @author Franz-Josef Elmer + */ +public enum PrivilegeLevel +{ + INSTANCE_ADMIN, SPACE_POWER_USER, DEFAULT; +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLService.java index 4257a2a156a15475aea472c84eaadbbe823efac7..b3c54130af70d8e5ff77f4645bc80b9a9eb82735 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLService.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLService.java @@ -734,6 +734,12 @@ public class ETLService extends AbstractCommonServer<IETLService> implements IET // do nothing, the access rights specified in method annotations are checked by a proxy } + public void checkSpacePowerUserAuthorization(String sessionToken) throws UserFailureException + { + checkSession(sessionToken); + // do nothing, the access rights specified in method annotations are checked by a proxy + } + public void checkDataSetAccess(String sessionToken, String dataSetCode) throws UserFailureException { diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceLogger.java index 76a24ea47579ed6411c2043fe5bca8d0c9c51cf2..fcbcbb36ca8f89b6400e2582aa3eca2aacac2498 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceLogger.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceLogger.java @@ -246,6 +246,11 @@ public class ETLServiceLogger extends AbstractServerLogger implements IETLServic logAccess(sessionToken, "checkInstanceAdminAuthorization"); } + public void checkSpacePowerUserAuthorization(String sessionToken) throws UserFailureException + { + logAccess(sessionToken, "checkSpacePowerUserAuthorization"); + } + public void checkDataSetAccess(String sessionToken, String dataSetCode) throws UserFailureException { diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java index e0d33f4e8f5e7e7db70ce8645a3fb4137a81f5d5..1c8539c0c2daa3e71207e24228258dc98e3025cb 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java @@ -348,6 +348,13 @@ public interface IETLLIMSService extends IServer, ISessionProvider @Transactional(readOnly = true) @RolesAllowed(RoleWithHierarchy.INSTANCE_ADMIN) public void checkInstanceAdminAuthorization(String sessionToken) throws UserFailureException; + + /** + * Checks that the user of specified session has SPACE_POWER_USER access rights. + */ + @Transactional(readOnly = true) + @RolesAllowed(RoleWithHierarchy.SPACE_POWER_USER) + public void checkSpacePowerUserAuthorization(String sessionToken) throws UserFailureException; /** * Does nothing besides checking that the current user has rights to access the content of the diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java.expected b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java.expected index e0d33f4e8f5e7e7db70ce8645a3fb4137a81f5d5..1c8539c0c2daa3e71207e24228258dc98e3025cb 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java.expected +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java.expected @@ -348,6 +348,13 @@ public interface IETLLIMSService extends IServer, ISessionProvider @Transactional(readOnly = true) @RolesAllowed(RoleWithHierarchy.INSTANCE_ADMIN) public void checkInstanceAdminAuthorization(String sessionToken) throws UserFailureException; + + /** + * Checks that the user of specified session has SPACE_POWER_USER access rights. + */ + @Transactional(readOnly = true) + @RolesAllowed(RoleWithHierarchy.SPACE_POWER_USER) + public void checkSpacePowerUserAuthorization(String sessionToken) throws UserFailureException; /** * Does nothing besides checking that the current user has rights to access the content of the 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 1b49df196620055dbabe44df863a47279e60a774..0bde2cd6a4862200c08a8709ec6d77c01e5bfa15 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 @@ -24,6 +24,7 @@ import ch.systemsx.cisd.common.api.IRpcService; import ch.systemsx.cisd.common.api.MinimalMinorVersion; import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.authorization.AuthorizationGuard; import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.authorization.DataSetAccessGuard; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.authorization.PrivilegeLevel; import ch.systemsx.cisd.openbis.dss.screening.shared.api.internal.authorization.DatasetIdentifierPredicate; import ch.systemsx.cisd.openbis.dss.screening.shared.api.internal.authorization.SingleDataSetIdentifierPredicate; import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.FeatureVectorDataset; @@ -309,7 +310,7 @@ public interface IDssServiceRpcScreening extends IRpcService * @since 1.4 */ @MinimalMinorVersion(4) - @DataSetAccessGuard(requiresInstanceAdmin = true) + @DataSetAccessGuard(privilegeLevel = PrivilegeLevel.SPACE_POWER_USER) public void saveImageTransformerFactory( String sessionToken, @AuthorizationGuard(guardClass = DatasetIdentifierPredicate.class) List<IDatasetIdentifier> dataSetIdentifiers, 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 a872a86b1be44711d8a791545f770703acfa4361..7a603291db437b908c54daa45b8a28052e6aea9c 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 @@ -439,8 +439,8 @@ public class DssServiceRpcScreeningTest extends AssertJUnit context.checking(new Expectations() { { - one(service).checkInstanceAdminAuthorization(SESSION_TOKEN); - will(throwException(new UserFailureException("You are not an admin."))); + one(service).checkSpacePowerUserAuthorization(SESSION_TOKEN); + will(throwException(new UserFailureException("You are not a space power user."))); } }); @@ -451,7 +451,7 @@ public class DssServiceRpcScreeningTest extends AssertJUnit fail("Unauthorized access not detected."); } catch (AuthorizationFailureException ex) { - assertEquals("Authorization failure: You are not an admin.", ex.getMessage()); + assertEquals("Authorization failure: You are not a space power user.", ex.getMessage()); } assertTrue(testMethodInterceptor.methodInvoked); @@ -465,11 +465,12 @@ public class DssServiceRpcScreeningTest extends AssertJUnit final DatasetIdentifier ds2 = new DatasetIdentifier("ds2", "url1"); final String channel = "dapi"; prepareLockDataSet(DATASET_CODE, "ds2"); + prepareAssetDataSetsAreAccessible(); context.checking(new Expectations() { { - one(service).checkInstanceAdminAuthorization(SESSION_TOKEN); - + one(service).checkSpacePowerUserAuthorization(SESSION_TOKEN); + long datasetId = 123; ImgDatasetDTO dataset = createDataset(datasetId); dataset.setPermId(DATASET_CODE); @@ -509,10 +510,11 @@ public class DssServiceRpcScreeningTest extends AssertJUnit { final DatasetIdentifier ds1 = new DatasetIdentifier(DATASET_CODE, "url1"); prepareLockDataSet(DATASET_CODE); + prepareAssetDataSetsAreAccessible("ds1"); context.checking(new Expectations() { { - one(service).checkInstanceAdminAuthorization(SESSION_TOKEN); + one(service).checkSpacePowerUserAuthorization(SESSION_TOKEN); Long containerId = 312L;