From c2be2917c671bb77b761bf48b55d48ebdfa62731 Mon Sep 17 00:00:00 2001 From: pkupczyk <pkupczyk> Date: Mon, 3 Apr 2017 19:36:02 +0000 Subject: [PATCH] SSDM-4999 : Project Authorization - Step 0: - extend RoleWithHierarchy with new project roles - add configuration switch to enable/disable project level authorization (disabled by default) - hide the new roles in all the places where they would automatically appear (show them only if the new feature is enabled) - extend/fix automated tests to cover new roles SVN: 38009 --- .../ui/amc/AddRoleAssignmentDialog.java | 2 +- .../application/ui/amc/RoleListBox.java | 18 ++++- .../web/client/dto/ApplicationInfo.java | 12 +++ .../web/server/AbstractClientService.java | 11 +++ .../api/v1/GeneralInformationService.java | 34 +++++--- .../server/authorization/CapabilityMap.java | 31 +++++-- .../DefaultAccessController.java | 3 +- .../business/bo/AbstractBusinessObject.java | 15 +++- .../dataaccess/IAuthorizationDAOFactory.java | 5 ++ .../db/AuthorizationDAOFactory.java | 14 +++- .../server/dataaccess/db/DAOFactory.java | 5 +- .../authorization/AuthorizationConfig.java | 80 +++++++++++++++++++ .../AuthorizationConfigFacade.java | 50 ++++++++++++ .../authorization/IAuthorizationConfig.java | 27 +++++++ .../shared/basic/dto/RoleWithHierarchy.java | 15 +++- .../QueryDatabaseDefinitionProvider.java | 21 ++++- .../source/java/genericApplicationContext.xml | 1 + .../api/v1/GeneralInformationServiceTest.java | 18 ++++- .../authorization/CapabilityMapTest.java | 34 +++++--- .../DefaultAccessControllerTest.java | 33 +++++--- .../basic/dto/RoleWithHierarchyTest.java | 43 +++++++++- 21 files changed, 412 insertions(+), 60 deletions(-) create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/AuthorizationConfig.java create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/AuthorizationConfigFacade.java create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/IAuthorizationConfig.java diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/amc/AddRoleAssignmentDialog.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/amc/AddRoleAssignmentDialog.java index 4333021acae..9505434ae26 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/amc/AddRoleAssignmentDialog.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/amc/AddRoleAssignmentDialog.java @@ -77,7 +77,7 @@ public class AddRoleAssignmentDialog extends AbstractRegistrationDialog group = new SpaceSelectionWidget(viewContext, PREFIX, false, false); group.setWidth(100); - roleBox = new AdapterField(new RoleListBox(group)); + roleBox = new AdapterField(new RoleListBox(viewContext, group)); roleBox.setFieldLabel("Role"); roleBox.setWidth(100); roleBox.setId(ROLE_FIELD_ID); diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/amc/RoleListBox.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/amc/RoleListBox.java index 4f804cf8e55..39cd50d7a60 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/amc/RoleListBox.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/amc/RoleListBox.java @@ -23,6 +23,8 @@ import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ChangeHandler; import com.google.gwt.user.client.ui.ListBox; +import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync; +import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext; import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.SpaceSelectionWidget; import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.FieldUtil; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy; @@ -35,10 +37,14 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy; public class RoleListBox extends ListBox { + private IViewContext<ICommonClientServiceAsync> viewContext; + private List<RoleWithHierarchy> roles; - public RoleListBox(final SpaceSelectionWidget groupWidget) + public RoleListBox(IViewContext<ICommonClientServiceAsync> viewContext, final SpaceSelectionWidget groupWidget) { + this.viewContext = viewContext; + for (RoleWithHierarchy visibleRoleCode : getRoles()) { addItem(visibleRoleCode.toString()); @@ -77,10 +83,18 @@ public class RoleListBox extends ListBox { if (roles == null) { + boolean projectLevelAuthorizationEnabled = viewContext.getModel().getApplicationInfo().isProjectAuthorizationEnabled(); + roles = new ArrayList<RoleWithHierarchy>(); for (RoleWithHierarchy role : RoleWithHierarchy.values()) { - if (!RoleWithHierarchy.INSTANCE_DISABLED.equals(role)) + if (RoleWithHierarchy.INSTANCE_DISABLED.equals(role)) + { + continue; + } else if (role.isProjectLevel() && false == projectLevelAuthorizationEnabled) + { + continue; + } else { roles.add(role); } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ApplicationInfo.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ApplicationInfo.java index c8a023707ee..f6159f0450c 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ApplicationInfo.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ApplicationInfo.java @@ -47,6 +47,8 @@ public final class ApplicationInfo implements IsSerializable private boolean projectSamplesEnabled; + private boolean projectLevelAuthorizationEnabled; + private WebClientConfiguration webClientConfiguration; private Set<String> enabledTechnologies; @@ -179,4 +181,14 @@ public final class ApplicationInfo implements IsSerializable this.projectSamplesEnabled = projectSamplesEnabled; } + public boolean isProjectAuthorizationEnabled() + { + return projectLevelAuthorizationEnabled; + } + + public void setProjectLevelAuthorizationEnabled(boolean projectAuthorizationEnabled) + { + this.projectLevelAuthorizationEnabled = projectAuthorizationEnabled; + } + } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/AbstractClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/AbstractClientService.java index abc4dfb9a06..fbcc6fa4de9 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/AbstractClientService.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/AbstractClientService.java @@ -77,6 +77,8 @@ import ch.systemsx.cisd.openbis.generic.server.SessionConstants; import ch.systemsx.cisd.openbis.generic.shared.Constants; import ch.systemsx.cisd.openbis.generic.shared.IServer; import ch.systemsx.cisd.openbis.generic.shared.WebClientConfigurationProvider; +import ch.systemsx.cisd.openbis.generic.shared.authorization.AuthorizationConfigFacade; +import ch.systemsx.cisd.openbis.generic.shared.authorization.IAuthorizationConfig; import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolder; import ch.systemsx.cisd.openbis.generic.shared.basic.TechId; import ch.systemsx.cisd.openbis.generic.shared.basic.WebAppsProperties; @@ -119,6 +121,9 @@ public abstract class AbstractClientService implements IClientService, @Autowired private TableDataCache<String, Object> tableDataCache; + @Autowired + private IAuthorizationConfig authorizationConfig; + private String cifexURL; private String cifexRecipient; @@ -475,6 +480,7 @@ public abstract class AbstractClientService implements IClientService, applicationInfo.setWebapps(extractWebAppsProperties()); applicationInfo.setArchivingConfigured(isArchivingConfigured()); applicationInfo.setProjectSamplesEnabled(isProjectSamplesEnabled()); + applicationInfo.setProjectLevelAuthorizationEnabled(isProjectLevelAuthorizationEnabled()); applicationInfo.setVersion(getVersion()); return applicationInfo; } @@ -565,6 +571,11 @@ public abstract class AbstractClientService implements IClientService, return false; } + private boolean isProjectLevelAuthorizationEnabled() + { + return new AuthorizationConfigFacade(authorizationConfig).isProjectLevelEnabled(); + } + @Override public final SessionContext tryToGetCurrentSessionContext(boolean anonymous, String sessionIdOrNull) { diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationService.java index b9a4da48b86..43ff9eed1d9 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationService.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationService.java @@ -33,6 +33,7 @@ import javax.annotation.Resource; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.Transformer; import org.hibernate.SQLQuery; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; @@ -106,6 +107,8 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.experiment.IExperim import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.metaproject.IMetaprojectId; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.project.IProjectId; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.sample.ISampleId; +import ch.systemsx.cisd.openbis.generic.shared.authorization.AuthorizationConfigFacade; +import ch.systemsx.cisd.openbis.generic.shared.authorization.IAuthorizationConfig; import ch.systemsx.cisd.openbis.generic.shared.basic.TechId; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AbstractExternalData; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ContainerDataSet; @@ -159,6 +162,9 @@ public class GeneralInformationService extends AbstractServer<IGeneralInformatio @Resource(name = ComponentNames.MANAGED_PROPERTY_EVALUATOR_FACTORY) private IManagedPropertyEvaluatorFactory managedPropertyEvaluatorFactory; + @Autowired + private IAuthorizationConfig authorizationConfig; + // Default constructor needed by Spring public GeneralInformationService() { @@ -166,11 +172,12 @@ public class GeneralInformationService extends AbstractServer<IGeneralInformatio GeneralInformationService(IOpenBisSessionManager sessionManager, IDAOFactory daoFactory, ICommonBusinessObjectFactory boFactory, IPropertiesBatchManager propertiesBatchManager, - ICommonServer commonServer) + ICommonServer commonServer, IAuthorizationConfig authorizationConfig) { super(sessionManager, daoFactory, propertiesBatchManager); this.boFactory = boFactory; this.commonServer = commonServer; + this.authorizationConfig = authorizationConfig; } @Override @@ -202,17 +209,26 @@ public class GeneralInformationService extends AbstractServer<IGeneralInformatio { checkSession(sessionToken); + AuthorizationConfigFacade configFacade = new AuthorizationConfigFacade(authorizationConfig); + Map<String, Set<Role>> namedRoleSets = new LinkedHashMap<String, Set<Role>>(); RoleWithHierarchy[] values = RoleWithHierarchy.values(); + for (RoleWithHierarchy roleSet : values) { - Set<RoleWithHierarchy> roles = roleSet.getRoles(); - Set<Role> translatedRoles = new HashSet<Role>(); - for (RoleWithHierarchy role : roles) + if (configFacade.isRoleEnabled(roleSet)) { - translatedRoles.add(Translator.translate(role)); + Set<RoleWithHierarchy> roles = roleSet.getRoles(); + Set<Role> translatedRoles = new HashSet<Role>(); + for (RoleWithHierarchy role : roles) + { + if (configFacade.isRoleEnabled(role)) + { + translatedRoles.add(Translator.translate(role)); + } + } + namedRoleSets.put(roleSet.name(), translatedRoles); } - namedRoleSets.put(roleSet.name(), translatedRoles); } return namedRoleSets; } @@ -623,8 +639,7 @@ public class GeneralInformationService extends AbstractServer<IGeneralInformatio @Override @Transactional(readOnly = true) - @RolesAllowed(value = - { RoleWithHierarchy.SPACE_OBSERVER, RoleWithHierarchy.SPACE_ETL_SERVER }) + @RolesAllowed(value = { RoleWithHierarchy.SPACE_OBSERVER, RoleWithHierarchy.SPACE_ETL_SERVER }) public String tryGetDataStoreBaseURL(String sessionToken, String dataSetCode) { Session session = getSession(sessionToken); @@ -641,8 +656,7 @@ public class GeneralInformationService extends AbstractServer<IGeneralInformatio @Override @Transactional(readOnly = true) - @RolesAllowed(value = - { RoleWithHierarchy.SPACE_OBSERVER, RoleWithHierarchy.SPACE_ETL_SERVER }) + @RolesAllowed(value = { RoleWithHierarchy.SPACE_OBSERVER, RoleWithHierarchy.SPACE_ETL_SERVER }) public List<DataStoreURLForDataSets> getDataStoreBaseURLs(String sessionToken, List<String> dataSetCodes) { diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/CapabilityMap.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/CapabilityMap.java index 952c2cfa85e..6ebbf47b702 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/CapabilityMap.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/CapabilityMap.java @@ -34,6 +34,8 @@ import ch.systemsx.cisd.base.exceptions.CheckedExceptionTunnel; import ch.systemsx.cisd.common.logging.LogCategory; import ch.systemsx.cisd.common.logging.LogFactory; import ch.systemsx.cisd.openbis.generic.server.authorization.annotation.Capability; +import ch.systemsx.cisd.openbis.generic.shared.authorization.AuthorizationConfigFacade; +import ch.systemsx.cisd.openbis.generic.shared.authorization.IAuthorizationConfig; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy; /** @@ -46,6 +48,8 @@ class CapabilityMap private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION, CapabilityMap.class); + private final IAuthorizationConfig authorizationConfig; + private final Map<String, Collection<RoleWithHierarchy>> capMap = new HashMap<String, Collection<RoleWithHierarchy>>(); @@ -73,13 +77,15 @@ class CapabilityMap } } - CapabilityMap(File file) + CapabilityMap(File file, IAuthorizationConfig authorizationConfig) { - this(readLines(file), file.getPath()); + this(readLines(file), file.getPath(), authorizationConfig); } - CapabilityMap(List<String> lines, String filePath) + CapabilityMap(List<String> lines, String filePath, IAuthorizationConfig authorizationConfig) { + this.authorizationConfig = authorizationConfig; + for (String line : lines) { final String trimmed = line.trim(); @@ -133,23 +139,34 @@ class CapabilityMap private void addRoles(String capabilityName, String roleNames, String line, String filePath) { Collection<RoleWithHierarchy> roles = capMap.get(capabilityName); + if (roles == null) { roles = new HashSet<RoleWithHierarchy>(); capMap.put(capabilityName, roles); } + + AuthorizationConfigFacade configFacade = new AuthorizationConfigFacade(authorizationConfig); + for (String roleName : StringUtils.split(roleNames, ",")) { roleName = roleName.trim().toUpperCase(); try { final RoleWithHierarchy role = RoleWithHierarchy.valueOf(roleName); - roles.add(role); - if (operationLog.isDebugEnabled()) + if (configFacade.isRoleEnabled(role)) + { + roles.add(role); + + if (operationLog.isDebugEnabled()) + { + operationLog.debug(String + .format("Add to map: '%s' -> %s", capabilityName, role)); + } + } else { - operationLog.debug(String - .format("Add to map: '%s' -> %s", capabilityName, role)); + logWarning(line, filePath, "role '" + roleName + "' doesn't exist"); } } catch (IllegalArgumentException ex) { diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/DefaultAccessController.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/DefaultAccessController.java index 18224192b48..fdc603fc8ff 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/DefaultAccessController.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/authorization/DefaultAccessController.java @@ -77,12 +77,13 @@ public final class DefaultAccessController implements IAccessController private final Map<Method, Map<String, Set<RoleWithHierarchy>>> argumentRolesCache = new HashMap<>(); - private final CapabilityMap capabilities = new CapabilityMap(new File("etc/capabilities")); + private final CapabilityMap capabilities; private PredicateExecutor predicateExecutor; public DefaultAccessController(final IAuthorizationDAOFactory daoFactory) { + capabilities = new CapabilityMap(new File("etc/capabilities"), daoFactory.getAuthorizationConfig()); predicateExecutor = new PredicateExecutor(); predicateExecutor.setPredicateFactory(new PredicateFactory()); predicateExecutor.setDAOFactory(daoFactory); diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObject.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObject.java index cbe3dd1bbb2..15124cdd817 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObject.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObject.java @@ -87,6 +87,7 @@ import ch.systemsx.cisd.openbis.generic.server.util.SpaceIdentifierHelper; import ch.systemsx.cisd.openbis.generic.shared.IDataStoreService; import ch.systemsx.cisd.openbis.generic.shared.ResourceNames; import ch.systemsx.cisd.openbis.generic.shared.WebClientConfigurationProvider; +import ch.systemsx.cisd.openbis.generic.shared.authorization.IAuthorizationConfig; import ch.systemsx.cisd.openbis.generic.shared.basic.IIdHolder; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Identifier; @@ -604,6 +605,12 @@ abstract class AbstractBusinessObject implements IDAOFactory return daoFactory.getOperationExecutionDAO(); } + @Override + public IAuthorizationConfig getAuthorizationConfig() + { + return daoFactory.getAuthorizationConfig(); + } + protected RelationshipTypePE getParentChildRelationshipType() { return RelationshipUtils.getParentChildRelationshipType(getRelationshipTypeDAO()); @@ -836,7 +843,7 @@ abstract class AbstractBusinessObject implements IDAOFactory } assignmentManager.performAssignment(relationshipService, session); } - + protected void assignSampleToProject(SamplePE sample, ProjectPE project) { if (project != null) @@ -867,7 +874,7 @@ abstract class AbstractBusinessObject implements IDAOFactory assignmentManager.assignDataSetAndRelatedComponents(data, newSample, experiment); assignmentManager.performAssignment(relationshipService, session); } - + protected <T extends IEntityInformationWithPropertiesHolder> void reindex(Class<T> objectClass, Collection<T> objects) { IDynamicPropertyEvaluationScheduler indexUpdater = daoFactory.getPersistencyResources().getDynamicPropertyEvaluationScheduler(); @@ -891,7 +898,7 @@ abstract class AbstractBusinessObject implements IDAOFactory { return WebClientConfigUtils.getExperimentText(getWebClientConfigProvider()); } - + protected String getSampleText() { return WebClientConfigUtils.getSampleText(getWebClientConfigProvider()); @@ -902,5 +909,5 @@ abstract class AbstractBusinessObject implements IDAOFactory return (WebClientConfigurationProvider) CommonServiceProvider.tryToGetBean( ResourceNames.WEB_CLIENT_CONFIGURATION_PROVIDER); } - + } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IAuthorizationDAOFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IAuthorizationDAOFactory.java index fd00edc2014..682db814727 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IAuthorizationDAOFactory.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IAuthorizationDAOFactory.java @@ -18,6 +18,8 @@ package ch.systemsx.cisd.openbis.generic.server.dataaccess; import org.hibernate.SessionFactory; +import ch.systemsx.cisd.openbis.generic.shared.authorization.IAuthorizationConfig; + /** * Factory definition for all Data Access Objects which are needed for managing authorization. * @@ -25,6 +27,9 @@ import org.hibernate.SessionFactory; */ public interface IAuthorizationDAOFactory { + + public IAuthorizationConfig getAuthorizationConfig(); + /** Returns the persistency resources used to create DAO's. */ public PersistencyResources getPersistencyResources(); diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/AuthorizationDAOFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/AuthorizationDAOFactory.java index ba5176b0a10..af1317179cc 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/AuthorizationDAOFactory.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/AuthorizationDAOFactory.java @@ -37,6 +37,7 @@ import ch.systemsx.cisd.openbis.generic.server.dataaccess.ISampleDAO; import ch.systemsx.cisd.openbis.generic.server.dataaccess.ISpaceDAO; import ch.systemsx.cisd.openbis.generic.server.dataaccess.PersistencyResources; import ch.systemsx.cisd.openbis.generic.server.dataaccess.db.deletion.EntityHistoryCreator; +import ch.systemsx.cisd.openbis.generic.shared.authorization.IAuthorizationConfig; import ch.systemsx.cisd.openbis.generic.shared.util.HibernateUtils; /** @@ -47,6 +48,8 @@ import ch.systemsx.cisd.openbis.generic.shared.util.HibernateUtils; public class AuthorizationDAOFactory implements IAuthorizationDAOFactory { + private final IAuthorizationConfig authorizationConfig; + private final IRoleAssignmentDAO roleAssignmentDAO; private final ISpaceDAO groupDAO; @@ -78,10 +81,10 @@ public class AuthorizationDAOFactory implements IAuthorizationDAOFactory public AuthorizationDAOFactory(final DatabaseConfigurationContext context, final SessionFactory sessionFactory, final IDynamicPropertyEvaluationScheduler dynamicPropertyEvaluationScheduler, - final EntityHistoryCreator historyCreator) + final EntityHistoryCreator historyCreator, final IAuthorizationConfig authorizationConfig) { persistencyResources = - new PersistencyResources(context, sessionFactory, + new PersistencyResources(context, sessionFactory, dynamicPropertyEvaluationScheduler); personDAO = new PersonDAO(sessionFactory, historyCreator); groupDAO = new SpaceDAO(sessionFactory, historyCreator); @@ -96,6 +99,7 @@ public class AuthorizationDAOFactory implements IAuthorizationDAOFactory queryDAO = new QueryDAO(sessionFactory, historyCreator); deletionDAO = new DeletionDAO(sessionFactory, persistencyResources, historyCreator); metaprojectDAO = new MetaprojectDAO(sessionFactory, historyCreator); + this.authorizationConfig = authorizationConfig; } @Override @@ -188,6 +192,12 @@ public class AuthorizationDAOFactory implements IAuthorizationDAOFactory return metaprojectDAO; } + @Override + public IAuthorizationConfig getAuthorizationConfig() + { + return authorizationConfig; + } + /** * Configures current session settings for batch update mode. * diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DAOFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DAOFactory.java index ca7eed5425c..e0001389dc2 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DAOFactory.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DAOFactory.java @@ -65,6 +65,7 @@ import ch.systemsx.cisd.openbis.generic.server.dataaccess.db.deletion.EntityHist import ch.systemsx.cisd.openbis.generic.server.dataaccess.db.search.HibernateSearchContext; import ch.systemsx.cisd.openbis.generic.server.dataaccess.util.UpdateUtils; import ch.systemsx.cisd.openbis.generic.shared.Constants; +import ch.systemsx.cisd.openbis.generic.shared.authorization.IAuthorizationConfig; import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE; import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind; @@ -142,9 +143,9 @@ public final class DAOFactory extends AuthorizationDAOFactory implements IDAOFac public DAOFactory(final DatabaseConfigurationContext context, final SessionFactory sessionFactory, HibernateSearchContext hibernateSearchContext, final IDynamicPropertyEvaluationScheduler dynamicPropertyEvaluationScheduler, - final EntityHistoryCreator historyCreator) + final EntityHistoryCreator historyCreator, final IAuthorizationConfig authorizationConfig) { - super(context, sessionFactory, dynamicPropertyEvaluationScheduler, historyCreator); + super(context, sessionFactory, dynamicPropertyEvaluationScheduler, historyCreator, authorizationConfig); this.context = context; this.dynamicPropertyEvaluationScheduler = dynamicPropertyEvaluationScheduler; historyCreator.setDaoFactory(this); diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/AuthorizationConfig.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/AuthorizationConfig.java new file mode 100644 index 00000000000..c0f8de5dcc9 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/AuthorizationConfig.java @@ -0,0 +1,80 @@ +/* + * Copyright 2017 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.generic.shared.authorization; + +import java.util.Properties; + +import javax.annotation.PostConstruct; + +import org.apache.log4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import ch.systemsx.cisd.common.logging.LogCategory; +import ch.systemsx.cisd.common.logging.LogFactory; +import ch.systemsx.cisd.common.spring.ExposablePropertyPlaceholderConfigurer; + +/** + * @author pkupczyk + */ +@Component("authorization-config") +public class AuthorizationConfig implements IAuthorizationConfig +{ + + private static final String PROJECT_LEVEL_AUTHORIZATION_ENABLED_PROPERTY_NAME = "authorization.project-level-enabled"; + + private static final boolean PROJECT_LEVEL_AUTHORIZATION_ENABLED_DEFAULT = false; + + private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION, AuthorizationConfig.class); + + private boolean projectLevelEnabled; + + @Autowired + private ExposablePropertyPlaceholderConfigurer configurer; + + private AuthorizationConfig() + { + } + + @PostConstruct + private void init() + { + Properties properties = configurer.getResolvedProps(); + + String projectLevelEnabledString = properties.getProperty(PROJECT_LEVEL_AUTHORIZATION_ENABLED_PROPERTY_NAME); + + if (projectLevelEnabledString == null || projectLevelEnabledString.trim().isEmpty()) + { + projectLevelEnabled = PROJECT_LEVEL_AUTHORIZATION_ENABLED_DEFAULT; + } else + { + projectLevelEnabled = Boolean.parseBoolean(projectLevelEnabledString); + } + + if (projectLevelEnabled) + { + operationLog.info("Project level authorization is enabled"); + } + } + + @Override + public boolean isProjectLevelEnabled() + { + return projectLevelEnabled; + } + +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/AuthorizationConfigFacade.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/AuthorizationConfigFacade.java new file mode 100644 index 00000000000..b7614ad862a --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/AuthorizationConfigFacade.java @@ -0,0 +1,50 @@ +/* + * Copyright 2017 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.generic.shared.authorization; + +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy; + +/** + * @author pkupczyk + */ +public class AuthorizationConfigFacade +{ + + private IAuthorizationConfig authorizationConfig; + + public AuthorizationConfigFacade(IAuthorizationConfig authorizationConfig) + { + this.authorizationConfig = authorizationConfig; + } + + public boolean isProjectLevelEnabled() + { + return authorizationConfig.isProjectLevelEnabled(); + } + + public boolean isRoleEnabled(RoleWithHierarchy role) + { + if (role.isProjectLevel()) + { + return authorizationConfig.isProjectLevelEnabled(); + } else + { + return true; + } + } + +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/IAuthorizationConfig.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/IAuthorizationConfig.java new file mode 100644 index 00000000000..930b74dc101 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/authorization/IAuthorizationConfig.java @@ -0,0 +1,27 @@ +/* + * Copyright 2017 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.generic.shared.authorization; + +/** + * @author pkupczyk + */ +public interface IAuthorizationConfig +{ + + public boolean isProjectLevelEnabled(); + +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/RoleWithHierarchy.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/RoleWithHierarchy.java index dc2db87f2ae..b2e0f93d1a7 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/RoleWithHierarchy.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/RoleWithHierarchy.java @@ -70,11 +70,19 @@ public enum RoleWithHierarchy implements Serializable SPACE_ETL_SERVER(INSTANCE_ETL_SERVER), + PROJECT_ADMIN(SPACE_ADMIN), + + PROJECT_POWER_USER(PROJECT_ADMIN, SPACE_POWER_USER), + + PROJECT_USER(PROJECT_POWER_USER, SPACE_USER), + + PROJECT_OBSERVER(PROJECT_USER, SPACE_OBSERVER) + ; public static enum RoleLevel implements IsSerializable { - INSTANCE, SPACE; + INSTANCE, SPACE, PROJECT; } /** @@ -181,6 +189,11 @@ public enum RoleWithHierarchy implements Serializable return roleLevel.equals(RoleLevel.SPACE); } + public boolean isProjectLevel() + { + return roleLevel.equals(RoleLevel.PROJECT); + } + public RoleLevel getRoleLevel() { return roleLevel; diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/server/QueryDatabaseDefinitionProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/server/QueryDatabaseDefinitionProvider.java index 8538f6abf0c..31b4f193bb7 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/server/QueryDatabaseDefinitionProvider.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/query/server/QueryDatabaseDefinitionProvider.java @@ -25,6 +25,7 @@ import java.util.Set; import javax.annotation.Resource; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import ch.systemsx.cisd.common.exceptions.UserFailureException; @@ -35,6 +36,8 @@ import ch.systemsx.cisd.common.spring.ExposablePropertyPlaceholderConfigurer; import ch.systemsx.cisd.dbmigration.SimpleDatabaseConfigurationContext; import ch.systemsx.cisd.openbis.generic.server.ComponentNames; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory; +import ch.systemsx.cisd.openbis.generic.shared.authorization.AuthorizationConfigFacade; +import ch.systemsx.cisd.openbis.generic.shared.authorization.IAuthorizationConfig; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy; import ch.systemsx.cisd.openbis.generic.shared.dto.SpacePE; import ch.systemsx.cisd.openbis.plugin.query.server.authorization.QueryAccessController; @@ -72,6 +75,9 @@ public class QueryDatabaseDefinitionProvider implements IQueryDatabaseDefinition @Resource(name = ComponentNames.DAO_FACTORY) private IDAOFactory daoFactory; + @Autowired + private IAuthorizationConfig authorizationConfig; + /** * map from dbKey to DatabaseDefinition */ @@ -130,8 +136,19 @@ public class QueryDatabaseDefinitionProvider implements IQueryDatabaseDefinition { final RoleWithHierarchy creatorMinimalRole = RoleWithHierarchy.valueOf(creatorMinimalRoleString); - definitions.put(databaseKey, new DatabaseDefinition(configurationContext, - databaseKey, label, creatorMinimalRole, dataSpaceOrNull)); + + AuthorizationConfigFacade configFacade = new AuthorizationConfigFacade(authorizationConfig); + + if (configFacade.isRoleEnabled(creatorMinimalRole)) + { + definitions.put(databaseKey, new DatabaseDefinition(configurationContext, + databaseKey, label, creatorMinimalRole, dataSpaceOrNull)); + } else + { + throw new UnsupportedOperationException("Query database '" + databaseKey + + "' is not defined properly. '" + creatorMinimalRoleString + + "' is not a valid role."); + } } catch (IllegalArgumentException ex) { throw new UnsupportedOperationException("Query database '" + databaseKey diff --git a/openbis/source/java/genericApplicationContext.xml b/openbis/source/java/genericApplicationContext.xml index dd3fb142158..362ea3aeb07 100644 --- a/openbis/source/java/genericApplicationContext.xml +++ b/openbis/source/java/genericApplicationContext.xml @@ -113,6 +113,7 @@ <constructor-arg ref="hibernate-search-context" /> <constructor-arg ref="dynamic-property-scheduler" /> <constructor-arg ref="entity-history-creator" /> + <constructor-arg ref="authorization-config" /> </bean> <bean id="dss-factory" diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationServiceTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationServiceTest.java index 5390d1a6267..41bdb63e342 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationServiceTest.java +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationServiceTest.java @@ -53,6 +53,7 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SampleFetchOption; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SearchCriteria; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SearchCriteria.MatchClause; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SearchCriteria.MatchClauseAttribute; +import ch.systemsx.cisd.openbis.generic.shared.authorization.IAuthorizationConfig; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SearchSubCriteria; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SpaceWithProjectsAndRoleAssignments; import ch.systemsx.cisd.openbis.generic.shared.basic.TechId; @@ -96,6 +97,8 @@ public class GeneralInformationServiceTest extends AbstractServerTestCase private ICommonBusinessObjectFactory boFactory; + private IAuthorizationConfig authorizationConfig; + @Override @BeforeMethod public final void setUp() @@ -104,10 +107,11 @@ public class GeneralInformationServiceTest extends AbstractServerTestCase commonServer = context.mock(ICommonServer.class); boFactory = context.mock(ICommonBusinessObjectFactory.class); sampleLister2 = context.mock(ISampleLister.class, "sampleListerForAPI"); + authorizationConfig = context.mock(IAuthorizationConfig.class); service = new GeneralInformationService(sessionManager, daoFactory, boFactory, - propertiesBatchManager, commonServer) + propertiesBatchManager, commonServer, authorizationConfig) { @Override protected ISampleLister createSampleLister(PersonPE person) @@ -123,6 +127,14 @@ public class GeneralInformationServiceTest extends AbstractServerTestCase { prepareGetSession(); + context.checking(new Expectations() + { + { + allowing(authorizationConfig).isProjectLevelEnabled(); + will(returnValue(false)); + } + }); + Map<String, Set<Role>> namedRoleSets = service.listNamedRoleSets(SESSION_TOKEN); List<Entry<String, Set<Role>>> entries = @@ -319,7 +331,7 @@ public class GeneralInformationServiceTest extends AbstractServerTestCase + "PROPERTY PARENT_PROPERTY: parent property value] (with wildcards), " + "ATTRIBUTE CODE: parent code AND PROPERTY PARENT_PROPERTY: " + "parent property value (with wildcards)]", criteriaMatcher.getRecordedObjects() - .toString()); + .toString()); context.assertIsSatisfied(); } @@ -351,7 +363,7 @@ public class GeneralInformationServiceTest extends AbstractServerTestCase + "PROPERTY CHILD_PROPERTY: child property value] (with wildcards), " + "ATTRIBUTE CODE: child code AND PROPERTY CHILD_PROPERTY: " + "child property value (with wildcards)]", criteriaMatcher.getRecordedObjects() - .toString()); + .toString()); context.assertIsSatisfied(); } diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/authorization/CapabilityMapTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/authorization/CapabilityMapTest.java index 74b08314ac1..103459eefe5 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/authorization/CapabilityMapTest.java +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/authorization/CapabilityMapTest.java @@ -32,6 +32,7 @@ import org.testng.annotations.Test; import ch.systemsx.cisd.common.logging.BufferedAppender; import ch.systemsx.cisd.common.logging.LogInitializer; import ch.systemsx.cisd.openbis.generic.server.authorization.annotation.Capability; +import ch.systemsx.cisd.openbis.generic.shared.authorization.IAuthorizationConfig; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy; import ch.systemsx.cisd.openbis.util.LogRecordingUtils; @@ -80,7 +81,7 @@ public class CapabilityMapTest { CapabilityMap capMap = new CapabilityMap(Arrays.asList("A: SPACE_POWER_USER\t", "# Some comment", "", - " B INSTANCE_ETL_SERVER"), "<memory>"); + " B INSTANCE_ETL_SERVER"), "<memory>", new TestAuthorizationConfig()); assertEquals("", logRecorder.getLogContent()); assertEquals( @@ -101,7 +102,7 @@ public class CapabilityMapTest { CapabilityMap capMap = new CapabilityMap(Arrays.asList("A:SPACE_POWER_USER\t", "# Some comment", "", - " B INSTANCE_ETL_SERVER"), "<memory>"); + " B INSTANCE_ETL_SERVER"), "<memory>", new TestAuthorizationConfig()); assertEquals("", logRecorder.getLogContent()); assertEquals( @@ -122,7 +123,7 @@ public class CapabilityMapTest { CapabilityMap capMap = new CapabilityMap(Arrays.asList("A :SPACE_POWER_USER\t", "# Some comment", "", - " B INSTANCE_ETL_SERVER"), "<memory>"); + " B INSTANCE_ETL_SERVER"), "<memory>", new TestAuthorizationConfig()); assertEquals("", logRecorder.getLogContent()); assertEquals( @@ -143,7 +144,7 @@ public class CapabilityMapTest { CapabilityMap capMap = new CapabilityMap(Arrays.asList("A : SPACE_POWER_USER\t", "# Some comment", "", - " b instance_etl_server"), "<memory>"); + " b instance_etl_server"), "<memory>", new TestAuthorizationConfig()); assertEquals("", logRecorder.getLogContent()); assertEquals( @@ -164,7 +165,7 @@ public class CapabilityMapTest { CapabilityMap capMap = new CapabilityMap(Arrays.asList("A SPACE_POWER_USER\t", - " A INSTANCE_ETL_SERVER"), "<memory>"); + " A INSTANCE_ETL_SERVER"), "<memory>", new TestAuthorizationConfig()); assertEquals("", logRecorder.getLogContent()); assertEquals(2, capMap.tryGetRoles(CapabilityMapTest.class.getDeclaredMethod("dummyA1"), null) @@ -180,7 +181,7 @@ public class CapabilityMapTest { CapabilityMap capMap = new CapabilityMap(Arrays.asList("A : SPACE_POWER_USER,INSTANCE_ETL_SERVER\t"), - "<memory>"); + "<memory>", new TestAuthorizationConfig()); assertEquals("", logRecorder.getLogContent()); assertEquals(2, capMap.tryGetRoles(CapabilityMapTest.class.getDeclaredMethod("dummyA1"), null) @@ -196,7 +197,7 @@ public class CapabilityMapTest { CapabilityMap capMap = new CapabilityMap(Arrays.asList("A\tSPACE_POWER_USER,INSTANCE_ETL_SERVER; " - + "sample = SPACE_USER, SPACE_ETL_SERVER"), "<memory>"); + + "sample = SPACE_USER, SPACE_ETL_SERVER"), "<memory>", new TestAuthorizationConfig()); assertEquals("", logRecorder.getLogContent()); assertRoles("[INSTANCE_ETL_SERVER, SPACE_POWER_USER]", capMap, "dummyA1", null); @@ -207,7 +208,7 @@ public class CapabilityMapTest public void testOnlyParameterRoles() throws Exception { CapabilityMap capMap = - new CapabilityMap(Arrays.asList("a : sample = SPACE_USER, SPACE_ETL_SERVER"), "<memory>"); + new CapabilityMap(Arrays.asList("a : sample = SPACE_USER, SPACE_ETL_SERVER"), "<memory>", new TestAuthorizationConfig()); assertEquals("", logRecorder.getLogContent()); assertNoRoles(capMap, "dummyA1", null); @@ -220,7 +221,7 @@ public class CapabilityMapTest CapabilityMap capMap = new CapabilityMap(Arrays.asList( "CapabilityMapTest.dummyA: SPACE_POWER_USER #wrong", - "CapabilityMapTest.dummyB NO_ROLE"), "<memory>"); + "CapabilityMapTest.dummyB NO_ROLE"), "<memory>", new TestAuthorizationConfig()); assertEquals("WARN OPERATION.CapabilityMap - Ignoring mal-formed line " + "'CapabilityMapTest.dummyA: SPACE_POWER_USER #wrong' in <memory> " @@ -238,7 +239,7 @@ public class CapabilityMapTest public void testUserRoleDisabled() throws SecurityException, NoSuchMethodException { CapabilityMap capMap = - new CapabilityMap(Arrays.asList("A: INSTANCE_DISABLED\t"), "<memory>"); + new CapabilityMap(Arrays.asList("A: INSTANCE_DISABLED\t"), "<memory>", new TestAuthorizationConfig()); assertEquals("", logRecorder.getLogContent()); assertEquals( @@ -246,7 +247,7 @@ public class CapabilityMapTest capMap.tryGetRoles(CapabilityMapTest.class.getDeclaredMethod("dummyA1"), null).toArray()[0]); assertTrue(capMap.tryGetRoles(CapabilityMapTest.class.getDeclaredMethod("dummyA1"), null) .toArray(new RoleWithHierarchy[0])[0] - .getRoles().isEmpty()); + .getRoles().isEmpty()); } private void assertRoles(String expectedRoles, CapabilityMap capMap, String methodName, @@ -267,4 +268,15 @@ public class CapabilityMapTest assertEquals(null, roles); } + private static class TestAuthorizationConfig implements IAuthorizationConfig + { + + @Override + public boolean isProjectLevelEnabled() + { + return false; + } + + } + } diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/authorization/DefaultAccessControllerTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/authorization/DefaultAccessControllerTest.java index e4d24abc7a8..6ba41054fd1 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/authorization/DefaultAccessControllerTest.java +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/authorization/DefaultAccessControllerTest.java @@ -52,6 +52,7 @@ import ch.systemsx.cisd.openbis.generic.server.authorization.annotation.RolesAll import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.IPredicate; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IProjectDAO; +import ch.systemsx.cisd.openbis.generic.shared.authorization.IAuthorizationConfig; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy.RoleCode; import ch.systemsx.cisd.openbis.generic.shared.dto.IAuthSession; @@ -78,6 +79,8 @@ public final class DefaultAccessControllerTest private IProjectDAO projectDAO; + private IAuthorizationConfig authorizationConfig; + private ProjectPE project; @BeforeTest @@ -105,13 +108,17 @@ public final class DefaultAccessControllerTest context = new Mockery(); daoFactory = context.mock(IDAOFactory.class); projectDAO = context.mock(IProjectDAO.class); + authorizationConfig = context.mock(IAuthorizationConfig.class); project = new ProjectPE(); project.setCode("TEST"); project.setSpace(new SpacePEBuilder().code("TEST").getSpace()); - accessController = new DefaultAccessController(daoFactory); + context.checking(new Expectations() { { + allowing(daoFactory).getAuthorizationConfig(); + will(returnValue(authorizationConfig)); + allowing(daoFactory).getProjectDAO(); will(returnValue(projectDAO)); @@ -119,6 +126,8 @@ public final class DefaultAccessControllerTest will(returnValue(project)); } }); + + accessController = new DefaultAccessController(daoFactory); } @AfterMethod @@ -406,8 +415,7 @@ public final class DefaultAccessControllerTest @Capability("MY_CAP") public void myMethodWithOtherRolesOverridden(); - @RolesAllowed( - { RoleWithHierarchy.SPACE_ETL_SERVER, RoleWithHierarchy.SPACE_OBSERVER }) + @RolesAllowed({ RoleWithHierarchy.SPACE_ETL_SERVER, RoleWithHierarchy.SPACE_OBSERVER }) public void myMethodWithTwoRoles(); @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER) @@ -420,27 +428,26 @@ public final class DefaultAccessControllerTest @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER) public void myMethodWithGardedArgumentWithDifferentRoles(String sessionToken, - @AuthorizationGuard(guardClass = MockPredicate.class, - rolesAllowed = { RoleWithHierarchy.SPACE_ETL_SERVER }) String argument1); + @AuthorizationGuard(guardClass = MockPredicate.class, rolesAllowed = { RoleWithHierarchy.SPACE_ETL_SERVER }) String argument1); @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER) @Capability("MY_CAP") public void myMethodWithGardedArgumentWithRolesOverridden(String sessionToken, - @AuthorizationGuard(name = "ARG1", guardClass = MockPredicate.class, - rolesAllowed = { RoleWithHierarchy.SPACE_ETL_SERVER }) String argument1); + @AuthorizationGuard(name = "ARG1", guardClass = MockPredicate.class, rolesAllowed = { + RoleWithHierarchy.SPACE_ETL_SERVER }) String argument1); @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER) @Capability("MY_CAP2") public void myMethodWithGardedArgumentWithRolesOverridden2(String sessionToken, - @AuthorizationGuard(name = "ARG1", guardClass = MockPredicate.class, - rolesAllowed = { RoleWithHierarchy.SPACE_ETL_SERVER }) String argument1); + @AuthorizationGuard(name = "ARG1", guardClass = MockPredicate.class, rolesAllowed = { + RoleWithHierarchy.SPACE_ETL_SERVER }) String argument1); @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER) public void myMethodWithGardedArgumentWithRolesOverridden3(String sessionToken, - @AuthorizationGuard(name = "ARG1", guardClass = MockPredicate.class, - rolesAllowed = { RoleWithHierarchy.SPACE_POWER_USER }) String argument1, - @AuthorizationGuard(name = "ARG2", guardClass = MockPredicate.class, - rolesAllowed = { RoleWithHierarchy.SPACE_USER }) String argument2); + @AuthorizationGuard(name = "ARG1", guardClass = MockPredicate.class, rolesAllowed = { + RoleWithHierarchy.SPACE_POWER_USER }) String argument1, + @AuthorizationGuard(name = "ARG2", guardClass = MockPredicate.class, rolesAllowed = { + RoleWithHierarchy.SPACE_USER }) String argument2); } /** diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/RoleWithHierarchyTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/RoleWithHierarchyTest.java index 4704b1b6f28..19d96a3e948 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/RoleWithHierarchyTest.java +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/RoleWithHierarchyTest.java @@ -16,9 +16,15 @@ package ch.systemsx.cisd.openbis.generic.shared.basic.dto; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + import org.testng.AssertJUnit; import org.testng.annotations.Test; +import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy.*; + import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy.RoleCode; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy.RoleLevel; @@ -57,14 +63,42 @@ public class RoleWithHierarchyTest extends AssertJUnit RoleWithHierarchy.valueOf(RoleLevel.INSTANCE, RoleCode.OBSERVER)); assertEquals(RoleWithHierarchy.SPACE_ADMIN, RoleWithHierarchy.valueOf(RoleLevel.SPACE, RoleCode.ADMIN)); + assertEquals(RoleWithHierarchy.PROJECT_ADMIN, + RoleWithHierarchy.valueOf(RoleLevel.PROJECT, RoleCode.ADMIN)); + } + + @Test + public void testGetRoles() throws Exception + { + assertRoles(RoleWithHierarchy.INSTANCE_ADMIN.getRoles(), INSTANCE_ADMIN); + assertRoles(RoleWithHierarchy.INSTANCE_OBSERVER.getRoles(), INSTANCE_ADMIN, INSTANCE_OBSERVER); + + assertRoles(RoleWithHierarchy.SPACE_ADMIN.getRoles(), INSTANCE_ADMIN, SPACE_ADMIN); + assertRoles(RoleWithHierarchy.SPACE_POWER_USER.getRoles(), INSTANCE_ADMIN, SPACE_ADMIN, SPACE_POWER_USER); + assertRoles(RoleWithHierarchy.SPACE_USER.getRoles(), INSTANCE_ADMIN, SPACE_ADMIN, SPACE_POWER_USER, SPACE_USER); + assertRoles(RoleWithHierarchy.SPACE_OBSERVER.getRoles(), INSTANCE_ADMIN, INSTANCE_OBSERVER, SPACE_ADMIN, SPACE_POWER_USER, SPACE_USER, + SPACE_OBSERVER); + + assertRoles(RoleWithHierarchy.PROJECT_ADMIN.getRoles(), INSTANCE_ADMIN, SPACE_ADMIN, PROJECT_ADMIN); + assertRoles(RoleWithHierarchy.PROJECT_POWER_USER.getRoles(), INSTANCE_ADMIN, SPACE_ADMIN, SPACE_POWER_USER, PROJECT_ADMIN, + PROJECT_POWER_USER); + assertRoles(RoleWithHierarchy.PROJECT_USER.getRoles(), INSTANCE_ADMIN, SPACE_ADMIN, SPACE_POWER_USER, SPACE_USER, PROJECT_ADMIN, + PROJECT_POWER_USER, PROJECT_USER); + assertRoles(RoleWithHierarchy.PROJECT_OBSERVER.getRoles(), INSTANCE_ADMIN, INSTANCE_OBSERVER, SPACE_ADMIN, SPACE_POWER_USER, SPACE_USER, + SPACE_OBSERVER, PROJECT_ADMIN, PROJECT_POWER_USER, PROJECT_USER, PROJECT_OBSERVER); } @Test public void testFigureRoleCode() throws Exception { + assertEquals(RoleCode.USER, RoleWithHierarchy.figureRoleCode("PROJECT_USER", RoleLevel.PROJECT)); + assertEquals(RoleCode.POWER_USER, + RoleWithHierarchy.figureRoleCode("PROJECT_POWER_USER", RoleLevel.PROJECT)); + assertEquals(RoleCode.USER, RoleWithHierarchy.figureRoleCode("SPACE_USER", RoleLevel.SPACE)); assertEquals(RoleCode.POWER_USER, RoleWithHierarchy.figureRoleCode("SPACE_POWER_USER", RoleLevel.SPACE)); + assertEquals(RoleCode.ADMIN, RoleWithHierarchy.figureRoleCode("INSTANCE_ADMIN", RoleLevel.INSTANCE)); } @@ -78,6 +112,7 @@ public class RoleWithHierarchyTest extends AssertJUnit @Test public void testFigureRoleLevel() throws Exception { + assertEquals(RoleLevel.PROJECT, RoleWithHierarchy.figureRoleLevel("PROJECT_USER")); assertEquals(RoleLevel.SPACE, RoleWithHierarchy.figureRoleLevel("SPACE_USER")); assertEquals(RoleLevel.INSTANCE, RoleWithHierarchy.figureRoleLevel("INSTANCE_USER")); } @@ -106,7 +141,13 @@ public class RoleWithHierarchyTest extends AssertJUnit @Test(expectedExceptions = IllegalArgumentException.class) public void testFigureRoleLevelNotMatchingConventionNonexistentLevel() throws Exception { - RoleWithHierarchy.figureRoleLevel("PROJECT_USER"); + RoleWithHierarchy.figureRoleLevel("EXPERIMENT_USER"); + } + + private void assertRoles(Set<RoleWithHierarchy> actualRoles, RoleWithHierarchy... expectedRoles) + { + Set<RoleWithHierarchy> expectedRolesSet = new HashSet<RoleWithHierarchy>(Arrays.asList(expectedRoles)); + assertEquals(expectedRolesSet, actualRoles); } } -- GitLab