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 66b4b1a4b..73b8ed89c 100644 --- a/src/main/java/org/ohdsi/webapi/security/model/ConceptSetPermissionSchema.java +++ b/src/main/java/org/ohdsi/webapi/security/model/ConceptSetPermissionSchema.java @@ -18,6 +18,9 @@ public class ConceptSetPermissionSchema extends EntityPermissionSchema { 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"); + put("conceptset:%s:expression:*:get", "expression:*:get permission, specific to this conceptset with id %s"); + put("conceptset:%s:version:get", "version:get permission, specific to this conceptset with id %s"); + put("conceptset:%s:copy-name:get", "copy-name:get permission, specific to this conceptset with id %s"); }}; public ConceptSetPermissionSchema() { diff --git a/src/main/resources/db/migration/postgresql/V2.15.0.20240621210500__custom_ctds_more_restricted_read_restricted_role.sql b/src/main/resources/db/migration/postgresql/V2.15.0.20240621210500__custom_ctds_more_restricted_read_restricted_role.sql index 89262be3e..240ebbf00 100644 --- a/src/main/resources/db/migration/postgresql/V2.15.0.20240621210500__custom_ctds_more_restricted_read_restricted_role.sql +++ b/src/main/resources/db/migration/postgresql/V2.15.0.20240621210500__custom_ctds_more_restricted_read_restricted_role.sql @@ -205,3 +205,8 @@ from join ${ohdsiSchema}.sec_permission on concat('cohortdefinition:', COHORT_DEFINITION_SEC_ROLE.cohort_definition_id, ':copy:get') = sec_permission.value ON CONFLICT (role_id, permission_id) DO NOTHING; + + +-- CTDS/"team project" feature specific - keep only "admin" role assignment... i.e. remove all other +-- role assignments for all users: +DELETE from ${ohdsiSchema}.sec_user_role where role_id != 2; -- role 2 is the standard "admin" role diff --git a/src/main/resources/db/migration/postgresql/V2.15.0.20240801170500__custom_ctds_more_restricted_read_restricted_role_part2.sql b/src/main/resources/db/migration/postgresql/V2.15.0.20240801170500__custom_ctds_more_restricted_read_restricted_role_part2.sql new file mode 100644 index 000000000..b562fd57d --- /dev/null +++ b/src/main/resources/db/migration/postgresql/V2.15.0.20240801170500__custom_ctds_more_restricted_read_restricted_role_part2.sql @@ -0,0 +1,100 @@ +-- Delete set of too broad conceptset permissions from role 15: +DELETE from ${ohdsiSchema}.sec_role_permission srp +where srp.role_id = 15 AND srp.permission_id in +( + Select sp.id from ${ohdsiSchema}.sec_permission sp + where sp.value IN + ( + 'conceptset:*:expression:*:get', -- taken over from role 10...This one was too broad + 'conceptset:*:version:get', -- taken over from role 10...This one was too broad + 'conceptset:*:copy-name:get' -- taken over from role 10...This one was too broad + ) +) +; + + +-- CONCEPT_SET_SEC_ROLE is our custom view that returns a list of conceptset ids per role +-- as long as that role has a permission starting with "conceptset:"" for that id. E.g. : +-- concept_set_id | sec_role_name +-- ----------------------+------------------------- +-- 1 | /gwas_projects/project2 +-- 2 | /gwas_projects/project2 +-- 30 | /gwas_projects/project1 + +DROP VIEW IF EXISTS ${ohdsiSchema}.CONCEPT_SET_SEC_ROLE; +CREATE VIEW ${ohdsiSchema}.CONCEPT_SET_SEC_ROLE AS + select + distinct cast(regexp_replace(sec_permission.value, + '^conceptset:([0-9]+):.*','\1') as integer) as concept_set_id, + sec_role.name as sec_role_name + from + ${ohdsiSchema}.sec_role + inner join ${ohdsiSchema}.sec_role_permission on sec_role.id = sec_role_permission.role_id + inner join ${ohdsiSchema}.sec_permission on sec_role_permission.permission_id = sec_permission.id + where + sec_permission.value ~ 'conceptset:[0-9]+' +; + +-- Below we create new "expression:*:get", "version:get", "copy-name:get" permissions specific to each conceptset (step 1), and +-- then tie these new permissions to the right role, according to the conceptset id vs role name +-- mapping found in CONCEPT_SET_SEC_ROLE (step 2). + +-- step 1. create the sec_permission records: +INSERT INTO ${ohdsiSchema}.sec_permission (value, description) +select + concat('conceptset:', concept_set_id, ':expression:*:get'), + 'expression:*:get permission, specific to this conceptset' +from ${ohdsiSchema}.CONCEPT_SET_SEC_ROLE +ON CONFLICT (value) +DO NOTHING; + +INSERT INTO ${ohdsiSchema}.sec_permission (value, description) +select + concat('conceptset:', concept_set_id, ':version:get'), + 'version:get permission, specific to this conceptset' +from ${ohdsiSchema}.CONCEPT_SET_SEC_ROLE +ON CONFLICT (value) +DO NOTHING; + +INSERT INTO ${ohdsiSchema}.sec_permission (value, description) +select + concat('conceptset:', concept_set_id, ':copy-name:get'), + 'copy-name:get permission, specific to this conceptset' +from ${ohdsiSchema}.CONCEPT_SET_SEC_ROLE +ON CONFLICT (value) +DO NOTHING; + + +-- step 2. insert sec_role_permissions: +INSERT INTO ${ohdsiSchema}.sec_role_permission (role_id, permission_id) +Select + sec_role.id, + sec_permission.id +from + ${ohdsiSchema}.CONCEPT_SET_SEC_ROLE + join ${ohdsiSchema}.sec_role on CONCEPT_SET_SEC_ROLE.sec_role_name = sec_role.name + join ${ohdsiSchema}.sec_permission on concat('conceptset:', CONCEPT_SET_SEC_ROLE.concept_set_id, ':expression:*:get') = sec_permission.value +ON CONFLICT (role_id, permission_id) +DO NOTHING; + +INSERT INTO ${ohdsiSchema}.sec_role_permission (role_id, permission_id) +Select + sec_role.id, + sec_permission.id +from + ${ohdsiSchema}.CONCEPT_SET_SEC_ROLE + join ${ohdsiSchema}.sec_role on CONCEPT_SET_SEC_ROLE.sec_role_name = sec_role.name + join ${ohdsiSchema}.sec_permission on concat('conceptset:', CONCEPT_SET_SEC_ROLE.concept_set_id, ':version:get') = sec_permission.value +ON CONFLICT (role_id, permission_id) +DO NOTHING; + +INSERT INTO ${ohdsiSchema}.sec_role_permission (role_id, permission_id) +Select + sec_role.id, + sec_permission.id +from + ${ohdsiSchema}.CONCEPT_SET_SEC_ROLE + join ${ohdsiSchema}.sec_role on CONCEPT_SET_SEC_ROLE.sec_role_name = sec_role.name + join ${ohdsiSchema}.sec_permission on concat('conceptset:', CONCEPT_SET_SEC_ROLE.concept_set_id, ':copy-name:get') = sec_permission.value +ON CONFLICT (role_id, permission_id) +DO NOTHING;