diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a8b686f57c..6050cfe6c4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,9 @@ changes in the following format: PR #1234*** #### Features - Added new interface intended to be used for querying module data from PHP (PR #8215) - Added the NOT NULL constraint on Project Name (PR #8295) +- Migrated instrument permissions from config.xml to database and added the ability + to manage instrument permissions in the frontend from the `instrument_manager` + module. (PR #8302) #### Updates and Improvements - Rename subproject to Cohort (PR #7817) diff --git a/Makefile b/Makefile index a7f0dc14533..658abc7e79c 100755 --- a/Makefile +++ b/Makefile @@ -52,8 +52,12 @@ check: checkstatic unittests testdata: php tools/raisinbread_refresh.php +instrument_manager: + target=instrument_manager npm run compile + login: target=login npm run compile mri_violations: target=mri_violations npm run compile + diff --git a/SQL/0000-00-02-Permission.sql b/SQL/0000-00-02-Permission.sql index c7ed19b6f5f..8ebca54b267 100644 --- a/SQL/0000-00-02-Permission.sql +++ b/SQL/0000-00-02-Permission.sql @@ -152,3 +152,11 @@ CREATE TABLE `notification_modules_perm_rel` ( INSERT INTO notification_modules_perm_rel SELECT nm.id, p.permID FROM notification_modules nm JOIN permissions p WHERE nm.module_name='media' AND (p.code='media_write' OR p.code='media_read'); INSERT INTO notification_modules_perm_rel SELECT nm.id, p.permID FROM notification_modules nm JOIN permissions p WHERE nm.module_name='document_repository' AND (p.code='document_repository_view' OR p.code='document_repository_delete'); INSERT INTO notification_modules_perm_rel SELECT nm.id, p.permID FROM notification_modules nm JOIN permissions p WHERE nm.module_name='publication' AND (p.code='publication_view' OR p.code='publication_propose' OR p.code='publication_approve'); + +CREATE TABLE `testnames_permissions_rel` ( + `TestID` int(10) unsigned NOT NULL, + `permID` int(10) unsigned NOT NULL, + PRIMARY KEY (`TestID`,`permID`), + CONSTRAINT `FK_testnames_permissions_rel_test` FOREIGN KEY (`TestID`) REFERENCES `test_names` (`ID`), + CONSTRAINT `FK_testnames_permissions_rel_perm` FOREIGN KEY (`permID`) REFERENCES `permissions` (`permID`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/SQL/New_patches/2022-12-20-instrumentpermissions.sql b/SQL/New_patches/2022-12-20-instrumentpermissions.sql new file mode 100644 index 00000000000..27a127c8a64 --- /dev/null +++ b/SQL/New_patches/2022-12-20-instrumentpermissions.sql @@ -0,0 +1,7 @@ +CREATE TABLE `testnames_permissions_rel` ( + `TestID` int(10) unsigned NOT NULL, + `permID` int(10) unsigned NOT NULL, + PRIMARY KEY (`TestID`,`permID`), + CONSTRAINT `FK_testnames_permissions_rel_test` FOREIGN KEY (`TestID`) REFERENCES `test_names` (`ID`), + CONSTRAINT `FK_testnames_permissions_rel_perm` FOREIGN KEY (`permID`) REFERENCES `permissions` (`permID`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/docs/config/config.xml b/docs/config/config.xml index 7f9e4cf5277..476e47501f6 100644 --- a/docs/config/config.xml +++ b/docs/config/config.xml @@ -70,33 +70,6 @@ Instrument Display Name - - - - - - false - - - - sampleInstrument - - sampleInstrumentPermissionName - - - sampleInstrument2 - sampleInstrument2PermissionName - - - diff --git a/modules/instrument_manager/jsx/instrumentManagerIndex.js b/modules/instrument_manager/jsx/instrumentManagerIndex.js index a9ff5b373ef..78fdecb74b2 100644 --- a/modules/instrument_manager/jsx/instrumentManagerIndex.js +++ b/modules/instrument_manager/jsx/instrumentManagerIndex.js @@ -8,6 +8,12 @@ import FilterableDataTable from 'FilterableDataTable'; import InstrumentUploadForm from './uploadForm'; +import Modal from 'jsx/Modal'; +import InfoPanel from 'jsx/InfoPanel'; + +import Select from 'react-select'; +import swal from 'sweetalert2'; + /** * Instrument Manager Index component */ @@ -23,6 +29,7 @@ class InstrumentManagerIndex extends Component { data: {}, error: false, isLoaded: false, + modifyPermissions: false, }; this.fetchData = this.fetchData.bind(this); @@ -62,6 +69,40 @@ class InstrumentManagerIndex extends Component { * @return {*} a formated table cell for a given column */ formatColumn(column, cell, row) { + if (column == 'Permission Required') { + const clickHandler = (row) => { + return () => { + this.setState({ + 'modifyPermissions': { + 'instrument': row.Instrument, + 'permissions': row['Permission Required'], + }, + }); + }; + }; + if (cell == null) { + if (this.props.hasPermission('instrument_manager_write')) { + return (No Permissions enforced. + + ); + } else { + return No Permissions enforced.; + } + } + if (this.props.hasPermission('instrument_manager_write')) { + return ({cell.join(',')} + + ); + } else { + return {cell.join(',')}; + } + } return ( {cell} ); @@ -114,12 +155,82 @@ class InstrumentManagerIndex extends Component { name: 'pagesValid', type: 'text', }}, + {label: 'Permission Required', show: true, filter: { + name: 'permissionsRequired', + type: 'text', + }}, ]; const tabs = [ {id: 'browse', label: 'Browse'}, ]; + let permsModal = null; + if (this.state.modifyPermissions !== false) { + const submitPromise = () => { + return new Promise( + (resolve, reject) => { + fetch( + this.props.BaseURL + '/instrument_manager/permissions', + { + method: 'POST', + body: JSON.stringify(this.state.modifyPermissions), + }).then((response) => { + if (!response.ok) { + console.error(response.status); + throw new Error('Could not modify permissions'); + } + return response.json(); + }).then( (data) => { + resolve(); + this.fetchData(); + }).catch((message) => { + swal.fire({ + title: 'Oops..', + text: 'Something went wrong!', + type: 'error', + }); + reject(); + }); + }); + }; + + permsModal = ( { + this.setState({'modifyPermissions': false}); + } + }> +

Select the permissions required for accessing  + {this.state.modifyPermissions.instrument} in the dropdown below. +

+

Any user accessing the instrument (either for viewing the data + or data entry) must have one of the access permissions selected. +

+ + A user with any of the selected permissions will + be able to access  + {this.state.modifyPermissions.instrument}. + If no permissions are selected, the default LORIS permissions + will be enforced for this instrument. + + + { + let modifyPermissions = {...this.state.modifyPermissions}; + modifyPermissions.permissions = newselected; + this.setState({modifyPermissions}); + }} + /> +
); + } if (this.props.hasPermission('instrument_manager_write')) { tabs.push({id: 'upload', label: 'Upload'}); } @@ -165,6 +276,7 @@ class InstrumentManagerIndex extends Component { return ( + {permsModal} { + return {value: val, label: val}; + }); + const values = options.filter((row) => { + if (props.selected == null) { + // nothing selected, filter everything + return false; + } + return props.selected.includes(row.value); + }); + return