Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[data_release] Introduce Project Separation #9385

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion SQL/0000-00-00-schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2095,7 +2095,9 @@ CREATE TABLE `data_release` (
`file_name` varchar(255),
`version` varchar(255),
`upload_date` date,
PRIMARY KEY (`id`)
`ProjectID` INT(10) UNSIGNED NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (ProjectID) REFERENCES Project (ProjectID)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `data_release_permissions` (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
ALTER TABLE data_release
ADD COLUMN ProjectID INT(10) UNSIGNED NULL DEFAULT NULL,
ADD CONSTRAINT FK_ProjectID
FOREIGN KEY (ProjectID) REFERENCES Project (ProjectID);
6 changes: 3 additions & 3 deletions modules/data_release/jsx/addPermissionForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,7 @@ class AddPermissionForm extends Component {
* Called by React when the component has been rendered on the page.
*/
componentDidMount() {
this.fetchData()
.then(() => this.setState({isLoaded: true}));
this.fetchData().then(() => this.setState({isLoaded: true}));
}

/**
Expand Down Expand Up @@ -112,6 +111,7 @@ class AddPermissionForm extends Component {
errorMessage={this.state.errorMessage.Filename}
required={false}
value={this.state.formData.data_release_id}
autoSelect={false}
/>
<h4>OR</h4><br/>
<SelectElement
Expand All @@ -124,6 +124,7 @@ class AddPermissionForm extends Component {
errorMessage={this.state.errorMessage.Version}
required={false}
value={this.state.formData.data_release_version}
autoSelect={false}
/>
<ButtonElement label='Add Permission'/>
</FormElement>
Expand Down Expand Up @@ -181,7 +182,6 @@ class AddPermissionForm extends Component {
}).then(function() {
window.location.assign('/data_release');
});
this.props.fetchData();
} else {
let msg = response.statusText ?
response.statusText :
Expand Down
6 changes: 6 additions & 0 deletions modules/data_release/jsx/dataReleaseIndex.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,11 @@ class DataReleaseIndex extends Component {
name: 'uploadDate',
type: 'text',
}},
{label: 'Project Name', show: true, filter: {
name: 'Project',
type: 'select',
options: this.state.data.fieldOptions.projects,
}},
{label: 'Data Release ID', show: false,
},
];
Expand All @@ -178,6 +183,7 @@ class DataReleaseIndex extends Component {
+ '/data_release/files'
}
action={loris.BaseURL + '/data_release/files'}
projects={this.state.data.fieldOptions.projects}
/>
</Modal>
);
Expand Down
108 changes: 82 additions & 26 deletions modules/data_release/jsx/managePermissionsForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
FormElement,
CheckboxElement,
StaticElement,
SearchableDropdown,
} from 'jsx/Form';

/**
Expand All @@ -24,11 +25,13 @@ class ManagePermissionsForm extends Component {

this.state = {
data: {},
originalData: {},
hasError: {},
errorMessage: {},
isLoaded: false,
};

this.setFormData = this.setFormData.bind(this);
this.fetchData = this.fetchData.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
Expand All @@ -49,7 +52,7 @@ class ManagePermissionsForm extends Component {
fetchData() {
return fetch(this.props.DataURL, {credentials: 'same-origin'})
.then((resp) => resp.json())
.then((data) => this.setState({data}))
.then((data) => this.setState({data, originalData: data}))
.catch( (error) => {
this.setState({error: 'An error occurred when loading the form!'});
console.error(error);
Expand Down Expand Up @@ -88,26 +91,73 @@ class ManagePermissionsForm extends Component {
onSubmit={this.handleSubmit}
>
<FormElement name="manage_permissions">
{Object.entries(data).map(([userId, user]) => {
const versions = Object.values(options.versions).map((version) =>
<div key={version}>

<SearchableDropdown name="user"
label="Manage Versions a User has access to"
placeHolder="Search for a User"
options={options.users}
strictSearch={true}
onUserInput={this.setFormData}
value={this.state.user}
/>
{this.state.user && <StaticElement
label={'Versions'}
text={Object.values(options.versions).map((version) =>
<div>
<CheckboxElement
name={version}
label={version || 'Unversioned'}
value={user.versions.includes(version)}
onUserInput={(version, permission) =>
this.setFormData(userId, version, permission)
}
name={'versionsByUser'}
label={version}
value={data[this.state.user].versions.includes(version)}
onUserInput={(formElement, checked) =>
this.setFormData(
'versionsByUser', {
userId: this.state.user, version, checked,
}
)
}
/><br/>
</div>
);

return <StaticElement
key={userId}
)}
/>
}
<SearchableDropdown
name="version"
label="Manage Users with access to a Version"
placeHolder="Search for a Version"
options={options.versions}
strictSearch={true}
onUserInput={this.setFormData}
value={this.state.version}
/>
{this.state.version &&
<StaticElement
label={'Users'}
text={Object.values(this.state.originalData).map((user) => {
if (user.versions.includes(this.state.version)) {
return <div>
<CheckboxElement
name={'usersByVersion'}
label={user.name}
text={<div>{versions}</div>}
/>;
})};
value={
data[user.id].versions.includes(this.state.version)
}
onUserInput={(_, checked) =>
this.setFormData(
'usersByVersion',
{
userId: user.id,
checked,
version: this.state.version,
}
)
}
/><br/>
</div>;
}
}
)}
/>
}
</FormElement>
</Modal>
);
Expand All @@ -116,19 +166,25 @@ class ManagePermissionsForm extends Component {
/**
* Store the value of the element in this.state.data
*
* @param {string} userId
* @param {string} version
* @param {boolean} permission
* @param {string} formElement - name of the selected element
* @param {string} value - selected value for corresponding form element
*/
setFormData(userId, version, permission) {
setFormData(formElement, value) {
let {data} = JSON.parse(JSON.stringify(this.state));
if (permission) {
data[userId].versions = [...data[userId].versions, version];
if (formElement === 'versionsByUser' || formElement === 'usersByVersion') {
let {checked, version, userId} = value;
if (checked) {
data[userId].versions = [...data[userId].versions, version];
} else {
data[userId].versions = data[userId].versions
.filter((e) => e !== version);
}
this.setState({data});
} else {
data[userId].versions = data[userId].versions
.filter((e) => e !== version);
this.setState({[formElement]: (value === '' ? null : value)});
if (formElement != 'user') this.setState({user: null});
if (formElement != 'version') this.setState({version: null});
}
this.setState({data});
}

/**
Expand Down
17 changes: 17 additions & 0 deletions modules/data_release/jsx/uploadFileForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
FileElement,
TextboxElement,
ButtonElement,
SelectElement,
} from 'jsx/Form';

/**
Expand Down Expand Up @@ -79,6 +80,14 @@ class UploadFileForm extends Component {
required={false}
value={this.state.formData.version}
/>
<SelectElement
name='project'
label='Project'
onUserInput={this.updateFormElement}
required={true}
value={this.state.formData.project}
options={this.props.projects}
/>
<ButtonElement label='Upload File'/>
<div className='row'>
<div className='col-sm-9 col-sm-offset-3'>
Expand Down Expand Up @@ -130,6 +139,13 @@ class UploadFileForm extends Component {
return;
}

if (!formData.project) {
errorMessage.Project = 'You must select a project';
hasError.Project = true;
this.setState({errorMessage, hasError});
return;
}

// Check that the size of the file is not bigger than the allowed size
let fileSize = formData.file ? Math.round((formData.file.size/1024)) : null;
const maxSizeAllowed = this.state.data.maxUploadSize;
Expand Down Expand Up @@ -230,6 +246,7 @@ class UploadFileForm extends Component {
UploadFileForm.propTypes = {
DataURL: PropTypes.string.isRequired,
action: PropTypes.string.isRequired,
projects: PropTypes.array.isRequired,
};

export default UploadFileForm;
44 changes: 32 additions & 12 deletions modules/data_release/php/data_release.class.inc
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,12 @@ class Data_Release extends \DataFrameworkMenu
function getUsersList(\Database $DB)
{
return $DB->pselectColWithIndexKey(
"SELECT ID, UserID FROM users",
[],
"SELECT DISTINCT ID, LOWER(users.UserID) as UserID FROM users
JOIN user_project_rel upr ON upr.UserID = users.ID
WHERE upr.ProjectID IN
(SELECT ProjectID FROM user_project_rel WHERE UserID = :userID)
ORDER BY LOWER(users.UserID)",
[':userID' => \User::singleton()->getID()],
"ID"
);
}
Expand All @@ -74,8 +78,10 @@ class Data_Release extends \DataFrameworkMenu
function getFilesList(\Database $DB)
{
$result = $DB->pselectWithIndexKey(
"SELECT id, file_name, version FROM data_release",
[],
"SELECT id, file_name, version, ProjectID FROM data_release
WHERE ProjectID IS NULL OR ProjectID IN
(SELECT ProjectID FROM user_project_rel WHERE UserID = :userID)",
[':userID' => \User::singleton()->getID()],
"id"
);

Expand All @@ -98,9 +104,12 @@ class Data_Release extends \DataFrameworkMenu
*/
function getVersionsList(\Database $DB)
{
$user =& \User::singleton();
$versions = $DB->pselectCol(
"SELECT DISTINCT version FROM data_release",
[],
"SELECT DISTINCT version FROM data_release
WHERE ProjectID IS NULL OR ProjectID IN
(SELECT ProjectID FROM user_project_rel WHERE UserID = :userID)",
['userID' => $user->getID()],
"version"
);

Expand All @@ -124,8 +133,10 @@ class Data_Release extends \DataFrameworkMenu
function getVersionFiles(\Database $db)
{
$result = $db->pselect(
"SELECT version, id FROM data_release",
[]
"SELECT version, id FROM data_release
WHERE ProjectID IS NULL OR ProjectID IN
(SELECT ProjectID FROM user_project_rel WHERE UserID = :userID)",
[':userID' => \User::singleton()->getID()]
);

$versionFiles = [];
Expand All @@ -150,16 +161,23 @@ class Data_Release extends \DataFrameworkMenu
$result = $db->pselect(
"SELECT u.ID as userId,
u.UserID as userName,
drp.data_release_id fileId
drp.data_release_id fileId,
dr.ProjectID as ProjectID
FROM users u
LEFT JOIN data_release_permissions drp ON (u.ID=drp.userid)
LEFT JOIN data_release dr ON (drp.data_release_id=dr.id)",
[]
LEFT JOIN data_release dr ON (drp.data_release_id=dr.id)
JOIN user_project_rel upr ON upr.UserID = u.ID
WHERE upr.ProjectID IN
(SELECT ProjectID FROM user_project_rel WHERE UserID = :userID)",
[':userID' => \User::singleton()->getID()]
);

error_log(print_r($result, true));

$userFiles = [];
foreach ($result as $row) {
$userFiles[$row['userId']]['name'] = $row['userName'];
$userFiles[$row['userId']]['id'] = $row['userId'];
if (empty($userFiles[$row['userId']]['files'])) {
$userFiles[$row['userId']]['files'] = [];
}
Expand Down Expand Up @@ -205,11 +223,13 @@ class Data_Release extends \DataFrameworkMenu
*/
protected function getFieldOptions() : array
{
$db = $this->loris->getDatabaseConnection();
$db = $this->loris->getDatabaseConnection();
$projects = \Utility::getProjectList();
return [
'users' => $this->getUsersList($db),
'versions' => $this->getVersionsList($db),
'filenames' => $this->getFilesList($db),
'projects' => array_combine($projects, $projects)
];
}

Expand Down
10 changes: 8 additions & 2 deletions modules/data_release/php/datareleaseprovisioner.class.inc
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@ class DataReleaseProvisioner extends \LORIS\Data\Provisioners\DBRowProvisioner
file_name AS fileName,
IF(version is null or version ='','Unversioned', version) AS version,
upload_date AS uploadDate,
p.Name as ProjectName,
dr.id as dataReleaseID
FROM data_release dr";
FROM data_release dr
LEFT JOIN Project p on p.ProjectID = dr.ProjectID";

if (!$user->hasPermission("superuser")) {
$query .= "
Expand All @@ -53,7 +55,11 @@ class DataReleaseProvisioner extends \LORIS\Data\Provisioners\DBRowProvisioner
ON
(dr.id=drp.data_release_id)
WHERE
drp.UserID=".$user->getID();
drp.UserID=".$user->getID()." AND (
dr.ProjectID IS NULL OR dr.ProjectID IN
(SELECT ProjectID FROM user_project_rel
WHERE UserID = ".$user->getID().")
)";
}

$query .= " ORDER BY uploadDate";
Expand Down
Loading
Loading