diff --git a/.gitignore b/.gitignore
index fb437d4ca8..c770a83d86 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+Makefile
WebAPIConfig/
*application.properties
.idea/
@@ -12,6 +13,7 @@ sandbox/
/nbactions*.xml
*~
.DS_Store
+.factorypath
### Developer's personal properties ###
**/resources/config/application*-dev-*.properties
diff --git a/Makefile b/Makefile
index adb76d0ea7..84b1aaac79 100644
--- a/Makefile
+++ b/Makefile
@@ -1,56 +1,21 @@
compile:
- mvn clean
- mvn compile -Pwebapi-postgresql-laertes
+ mvn clean compile -DskipUnitTests -DskipITtests -s WebAPIConfig/settings.xml -P webapi-postgresql
package: compile
- mvn package -Pwebapi-postgresql-laertes
+ mvn package -DskipUnitTests -DskipITtests -s WebAPIConfig/settings.xml -P webapi-postgresql
-deploy: package
- sudo service tomcat7 stop
- sleep 4
- sudo rm -rf /var/lib/tomcat7/webapps/WebAPI*
- sudo cp -r target/WebAPI.war /var/lib/tomcat7/webapps/
- sudo chown tomcat7 /var/lib/tomcat7/webapps/WebAPI.war
- sudo chgrp tomcat7 /var/lib/tomcat7/webapps/WebAPI.war
- sudo service tomcat7 start
+deploy: package
+ /home/ubuntu/Downloads/apache-tomcat-8.5.84-DEV/bin/shutdown.sh
+ mv /home/ubuntu/Downloads/apache-tomcat-8.5.84-DEV/webapps/WebAPI /mnt/disk1/webapi-dev-tmp/WebAPI-FOLDER-`date +%m%d%H%S`
+ mv /home/ubuntu/Downloads/apache-tomcat-8.5.84-DEV/webapps/WebAPI.war /mnt/disk1/webapi-dev-tmp/WebAPI.war-`date +%m%d%H%S`
+ mv target/WebAPI.war /home/ubuntu/Downloads/apache-tomcat-8.5.84-DEV/webapps/
+ echo "Now run /home/ubuntu/Downloads/apache-tomcat-8.5.84-DEV/bin/startup.sh"
git-push:
- git push myfork master
+ git push
test:
- wget -O tests/test-general-evidence.json "http://localhost:8080/WebAPI/LAERTES_CDM/evidence/752061"
- wget -O tests/test-drug-hoi.json "http://localhost:8080/WebAPI/LAERTES_CDM/evidence/drughoi/752061-374013"
- wget -O tests/test-drug.json "http://localhost:8080/WebAPI/LAERTES_CDM/evidence/drug/752061"
- wget -O tests/test-hoi.json "http://localhost:8080/WebAPI/LAERTES_CDM/evidence/hoi/320073"
- wget -O tests/test-info.json "http://localhost:8080/WebAPI/LAERTES_CDM/evidence/info"
- wget -O tests/test-drug-hoi-eu-spc.json "http://localhost:8080/WebAPI/LAERTES_CDM/evidence/drughoi/904351-4190045"
- wget -O tests/test-drug-hoi-splicer.json "http://localhost:8080/WebAPI/LAERTES_CDM/evidence/drughoi/19133853-195588"
- wget -O tests/test-drug-hoi-faers-counts-and-signals.json "http://localhost:8080/WebAPI/LAERTES_CDM/evidence/drughoi/1154343-433031"
- wget -O tests/test-drug-hoi-pubmed-mesh-cr.json "http://localhost:8080/WebAPI/LAERTES_CDM/evidence/drughoi/1154343-433031"
- wget -O tests/test-drug-hoi-pubmed-mesh-clin-trial.json "http://localhost:8080/WebAPI/LAERTES_CDM/evidence/drughoi/789578-378144"
- wget -O tests/test-drug-hoi-pubmed-mesh-other.json "http://localhost:8080/WebAPI/LAERTES_CDM/evidence/drughoi/19010482-316866"
- wget -O tests/test-drug-hoi-semmed-cr.json "http://localhost:8080/WebAPI/LAERTES_CDM/evidence/drughoi/1112807-441202"
- wget -O tests/test-drug-hoi-semmed-clin-trial.json "http://localhost:8080/WebAPI/LAERTES_CDM/evidence/drughoi/19059744-381591"
- wget -O tests/test-drug-rollup-ingredient.json "http://localhost:8080/WebAPI/LAERTES_CDM/evidence/drugrollup/ingredient/1000632"
- wget -O tests/test-drug-rollup-clin-drug.json "http://localhost:8080/WebAPI/LAERTES_CDM/evidence/drugrollup/clinicaldrug/19074181"
- wget -O tests/test-drug-rollup-branded-drug.json "http://localhost:8080/WebAPI/LAERTES_CDM/evidence/drugrollup/brandeddrug/1000640"
- wget -O tests/test-rdf-evidencesummary.json "http://localhost:8080/WebAPI/LAERTES_CDM/evidence/evidencesummary?conditionID=139900&drugID=1115008&evidenceGroup=Literature"
- wget -O tests/test-rdf-evidencedetails.json "http://localhost:8080/WebAPI/LAERTES_CDM/evidence/evidencedetails?conditionID=24134&drugID=1115008&evidenceType=SPL_SPLICER_ADR"
+ wget -O /tmp/tests/test-drug-rollup-branded-drug.json "http://api.ohdsi.org/WebAPI/CS1/evidence/drugrollup/brandeddrug/1000640"
test-public:
- wget -O tests/test-general-evidence.json "http://api.ohdsi.org/WebAPI/CS1/evidence/1000640"
- wget -O /tmp/tests/test-drug-hoi.json "http://api.ohdsi.org/WebAPI/CS1/evidence/drughoi/1000640-137682"
- wget -O /tmp/tests/test-drug.json "http://api.ohdsi.org/WebAPI/CS1/evidence/drug/1000640"
- wget -O /tmp/tests/test-hoi.json "http://api.ohdsi.org/WebAPI/CS1/evidence/hoi/320073"
- wget -O /tmp/tests/test-info.json "http://api.ohdsi.org/WebAPI/CS1/evidence/info"
- wget -O /tmp/tests/test-drug-hoi-eu-spc.json "http://api.ohdsi.org/WebAPI/CS1/evidence/drughoi/40239056-75053"
- wget -O /tmp/tests/test-drug-hoi-splicer.json "http://api.ohdsi.org/WebAPI/CS1/evidence/drughoi/19133853-195588"
- wget -O /tmp/tests/test-drug-hoi-faers-counts-and-signals.json "http://api.ohdsi.org/WebAPI/CS1/evidence/drughoi/1154343-433031"
- wget -O /tmp/tests/test-drug-hoi-pubmed-mesh-cr.json "http://api.ohdsi.org/WebAPI/CS1/evidence/drughoi/1154343-433031"
- wget -O /tmp/tests/test-drug-hoi-pubmed-mesh-clin-trial.json "http://api.ohdsi.org/WebAPI/CS1/evidence/drughoi/789578-378144"
- wget -O /tmp/tests/test-drug-hoi-pubmed-mesh-other.json "http://api.ohdsi.org/WebAPI/CS1/evidence/drughoi/19010482-316866"
- wget -O /tmp/tests/test-drug-hoi-semmed-cr.json "http://api.ohdsi.org/WebAPI/CS1/evidence/drughoi/1782521-45612000"
- wget -O /tmp/tests/test-drug-hoi-semmed-clin-trial.json "http://api.ohdsi.org/WebAPI/CS1/evidence/drughoi/1303425-45616736"
- wget -O /tmp/tests/test-drug-rollup-ingredient.json "http://api.ohdsi.org/WebAPI/CS1/evidence/drugrollup/ingredient/1000632"
- wget -O /tmp/tests/test-drug-rollup-clin-drug.json "http://api.ohdsi.org/WebAPI/CS1/evidence/drugrollup/clinicaldrug/19074181"
wget -O /tmp/tests/test-drug-rollup-branded-drug.json "http://api.ohdsi.org/WebAPI/CS1/evidence/drugrollup/brandeddrug/1000640"
diff --git a/pom.xml b/pom.xml
index 5f8c9a199b..0bade7f5f7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -192,6 +192,11 @@
true
authDataSource
+
+
+
+ true
+
8080
diff --git a/src/main/java/org/ohdsi/webapi/cohortcharacterization/CcController.java b/src/main/java/org/ohdsi/webapi/cohortcharacterization/CcController.java
index af2aa3a3f3..d32f478a8d 100644
--- a/src/main/java/org/ohdsi/webapi/cohortcharacterization/CcController.java
+++ b/src/main/java/org/ohdsi/webapi/cohortcharacterization/CcController.java
@@ -42,9 +42,11 @@
import org.ohdsi.webapi.versioning.dto.VersionUpdateDTO;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestBody;
import javax.ws.rs.Consumes;
@@ -63,6 +65,7 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.StringWriter;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -151,11 +154,12 @@ public CohortCharacterizationDTO copy(@PathParam("id") final Long id) {
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Page list(@Pagination Pageable pageable) {
- return service.getPage(pageable).map(entity -> {
- CcShortDTO dto = convertCcToShortDto(entity);
- permissionService.fillWriteAccess(entity, dto);
- return dto;
- });
+ return service.getPage(pageable).map(entity -> {
+ CcShortDTO dto = convertCcToShortDto(entity);
+ permissionService.fillWriteAccess(entity, dto);
+ permissionService.fillReadAccess(entity, dto);
+ return dto;
+ });
}
/**
@@ -168,7 +172,12 @@ public Page list(@Pagination Pageable pageable) {
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Page listDesign(@Pagination Pageable pageable) {
- return service.getPageWithLinkedEntities(pageable).map(this::convertCcToDto);
+ return service.getPageWithLinkedEntities(pageable).map(entity -> {
+ CohortCharacterizationDTO dto = convertCcToDto(entity);
+ permissionService.fillWriteAccess(entity, dto);
+ permissionService.fillReadAccess(entity, dto);
+ return dto;
+ });
}
/**
diff --git a/src/main/java/org/ohdsi/webapi/cohortcharacterization/CcServiceImpl.java b/src/main/java/org/ohdsi/webapi/cohortcharacterization/CcServiceImpl.java
index 455a741418..b4ee8849c1 100644
--- a/src/main/java/org/ohdsi/webapi/cohortcharacterization/CcServiceImpl.java
+++ b/src/main/java/org/ohdsi/webapi/cohortcharacterization/CcServiceImpl.java
@@ -133,6 +133,9 @@
import static org.ohdsi.webapi.Constants.Params.JOB_AUTHOR;
import static org.ohdsi.webapi.Constants.Params.JOB_NAME;
import static org.ohdsi.webapi.Constants.Params.SOURCE_ID;
+import org.ohdsi.webapi.security.PermissionService;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.domain.PageImpl;
@Service
@Transactional
@@ -207,7 +210,12 @@ public class CcServiceImpl extends AbstractDaoService implements CcService, Gene
private final GenericConversionService genericConversionService;
private final VocabularyService vocabularyService;
private VersionService versionService;
+
+ private PermissionService permissionService;
+ @Value("#{'${security.defaultGlobalReadPermissions}'.equals(false)}")
+ private boolean defaultGlobalReadPermissions;
+
private final Environment env;
public CcServiceImpl(
@@ -231,6 +239,7 @@ public CcServiceImpl(
final JobInvalidator jobInvalidator,
final VocabularyService vocabularyService,
final VersionService versionService,
+ final PermissionService permissionService,
@Qualifier("conversionService") final GenericConversionService genericConversionService,
Environment env) {
this.repository = ccRepository;
@@ -251,6 +260,7 @@ public CcServiceImpl(
this.eventPublisher = eventPublisher;
this.jobInvalidator = jobInvalidator;
this.vocabularyService = vocabularyService;
+ this.permissionService = permissionService;
this.genericConversionService = genericConversionService;
this.versionService = versionService;
this.env = env;
@@ -531,12 +541,24 @@ public CohortCharacterization findDesignByGenerationId(@CcGenerationId final Lon
@Override
public Page getPageWithLinkedEntities(final Pageable pageable) {
- return repository.findAll(pageable, defaultEntityGraph);
+ return repository.findAll(pageable, defaultEntityGraph);
+
}
@Override
public Page getPage(final Pageable pageable) {
- return repository.findAll(pageable);
+ List ccList = repository.findAll()
+ .stream().filter(!defaultGlobalReadPermissions ? entity -> permissionService.hasReadAccess(entity) : entity -> true)
+ .collect(Collectors.toList());
+ return getPageFromResults(pageable, ccList);
+ }
+
+ private Page getPageFromResults(Pageable pageable, List results) {
+ // Calculate the start and end indices for the current page
+ int startIndex = pageable.getPageNumber() * pageable.getPageSize();
+ int endIndex = Math.min(startIndex + pageable.getPageSize(), results.size());
+
+ return new PageImpl<>(results.subList(startIndex, endIndex), pageable, results.size());
}
@Override
diff --git a/src/main/java/org/ohdsi/webapi/estimation/EstimationController.java b/src/main/java/org/ohdsi/webapi/estimation/EstimationController.java
index 90c7b7fa33..485cc4f58f 100644
--- a/src/main/java/org/ohdsi/webapi/estimation/EstimationController.java
+++ b/src/main/java/org/ohdsi/webapi/estimation/EstimationController.java
@@ -22,6 +22,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.stereotype.Controller;
@@ -70,7 +71,10 @@ public class EstimationController {
private final ScriptExecutionService executionService;
private EstimationChecker checker;
private PermissionService permissionService;
-
+
+ @Value("#{'${security.defaultGlobalReadPermissions}'.equals(false)}")
+ private boolean defaultGlobalReadPermissions;
+
public EstimationController(EstimationService service,
GenericConversionService conversionService,
CommonGenerationSensitiveInfoService sensitiveInfoService,
@@ -97,11 +101,12 @@ public EstimationController(EstimationService service,
@Path("/")
@Produces(MediaType.APPLICATION_JSON)
public List getAnalysisList() {
-
return StreamSupport.stream(service.getAnalysisList().spliterator(), false)
+ .filter(!defaultGlobalReadPermissions ? entity -> permissionService.hasReadAccess(entity) : entity -> true)
.map(analysis -> {
EstimationShortDTO dto = conversionService.convert(analysis, EstimationShortDTO.class);
permissionService.fillWriteAccess(analysis, dto);
+ permissionService.fillReadAccess(analysis, dto);
return dto;
})
.collect(Collectors.toList());
diff --git a/src/main/java/org/ohdsi/webapi/pathway/PathwayController.java b/src/main/java/org/ohdsi/webapi/pathway/PathwayController.java
index 04c50a1434..4d7cd55dc6 100644
--- a/src/main/java/org/ohdsi/webapi/pathway/PathwayController.java
+++ b/src/main/java/org/ohdsi/webapi/pathway/PathwayController.java
@@ -25,8 +25,10 @@
import org.ohdsi.webapi.versioning.dto.VersionDTO;
import org.ohdsi.webapi.versioning.dto.VersionUpdateDTO;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
@@ -34,6 +36,7 @@
import javax.transaction.Transactional;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -156,13 +159,14 @@ public PathwayAnalysisDTO importAnalysis(final PathwayAnalysisExportDTO dto) {
@Consumes(MediaType.APPLICATION_JSON)
@Transactional
public Page list(@Pagination Pageable pageable) {
-
return pathwayService.getPage(pageable).map(pa -> {
PathwayAnalysisDTO dto = conversionService.convert(pa, PathwayAnalysisDTO.class);
permissionService.fillWriteAccess(pa, dto);
+ permissionService.fillReadAccess(pa, dto);
return dto;
});
}
+
/**
* Check that a pathway analysis name exists.
diff --git a/src/main/java/org/ohdsi/webapi/pathway/PathwayServiceImpl.java b/src/main/java/org/ohdsi/webapi/pathway/PathwayServiceImpl.java
index 12eb75f326..ed7fbae428 100644
--- a/src/main/java/org/ohdsi/webapi/pathway/PathwayServiceImpl.java
+++ b/src/main/java/org/ohdsi/webapi/pathway/PathwayServiceImpl.java
@@ -96,6 +96,10 @@
import static org.ohdsi.webapi.Constants.Params.JOB_NAME;
import static org.ohdsi.webapi.Constants.Params.PATHWAY_ANALYSIS_ID;
import static org.ohdsi.webapi.Constants.Params.SOURCE_ID;
+import org.ohdsi.webapi.cohortcharacterization.domain.CohortCharacterizationEntity;
+import org.ohdsi.webapi.security.PermissionService;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.domain.PageImpl;
@Service
@Transactional
@@ -116,6 +120,11 @@ public class PathwayServiceImpl extends AbstractDaoService implements PathwaySer
private final CohortDefinitionService cohortDefinitionService;
private final VersionService versionService;
+ private PermissionService permissionService;
+
+ @Value("#{'${security.defaultGlobalReadPermissions}'.equals(false)}")
+ private boolean defaultGlobalReadPermissions;
+
private final List STEP_COLUMNS = Arrays.asList(new String[]{"step_1", "step_2", "step_3", "step_4", "step_5", "step_6", "step_7", "step_8", "step_9", "step_10"});
private final EntityGraph defaultEntityGraph = EntityUtils.fromAttributePaths(
@@ -142,7 +151,8 @@ public PathwayServiceImpl(
@Qualifier("conversionService") GenericConversionService genericConversionService,
StepBuilderFactory stepBuilderFactory,
CohortDefinitionService cohortDefinitionService,
- VersionService versionService) {
+ VersionService versionService,
+ PermissionService permissionService) {
this.pathwayAnalysisRepository = pathwayAnalysisRepository;
this.pathwayAnalysisGenerationRepository = pathwayAnalysisGenerationRepository;
@@ -159,6 +169,7 @@ public PathwayServiceImpl(
this.stepBuilderFactory = stepBuilderFactory;
this.cohortDefinitionService = cohortDefinitionService;
this.versionService = versionService;
+ this.permissionService = permissionService;
SerializedPathwayAnalysisToPathwayAnalysisConverter.setConversionService(conversionService);
}
@@ -218,8 +229,18 @@ public PathwayAnalysisEntity importAnalysis(PathwayAnalysisEntity toImport) {
@Override
public Page getPage(final Pageable pageable) {
+ List pathwayList = pathwayAnalysisRepository.findAll(defaultEntityGraph)
+ .stream().filter(!defaultGlobalReadPermissions ? entity -> permissionService.hasReadAccess(entity) : entity -> true)
+ .collect(Collectors.toList());
+ return getPageFromResults(pageable, pathwayList);
+ }
+
+ private Page getPageFromResults(Pageable pageable, List results) {
+ // Calculate the start and end indices for the current page
+ int startIndex = pageable.getPageNumber() * pageable.getPageSize();
+ int endIndex = Math.min(startIndex + pageable.getPageSize(), results.size());
- return pathwayAnalysisRepository.findAll(pageable, defaultEntityGraph);
+ return new PageImpl<>(results.subList(startIndex, endIndex), pageable, results.size());
}
@Override
diff --git a/src/main/java/org/ohdsi/webapi/prediction/PredictionController.java b/src/main/java/org/ohdsi/webapi/prediction/PredictionController.java
index 67a35b7b55..bae37c4c12 100644
--- a/src/main/java/org/ohdsi/webapi/prediction/PredictionController.java
+++ b/src/main/java/org/ohdsi/webapi/prediction/PredictionController.java
@@ -21,6 +21,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.stereotype.Controller;
@@ -67,6 +68,9 @@ public class PredictionController {
private PermissionService permissionService;
+ @Value("#{'${security.defaultGlobalReadPermissions}'.equals(false)}")
+ private boolean defaultGlobalReadPermissions;
+
@Autowired
public PredictionController(PredictionService service,
GenericConversionService conversionService,
@@ -94,12 +98,13 @@ public PredictionController(PredictionService service,
@Path("/")
@Produces(MediaType.APPLICATION_JSON)
public List getAnalysisList() {
-
return StreamSupport
.stream(service.getAnalysisList().spliterator(), false)
+ .filter(!defaultGlobalReadPermissions ? entity -> permissionService.hasReadAccess(entity) : entity -> true)
.map(analysis -> {
CommonAnalysisDTO dto = conversionService.convert(analysis, CommonAnalysisDTO.class);
permissionService.fillWriteAccess(analysis, dto);
+ permissionService.fillReadAccess(analysis, dto);
return dto;
})
.collect(Collectors.toList());
@@ -107,11 +112,12 @@ public List getAnalysisList() {
/**
* Check to see if a prediction design exists by name
- *
+ *
* @summary Prediction design exists by name
* @param id The prediction design id
* @param name The prediction design name
- * @return 1 if a prediction design with the given name and id exist in WebAPI and 0 otherwise
+ * @return 1 if a prediction design with the given name and id exist in WebAPI
+ * and 0 otherwise
*/
@GET
@Path("/{id}/exists")
diff --git a/src/main/java/org/ohdsi/webapi/security/PermissionController.java b/src/main/java/org/ohdsi/webapi/security/PermissionController.java
index 7a1bd26c4c..6471b75bbf 100644
--- a/src/main/java/org/ohdsi/webapi/security/PermissionController.java
+++ b/src/main/java/org/ohdsi/webapi/security/PermissionController.java
@@ -83,26 +83,28 @@ public List listAccessesForEntity(@QueryParam("roleSearch") String role
}
/**
- * Get entity role access information
- *
- * @summary Get entity role information
+ * Get roles that have a permission type (READ/WRITE) to entity
+ *
+ * @summary Get roles that have a specific permission (READ/WRITE) for the
+ * entity
* @param entityType The entity type
* @param entityId The entity ID
- * @return The list of roles
- * @throws Exception
+ * @return The list of permissions for the permission type
+ * @throws Exception
*/
@GET
- @Path("/access/{entityType}/{entityId}")
+ @Path("/access/{entityType}/{entityId}/{permType}")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
- public List listAccessesForEntity(
+ public List listAccessesForEntityByPermType(
@PathParam("entityType") EntityType entityType,
- @PathParam("entityId") Integer entityId
+ @PathParam("entityId") Integer entityId,
+ @PathParam("permType") AccessType permType
) throws Exception {
permissionService.checkCommonEntityOwnership(entityType, entityId);
-
- Set permissionTemplates = permissionService.getTemplatesForType(entityType, AccessType.WRITE).keySet();
+ Set permissionTemplates = null;
+ permissionTemplates = permissionService.getTemplatesForType(entityType, permType).keySet();
List permissions = permissionTemplates
.stream()
@@ -114,6 +116,26 @@ public List listAccessesForEntity(
return roles.stream().map(re -> conversionService.convert(re, RoleDTO.class)).collect(Collectors.toList());
}
+ /**
+ * Get roles that have a permission type (READ/WRITE) to entity
+ *
+ * @summary Get roles that have a specific permission (READ/WRITE) for the
+ * entity
+ * @param entityType The entity type
+ * @param entityId The entity ID
+ * @return The list of permissions for the permission type
+ * @throws Exception
+ */
+ @GET
+ @Path("/access/{entityType}/{entityId}")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public List listAccessesForEntity(
+ @PathParam("entityType") EntityType entityType,
+ @PathParam("entityId") Integer entityId
+ ) throws Exception {
+ return listAccessesForEntityByPermType(entityType, entityId, AccessType.WRITE);
+ }
/**
* Grant group of permissions (READ / WRITE / ...) for the specified entity to the given role.
diff --git a/src/main/java/org/ohdsi/webapi/security/PermissionService.java b/src/main/java/org/ohdsi/webapi/security/PermissionService.java
index b3ec2f7e5c..5bb63729d3 100644
--- a/src/main/java/org/ohdsi/webapi/security/PermissionService.java
+++ b/src/main/java/org/ohdsi/webapi/security/PermissionService.java
@@ -136,6 +136,8 @@ public Map getPermissionTemplates(EntityPermissionSchema permiss
switch (accessType) {
case WRITE:
return permissionSchema.getWritePermissions();
+ case READ:
+ return permissionSchema.getReadPermissions();
default:
throw new UnsupportedOperationException();
}
@@ -227,6 +229,25 @@ public List getRolesHavingPermissions(EntityType entityType, Number id)
return roles;
}
+ public List getRolesHavingReadPermissions(EntityType entityType, Number id) {
+ Set permissionTemplates = getTemplatesForType(entityType, AccessType.READ).keySet();
+ preparePermissionCache(entityType, permissionTemplates);
+
+ List permissions = permissionTemplates.stream()
+ .map(pt -> getPermission(pt, id))
+ .collect(Collectors.toList());
+ int fitCount = permissions.size();
+ Map roleMap = permissions.stream()
+ .filter(p -> permissionCache.get().get(entityType).get(p) != null)
+ .flatMap(p -> permissionCache.get().get(entityType).get(p).stream())
+ .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
+ List roles = roleMap.entrySet().stream()
+ .filter(es -> es.getValue() == fitCount)
+ .map(es -> es.getKey())
+ .collect(Collectors.toList());
+ return roles;
+ }
+
public void clearPermissionCache() {
this.permissionCache.set(new ConcurrentHashMap<>());
}
@@ -237,11 +258,40 @@ public boolean hasWriteAccess(CommonEntity entity) {
try {
String login = this.permissionManager.getSubjectName();
UserSimpleAuthorizationInfo authorizationInfo = this.permissionManager.getAuthorizationInfo(login);
- if (!Objects.equals(authorizationInfo.getUserId(), entity.getCreatedBy().getId())) {
+ if (Objects.equals(authorizationInfo.getUserId(), entity.getCreatedBy().getId())) {
+ hasAccess = true; // the role is the one that created the artifact
+ } else {
EntityType entityType = entityPermissionSchemaResolver.getEntityType(entity.getClass());
List roles = getRolesHavingPermissions(entityType, entity.getId());
+ Collection userRoles = authorizationInfo.getRoles();
+ hasAccess = roles.stream()
+ .anyMatch(r -> userRoles.stream()
+ .anyMatch(re -> re.equals(r.getName())));
+ }
+ } catch (Exception e) {
+ logger.error("Error getting user roles and permissions", e);
+ throw new RuntimeException(e);
+ }
+ }
+ return hasAccess;
+ }
+
+
+ public boolean hasReadAccess(CommonEntity entity) {
+ boolean hasAccess = false;
+ if (securityEnabled && entity.getCreatedBy() != null) {
+ try {
+ String login = this.permissionManager.getSubjectName();
+ UserSimpleAuthorizationInfo authorizationInfo = this.permissionManager.getAuthorizationInfo(login);
+ if (Objects.equals(authorizationInfo.getUserId(), entity.getCreatedBy().getId())){
+ hasAccess = true; // the role is the one that created the artifact
+ } else {
+ EntityType entityType = entityPermissionSchemaResolver.getEntityType(entity.getClass());
+
+ List roles = getRolesHavingReadPermissions(entityType, entity.getId());
+
Collection userRoles = authorizationInfo.getRoles();
hasAccess = roles.stream()
.anyMatch(r -> userRoles.stream()
@@ -260,6 +310,12 @@ public void fillWriteAccess(CommonEntity entity, CommonEntityDTO entityDTO) {
entityDTO.setHasWriteAccess(hasWriteAccess(entity));
}
}
+
+ public void fillReadAccess(CommonEntity entity, CommonEntityDTO entityDTO) {
+ if (securityEnabled && entity.getCreatedBy() != null) {
+ entityDTO.setHasReadAccess(hasReadAccess(entity));
+ }
+ }
public boolean isSecurityEnabled() {
return this.securityEnabled;
diff --git a/src/main/java/org/ohdsi/webapi/security/model/CohortCharacterizationPermissionSchema.java b/src/main/java/org/ohdsi/webapi/security/model/CohortCharacterizationPermissionSchema.java
index 7768187da0..f6ea10012a 100644
--- a/src/main/java/org/ohdsi/webapi/security/model/CohortCharacterizationPermissionSchema.java
+++ b/src/main/java/org/ohdsi/webapi/security/model/CohortCharacterizationPermissionSchema.java
@@ -13,8 +13,19 @@ public class CohortCharacterizationPermissionSchema extends EntityPermissionSche
put("cohort-characterization:%s:delete", "Delete Cohort Characterization with ID = %s");
}};
+ private static Map readPermissions = new HashMap() {{
+ put("cohort-characterization:%s:get", "Get cohort characterization");
+ put("cohort-characterization:%s:generation:get", "Get cohort characterization generations");
+ put("cohort-characterization:generation:*:get", "Get cohort characterization generation");
+ put("cohort-characterization:design:get", "cohort-characterization:design:get");
+ put("cohort-characterization:%s:design:get", "Get cohort characterization design");
+ put("cohort-characterization:design:%s:get", "view cohort characterization with id %s");
+ put("cohort-characterization:%s:version:get", "Get list of characterization versions");
+ put("cohort-characterization:%s:version:*:get", "Get list of characterization version");
+ }};
+
public CohortCharacterizationPermissionSchema() {
- super(EntityType.COHORT_CHARACTERIZATION, new HashMap<>(), writePermissions);
+ super(EntityType.COHORT_CHARACTERIZATION, readPermissions, writePermissions);
}
}
diff --git a/src/main/java/org/ohdsi/webapi/security/model/CohortDefinitionPermissionSchema.java b/src/main/java/org/ohdsi/webapi/security/model/CohortDefinitionPermissionSchema.java
index 5c7f87c50a..bb6781ae0a 100644
--- a/src/main/java/org/ohdsi/webapi/security/model/CohortDefinitionPermissionSchema.java
+++ b/src/main/java/org/ohdsi/webapi/security/model/CohortDefinitionPermissionSchema.java
@@ -14,8 +14,17 @@ public class CohortDefinitionPermissionSchema extends EntityPermissionSchema {
put("cohortdefinition:%s:check:post", "Fix Cohort Definition with ID = %s");
}};
+ private static Map readPermissions = new HashMap() {{
+ put("cohortdefinition:%s:get", "Get Cohort Definition by ID");
+ put("cohortdefinition:%s:info:get","");
+
+ put("cohortdefinition:%s:version:get", "Get list of cohort versions");
+ put("cohortdefinition:%s:version:*:get", "Get cohort version");
+ }
+ };
+
public CohortDefinitionPermissionSchema() {
- super(EntityType.COHORT_DEFINITION, new HashMap<>(), writePermissions);
+ super(EntityType.COHORT_DEFINITION, readPermissions, writePermissions);
}
}
diff --git a/src/main/java/org/ohdsi/webapi/security/model/ConceptSetPermissionSchema.java b/src/main/java/org/ohdsi/webapi/security/model/ConceptSetPermissionSchema.java
index 846cbc9b0c..66b4b1a4b2 100644
--- a/src/main/java/org/ohdsi/webapi/security/model/ConceptSetPermissionSchema.java
+++ b/src/main/java/org/ohdsi/webapi/security/model/ConceptSetPermissionSchema.java
@@ -14,8 +14,14 @@ public class ConceptSetPermissionSchema extends EntityPermissionSchema {
put("conceptset:%s:delete", "Delete Concept Set with ID = %s");
}};
+ private static Map readPermissions = new HashMap() {{
+ put("conceptset:%s:get", "view conceptset definition with id %s");
+ put("conceptset:%s:expression:get", "Resolve concept set %s expression");
+ put("conceptset:%s:version:*:expression:get", "Get expression for concept set %s items for default source");
+ }};
+
public ConceptSetPermissionSchema() {
- super(EntityType.CONCEPT_SET, new HashMap<>(), writePermissions);
+ super(EntityType.CONCEPT_SET, readPermissions, writePermissions);
}
}
diff --git a/src/main/java/org/ohdsi/webapi/security/model/EstimationPermissionSchema.java b/src/main/java/org/ohdsi/webapi/security/model/EstimationPermissionSchema.java
index 416b049fa6..0df160ee52 100644
--- a/src/main/java/org/ohdsi/webapi/security/model/EstimationPermissionSchema.java
+++ b/src/main/java/org/ohdsi/webapi/security/model/EstimationPermissionSchema.java
@@ -13,8 +13,19 @@ public class EstimationPermissionSchema extends EntityPermissionSchema {
put("estimation:%s:delete", "Delete Estimation with ID=%s");
}};
- public EstimationPermissionSchema() {
+ private static Map readPermissions = new HashMap() {{
+ put("estimation:%s:get", "Get Estimation instance");
+ put("estimation:%s:generation:get", "View Estimation Generations");
+ put("estimation:%s:copy:get", "Copy Estimation instance");
+ put("estimation:%s:download:get", "Download Estimation package");
+ put("estimation:%s:export:get", "Export Estimation");
+ put("estimation:%s:generation:get", "View Estimation Generations");
+ put("comparativecohortanalysis:%s:get","Get estimation");
+ }
+ };
- super(EntityType.ESTIMATION, new HashMap<>(), writePermissions);
+
+ public EstimationPermissionSchema() {
+ super(EntityType.ESTIMATION, readPermissions, writePermissions);
}
}
diff --git a/src/main/java/org/ohdsi/webapi/security/model/FeatureAnalysisPermissionSchema.java b/src/main/java/org/ohdsi/webapi/security/model/FeatureAnalysisPermissionSchema.java
index 0090a45b3b..b36ea20b64 100644
--- a/src/main/java/org/ohdsi/webapi/security/model/FeatureAnalysisPermissionSchema.java
+++ b/src/main/java/org/ohdsi/webapi/security/model/FeatureAnalysisPermissionSchema.java
@@ -13,8 +13,14 @@ public class FeatureAnalysisPermissionSchema extends EntityPermissionSchema {
put("feature-analysis:%s:delete", "Delete Feature Analysis with ID = %s");
}};
+ private static Map readPermissions = new HashMap() {{
+ put("feature-analysis:%s:get", "get feature analysis");
+ put("feature-analysis:aggregates:get", "feature-analysis:aggregates:get");
+ }
+ };
+
public FeatureAnalysisPermissionSchema() {
- super(EntityType.FE_ANALYSIS, new HashMap<>(), writePermissions);
+ super(EntityType.FE_ANALYSIS, readPermissions, writePermissions);
}
}
diff --git a/src/main/java/org/ohdsi/webapi/security/model/IncidenceRatePermissionSchema.java b/src/main/java/org/ohdsi/webapi/security/model/IncidenceRatePermissionSchema.java
index 1c336a3ff2..57441e5edf 100644
--- a/src/main/java/org/ohdsi/webapi/security/model/IncidenceRatePermissionSchema.java
+++ b/src/main/java/org/ohdsi/webapi/security/model/IncidenceRatePermissionSchema.java
@@ -15,8 +15,18 @@ public class IncidenceRatePermissionSchema extends EntityPermissionSchema {
put("ir:%s:delete", "Delete Incidence Rate with ID=%s");
}};
+ private static Map readPermissions = new HashMap() {{
+ put("ir:%s:get", "view list of incident rates");
+ put("ir:%s:version:get", "Get list of IR analsis versions");
+ put("ir:%s:version:*:get", "Get IR analysis version");
+ put("ir:%s:copy:get","Copy incidence rate");
+ put("ir:%s:info:get","Get IR info");
+ put("ir:%s:design:get","Export Incidence Rates design");
+ }
+ };
+
public IncidenceRatePermissionSchema() {
- super(EntityType.INCIDENCE_RATE, new HashMap<>(), writePermissions);
+ super(EntityType.INCIDENCE_RATE, readPermissions, writePermissions);
}
}
diff --git a/src/main/java/org/ohdsi/webapi/security/model/PathwayAnalysisPermissionSchema.java b/src/main/java/org/ohdsi/webapi/security/model/PathwayAnalysisPermissionSchema.java
index 6c19b76c09..2f6f30ec63 100644
--- a/src/main/java/org/ohdsi/webapi/security/model/PathwayAnalysisPermissionSchema.java
+++ b/src/main/java/org/ohdsi/webapi/security/model/PathwayAnalysisPermissionSchema.java
@@ -14,8 +14,19 @@ public class PathwayAnalysisPermissionSchema extends EntityPermissionSchema {
put("pathway-analysis:%s:delete", "Delete Pathway Analysis with ID = %s");
}};
+ private static Map readPermissions = new HashMap() {{
+ put("pathway-analysis:%s:get", "Get Pathways Analysis instance");
+ put("pathway-analysis:%s:generation:get", "Get Pathways Analysis generations list");
+ put("pathway-analysis:generation:*:get", "Get Pathways Analysis generation instance");
+ put("pathway-analysis:generation:*:result:get", "Get Pathways Analysis generation results");
+ put("pathway-analysis:generation:*:design:get", "Get Pathways Analysis generation design");
+ put("pathway-analysis:%s:version:get", "Get list of pathway analysis versions");
+ put("pathway-analysis:%s:version:*:get", "Get pathway analysis version");
+ }
+ };
+
public PathwayAnalysisPermissionSchema() {
- super(EntityType.PATHWAY_ANALYSIS, new HashMap<>(), writePermissions);
+ super(EntityType.PATHWAY_ANALYSIS, readPermissions, writePermissions);
}
}
diff --git a/src/main/java/org/ohdsi/webapi/security/model/PredictionPermissionSchema.java b/src/main/java/org/ohdsi/webapi/security/model/PredictionPermissionSchema.java
index ad34f12425..d2e3cc458d 100644
--- a/src/main/java/org/ohdsi/webapi/security/model/PredictionPermissionSchema.java
+++ b/src/main/java/org/ohdsi/webapi/security/model/PredictionPermissionSchema.java
@@ -13,8 +13,19 @@ public class PredictionPermissionSchema extends EntityPermissionSchema {
put("prediction:%s:delete", "Delete Estimation with ID=%s");
}};
+ private static Map readPermissions = new HashMap() {{
+ put("prediction:%s:get", "Get Prediction instance");
+ put("prediction:%s:copy:get", "Copy Prediction instance");
+ put("prediction:%s:download:get", "Download Prediction package");
+ put("prediction:%s:export:get", "Export Prediction");
+ put("prediction:%s:generation:get", "View Prediction Generations");
+ put("prediction:%s:exists:get", "Check name uniqueness of prediction");
+ put("plp:%s:get", "Get population level prediction");
+ }
+ };
+
public PredictionPermissionSchema() {
- super(EntityType.PREDICTION, new HashMap<>(), writePermissions);
+ super(EntityType.PREDICTION, readPermissions, writePermissions);
}
}
diff --git a/src/main/java/org/ohdsi/webapi/security/model/ReusablePermissionSchema.java b/src/main/java/org/ohdsi/webapi/security/model/ReusablePermissionSchema.java
index 78803dc01e..6ee5a940a6 100644
--- a/src/main/java/org/ohdsi/webapi/security/model/ReusablePermissionSchema.java
+++ b/src/main/java/org/ohdsi/webapi/security/model/ReusablePermissionSchema.java
@@ -13,6 +13,13 @@ public class ReusablePermissionSchema extends EntityPermissionSchema {
put("reusable:%s:put", "Update reusable");
}};
+ private static Map readPermissions = new HashMap() {{
+ put("reusable:%s:get", "view reusable with id %s");
+ put("reusable:%s:expression:get", "Resolve reusable %s expression");
+ put("reusable:%s:version:*:get", "Get expression for reusable %s items for default source");
+ }
+ };
+
public ReusablePermissionSchema() {
super(EntityType.REUSABLE, new HashMap<>(), writePermissions);
diff --git a/src/main/java/org/ohdsi/webapi/security/model/TagPermissionSchema.java b/src/main/java/org/ohdsi/webapi/security/model/TagPermissionSchema.java
index e68747570b..58476a4fe9 100644
--- a/src/main/java/org/ohdsi/webapi/security/model/TagPermissionSchema.java
+++ b/src/main/java/org/ohdsi/webapi/security/model/TagPermissionSchema.java
@@ -13,6 +13,12 @@ public class TagPermissionSchema extends EntityPermissionSchema {
put("tag:%s:put", "Update tag");
}};
+ private static Map readPermissions = new HashMap() {{
+ put("tag:get", "view tag with id %s");
+ put("tag:search:get", "Resolve tag %s expression");
+ }
+ };
+
public TagPermissionSchema() {
super(EntityType.TAG, new HashMap<>(), writePermissions);
diff --git a/src/main/java/org/ohdsi/webapi/service/CohortDefinitionService.java b/src/main/java/org/ohdsi/webapi/service/CohortDefinitionService.java
index 976389eb54..1c71755070 100644
--- a/src/main/java/org/ohdsi/webapi/service/CohortDefinitionService.java
+++ b/src/main/java/org/ohdsi/webapi/service/CohortDefinitionService.java
@@ -86,6 +86,7 @@
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.job.builder.SimpleJobBuilder;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.core.convert.ConversionService;
import org.springframework.jdbc.core.RowMapper;
@@ -204,6 +205,9 @@ public class CohortDefinitionService extends AbstractDaoService implements HasTa
@Autowired
private VersionService versionService;
+ @Value("#{'${security.defaultGlobalReadPermissions}'.equals(false)}")
+ private boolean defaultGlobalReadPermissions;
+
private final MarkdownRender markdownPF = new MarkdownRender();
private final List extensions = Arrays.asList(TablesExtension.create());
@@ -406,11 +410,12 @@ public GenerateSqlResult generateSql(GenerateSqlRequest request) {
@Transactional
public List getCohortDefinitionList() {
List definitions = cohortDefinitionRepository.list();
-
return definitions.stream()
+ .filter(!defaultGlobalReadPermissions ? entity -> permissionService.hasReadAccess(entity) : entity -> true)
.map(def -> {
CohortMetadataDTO dto = conversionService.convert(def, CohortMetadataImplDTO.class);
permissionService.fillWriteAccess(def, dto);
+ permissionService.fillReadAccess(def, dto);
return dto;
})
.collect(Collectors.toList());
diff --git a/src/main/java/org/ohdsi/webapi/service/ConceptSetService.java b/src/main/java/org/ohdsi/webapi/service/ConceptSetService.java
index 1186a22445..9b4143feea 100644
--- a/src/main/java/org/ohdsi/webapi/service/ConceptSetService.java
+++ b/src/main/java/org/ohdsi/webapi/service/ConceptSetService.java
@@ -58,6 +58,7 @@
import org.ohdsi.webapi.versioning.service.VersionService;
import org.ohdsi.webapi.vocabulary.Concept;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.stereotype.Component;
@@ -103,6 +104,9 @@ public class ConceptSetService extends AbstractDaoService implements HasTags versionService;
+ @Value("#{'${security.defaultGlobalReadPermissions}'.equals(false)}")
+ private boolean defaultGlobalReadPermissions;
+
public static final String COPY_NAME = "copyName";
/**
@@ -131,15 +135,17 @@ public ConceptSetDTO getConceptSet(@PathParam("id") final int id) {
@Path("/")
@Produces(MediaType.APPLICATION_JSON)
public Collection getConceptSets() {
- return getTransactionTemplate().execute(transactionStatus ->
- StreamSupport.stream(getConceptSetRepository().findAll().spliterator(), false)
+ return getTransactionTemplate().execute(
+ transactionStatus -> StreamSupport.stream(getConceptSetRepository().findAll().spliterator(), false)
+ .filter(!defaultGlobalReadPermissions ? entity -> permissionService.hasReadAccess(entity) : entity -> true)
.map(conceptSet -> {
ConceptSetDTO dto = conversionService.convert(conceptSet, ConceptSetDTO.class);
permissionService.fillWriteAccess(conceptSet, dto);
+ permissionService.fillReadAccess(conceptSet, dto);
return dto;
})
- .collect(Collectors.toList())
- );
+ .collect(Collectors.toList()));
+
}
/**
diff --git a/src/main/java/org/ohdsi/webapi/service/IRAnalysisService.java b/src/main/java/org/ohdsi/webapi/service/IRAnalysisService.java
index ea66cdce4c..32d27257f0 100644
--- a/src/main/java/org/ohdsi/webapi/service/IRAnalysisService.java
+++ b/src/main/java/org/ohdsi/webapi/service/IRAnalysisService.java
@@ -85,6 +85,7 @@
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.job.builder.SimpleJobBuilder;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.convert.ConversionService;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Component;
@@ -141,6 +142,9 @@ public class IRAnalysisService extends AbstractDaoService implements
private final IRAnalysisQueryBuilder queryBuilder;
+ @Value("#{'${security.defaultGlobalReadPermissions}'.equals(false)}")
+ private boolean defaultGlobalReadPermissions;
+
@Autowired
private IncidenceRateAnalysisRepository irAnalysisRepository;
@@ -341,13 +345,14 @@ private String getStrataTreemapData(int analysisId, int targetId, int outcomeId,
@Override
public List getIRAnalysisList() {
-
return getTransactionTemplate().execute(transactionStatus -> {
Iterable analysisList = this.irAnalysisRepository.findAll();
return StreamSupport.stream(analysisList.spliterator(), false)
+ .filter(!defaultGlobalReadPermissions ? entity -> permissionService.hasReadAccess(entity) : entity -> true)
.map(analysis -> {
IRAnalysisShortDTO dto = conversionService.convert(analysis, IRAnalysisShortDTO.class);
permissionService.fillWriteAccess(analysis, dto);
+ permissionService.fillReadAccess(analysis, dto);
return dto;
})
.collect(Collectors.toList());
diff --git a/src/main/java/org/ohdsi/webapi/service/dto/CommonEntityDTO.java b/src/main/java/org/ohdsi/webapi/service/dto/CommonEntityDTO.java
index 5a33780593..287894aef9 100644
--- a/src/main/java/org/ohdsi/webapi/service/dto/CommonEntityDTO.java
+++ b/src/main/java/org/ohdsi/webapi/service/dto/CommonEntityDTO.java
@@ -17,7 +17,9 @@ public abstract class CommonEntityDTO implements CommonDTO {
private Date createdDate;
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
private Date modifiedDate;
+
private boolean hasWriteAccess;
+ private boolean hasReadAccess;
public UserDTO getCreatedBy() {
return createdBy;
@@ -58,4 +60,12 @@ public boolean isHasWriteAccess() {
public void setHasWriteAccess(boolean hasWriteAccess) {
this.hasWriteAccess = hasWriteAccess;
}
+
+ public boolean isHasReadAccess() {
+ return hasReadAccess;
+ }
+
+ public void setHasReadAccess(boolean hasReadAccess) {
+ this.hasReadAccess = hasReadAccess;
+ }
}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index cbc3823116..cd1afb2013 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -107,6 +107,7 @@ csrf.disable=true
sparql.endpoint=http://virtuoso.ohdsi.org:8890/sparql?default-graph-uri=&query=
+security.defaultGlobalReadPermissions=${security.defaultGlobalReadPermissions}
security.provider=${security.provider}
security.cors.enabled=${security.cors.enabled}
security.token.expiration=${security.token.expiration}