mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Merge pull request #11347 from OlegZharkov/dataset-lib-permissions
Dataset lib permissions Vue rewrite
This commit is contained in:
@@ -461,7 +461,8 @@ export default {
|
||||
else if (element.type === "folder") return `${this.root}library/folders/${element.id}`;
|
||||
},
|
||||
navigateToPermission(element) {
|
||||
if (element.type === "file") window.location.replace(`${this.createContentLink(element)}/permissions`);
|
||||
if (element.type === "file")
|
||||
this.$router.push({ path: `/permissions/${this.folder_id}/dataset/${element.id}` });
|
||||
else if (element.type === "folder") this.$router.push({ path: `/permissions/${element.id}` });
|
||||
},
|
||||
getMessage(element) {
|
||||
|
||||
+243
@@ -0,0 +1,243 @@
|
||||
<template>
|
||||
<div>
|
||||
<b-container fluid>
|
||||
<div v-if="dataset">
|
||||
<b-breadcrumb>
|
||||
<b-breadcrumb-item title="Return to the list of libraries" :href="`${root}library/list`">
|
||||
Libraries
|
||||
</b-breadcrumb-item>
|
||||
<template v-for="path_item in this.dataset.full_path">
|
||||
<b-breadcrumb-item
|
||||
:key="path_item[0]"
|
||||
:to="{ path: `/${path_item[0]}` }"
|
||||
:active="path_item[0] === dataset_id"
|
||||
href="#"
|
||||
>{{ path_item[1] }}</b-breadcrumb-item
|
||||
>
|
||||
</template>
|
||||
</b-breadcrumb>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-button
|
||||
data-toggle="tooltip"
|
||||
data-placement="top"
|
||||
title="Go to Dataset Details"
|
||||
variant="secondary"
|
||||
type="button"
|
||||
:href="`${root}library/list#folders/${folder_id}/datasets/${dataset_id}`"
|
||||
>
|
||||
<font-awesome-icon :icon="['far', 'file']" />
|
||||
Dataset Details
|
||||
</b-button>
|
||||
</b-col>
|
||||
<b-col>
|
||||
<div>
|
||||
<div class="header text-center">{{ dataset.name }}</div>
|
||||
</div>
|
||||
</b-col>
|
||||
<b-col />
|
||||
</b-row>
|
||||
</div>
|
||||
|
||||
<LibraryPermissionsWarning :is_admin="is_admin" />
|
||||
<hr class="my-4" />
|
||||
<h2 class="text-center">Library-related permissions</h2>
|
||||
<PermissionsInputField
|
||||
v-if="modify_item_roles"
|
||||
:id="dataset_id"
|
||||
:permission_type="modify_item_roles_type"
|
||||
:initial_value="modify_item_roles"
|
||||
title="Roles that can modify the library item"
|
||||
:apiRootUrl="apiRootUrl"
|
||||
alert="User with <strong>any</strong> of these roles can modify name, metadata, and other information about this library item."
|
||||
@input="setUserPermissionsPreferences"
|
||||
/>
|
||||
<hr class="my-4" />
|
||||
<h2 class="text-center">Dataset-related permissions</h2>
|
||||
<div class="alert alert-warning text-center">
|
||||
Changes made below will affect <strong>every</strong> library item that was created from this dataset
|
||||
and also every history this dataset is part of.
|
||||
</div>
|
||||
<p class="text-center" v-if="is_unrestricted">
|
||||
You can
|
||||
<strong @click="toggleDatasetPrivacy(true)" class="make-private">
|
||||
<a href="javascript:void(0)">make this dataset private</a>
|
||||
</strong>
|
||||
to you.
|
||||
</p>
|
||||
<p class="text-center" v-else>
|
||||
You can
|
||||
<strong @click="toggleDatasetPrivacy(false)" class="remove-restrictions">
|
||||
<a href="javascript:void(0)">remove all access restrictions</a>
|
||||
</strong>
|
||||
on this dataset.
|
||||
</p>
|
||||
|
||||
<PermissionsInputField
|
||||
ref="access_field"
|
||||
v-if="access_dataset_roles"
|
||||
:id="dataset_id"
|
||||
:permission_type="access_dataset_roles_type"
|
||||
:initial_value="access_dataset_roles"
|
||||
:apiRootUrl="apiRootUrl"
|
||||
title="Roles that can access the dataset"
|
||||
alert="User has to have <strong>all these roles</strong> in order to access this dataset.
|
||||
Users without access permission <strong>cannot</strong> have other permissions on this dataset.
|
||||
If there are no access roles set on the dataset it is considered <strong>unrestricted</strong>."
|
||||
@input="setUserPermissionsPreferences"
|
||||
/>
|
||||
<PermissionsInputField
|
||||
v-if="manage_dataset_roles"
|
||||
:id="dataset_id"
|
||||
:permission_type="manage_dataset_roles_type"
|
||||
:initial_value="manage_dataset_roles"
|
||||
:apiRootUrl="apiRootUrl"
|
||||
title="Roles that can manage permissions on the dataset"
|
||||
alert="User with <strong>any</strong> of these roles can manage permissions of this dataset.
|
||||
If you remove yourself you will lose the ability manage this dataset unless you are an admin."
|
||||
@input="setUserPermissionsPreferences"
|
||||
/>
|
||||
<b-button
|
||||
data-toggle="tooltip"
|
||||
data-placement="top"
|
||||
title="Save modifications"
|
||||
class="toolbtn_save_permissions"
|
||||
variant="secondary"
|
||||
@click="postPermissions"
|
||||
>
|
||||
<font-awesome-icon :icon="['far', 'save']" />
|
||||
Save
|
||||
</b-button>
|
||||
</b-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from "vue";
|
||||
import { getAppRoot } from "onload/loadConfig";
|
||||
import BootstrapVue from "bootstrap-vue";
|
||||
import { Services } from "./services";
|
||||
import { Toast } from "ui/toast";
|
||||
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
||||
import { getGalaxyInstance } from "app";
|
||||
import PermissionsInputField from "./PermissionsInputField.vue";
|
||||
import { initPermissionsIcons } from "components/LibraryFolder/icons";
|
||||
import LibraryPermissionsWarning from "components/LibraryFolder/LibraryFolderPermissions/LibraryPermissionsWarning.vue";
|
||||
import { extractRoles } from "./utils";
|
||||
|
||||
import "vue-multiselect/dist/vue-multiselect.min.css";
|
||||
import VueObserveVisibility from "vue-observe-visibility";
|
||||
|
||||
Vue.use(VueObserveVisibility);
|
||||
Vue.use(BootstrapVue);
|
||||
initPermissionsIcons();
|
||||
|
||||
export default {
|
||||
props: {
|
||||
folder_id: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
dataset_id: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
components: {
|
||||
PermissionsInputField,
|
||||
LibraryPermissionsWarning,
|
||||
FontAwesomeIcon,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
permissions: undefined,
|
||||
dataset: undefined,
|
||||
is_admin: undefined,
|
||||
access_dataset_roles: undefined,
|
||||
modify_item_roles: undefined,
|
||||
manage_dataset_roles: undefined,
|
||||
access_dataset_roles_type: "access_dataset_roles",
|
||||
modify_item_roles_type: "modify_item_roles",
|
||||
manage_dataset_roles_type: "manage_dataset_roles",
|
||||
apiRootUrl: `${getAppRoot()}api/libraries/datasets`,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
const Galaxy = getGalaxyInstance();
|
||||
this.root = getAppRoot();
|
||||
this.services = new Services({ root: this.root });
|
||||
this.is_admin = Galaxy.user.attributes.is_admin;
|
||||
this.services
|
||||
.getDatasetPermissions(this.dataset_id)
|
||||
.then((fetched_permissions) => this.assignFetchedPermissions(fetched_permissions));
|
||||
this.services.getDataset(this.dataset_id).then((response) => {
|
||||
this.dataset = response;
|
||||
});
|
||||
},
|
||||
computed: {
|
||||
is_unrestricted() {
|
||||
return this.access_dataset_roles ? this.access_dataset_roles.length === 0 : false;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
assignFetchedPermissions(fetched_permissions) {
|
||||
this.access_dataset_roles = extractRoles(fetched_permissions.access_dataset_roles);
|
||||
this.modify_item_roles = extractRoles(fetched_permissions.modify_item_roles);
|
||||
this.manage_dataset_roles = extractRoles(fetched_permissions.manage_dataset_roles);
|
||||
console.log(this.access_dataset_roles);
|
||||
},
|
||||
toggleDatasetPrivacy(isMakePrivate) {
|
||||
this.services.toggleDatasetPrivacy(
|
||||
this.dataset_id,
|
||||
isMakePrivate,
|
||||
(fetched_permissions) => {
|
||||
Toast.success(
|
||||
`${
|
||||
isMakePrivate
|
||||
? "The dataset is now private to you."
|
||||
: "Access to this dataset is now unrestricted."
|
||||
}`
|
||||
);
|
||||
this.assignFetchedPermissions(fetched_permissions);
|
||||
this.$refs.access_field.assignValue(this.access_dataset_roles);
|
||||
},
|
||||
(error) => {
|
||||
Toast.error("An error occurred while attempting to set folder permissions.");
|
||||
console.error(error);
|
||||
}
|
||||
);
|
||||
},
|
||||
getParentLink() {
|
||||
return `${this.root}library/folders/${this.folder_id}`;
|
||||
},
|
||||
setUserPermissionsPreferences(ids, permission_type) {
|
||||
this[permission_type] = ids;
|
||||
},
|
||||
postPermissions() {
|
||||
this.services.setPermissions(
|
||||
this.apiRootUrl,
|
||||
this.dataset_id,
|
||||
[
|
||||
{ "access_ids[]": this.access_dataset_roles },
|
||||
{ "modify_ids[]": this.modify_item_roles },
|
||||
{ "manage_ids[]": this.manage_dataset_roles },
|
||||
],
|
||||
(fetched_permissions) => {
|
||||
Toast.success("Permissions saved.");
|
||||
this.assignFetchedPermissions(fetched_permissions);
|
||||
},
|
||||
(error) => {
|
||||
Toast.error("An error occurred while attempting to set folder permissions.");
|
||||
console.error(error);
|
||||
}
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.header {
|
||||
font-size: 45px;
|
||||
}
|
||||
</style>
|
||||
+56
-104
@@ -2,84 +2,51 @@
|
||||
<div>
|
||||
<div>
|
||||
<div v-if="folder">
|
||||
<b-button variant="primary" :to="{ path: `/${this.folder.parent_id}` }">
|
||||
<font-awesome-icon icon="angle-double-left">1</font-awesome-icon>
|
||||
<b-button variant="primary" title="back to parent folder" :to="{ path: `/${this.folder.parent_id}` }">
|
||||
<font-awesome-icon icon="angle-double-left" />
|
||||
</b-button>
|
||||
<div>
|
||||
<div class="header text-center">{{ folder.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-center">
|
||||
<b-alert show variant="warning" v-if="is_admin">
|
||||
You are logged in as an <strong>administrator</strong> therefore you can manage any folder on
|
||||
this Galaxy instance. Please make sure you understand the consequences.
|
||||
</b-alert>
|
||||
<b-alert show variant="warning" v-else>
|
||||
You can assign any number of roles to any of the following permission types. However please read
|
||||
carefully the implications of such actions.
|
||||
</b-alert>
|
||||
</div>
|
||||
</div>
|
||||
<LibraryPermissionsWarning :is_admin="is_admin" />
|
||||
<hr class="my-4" />
|
||||
<b-container fluid>
|
||||
<div class="dataset_table">
|
||||
<h2>Folder permissions</h2>
|
||||
<h4>
|
||||
Roles that can manage permissions on this folder
|
||||
</h4>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<PermissionsInputField
|
||||
v-if="manage_folder_role_list"
|
||||
:folder_id="folder_id"
|
||||
:permission_type="manage_type"
|
||||
:initial_value="manage_folder_role_list"
|
||||
@input="setUserPermissionsPreferences"
|
||||
/></b-col>
|
||||
<b-col>
|
||||
<b-alert show variant="info">
|
||||
User with <strong>any</strong> of these roles can manage permissions on this folder.
|
||||
</b-alert>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<h4>
|
||||
Roles that can add items to this folder
|
||||
</h4>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<PermissionsInputField
|
||||
v-if="add_library_item_role_list"
|
||||
:folder_id="folder_id"
|
||||
:permission_type="add_type"
|
||||
:initial_value="add_library_item_role_list"
|
||||
@input="setUserPermissionsPreferences"
|
||||
/></b-col>
|
||||
<b-col>
|
||||
<b-alert class="p-3" show variant="info">
|
||||
User with <strong>any</strong> of these roles can add items to this folder (folders and
|
||||
datasets).
|
||||
</b-alert>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<h4>
|
||||
Roles that can modify this folder
|
||||
</h4>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<PermissionsInputField
|
||||
v-if="modify_folder_role_list"
|
||||
:folder_id="folder_id"
|
||||
:permission_type="modify_type"
|
||||
:initial_value="modify_folder_role_list"
|
||||
@input="setUserPermissionsPreferences"
|
||||
/></b-col>
|
||||
<b-col>
|
||||
<b-alert show variant="info">
|
||||
User with <strong>any</strong> of these roles can modify this folder (name, etc.).
|
||||
</b-alert></b-col
|
||||
>
|
||||
</b-row>
|
||||
<h2 class="text-center">Folder permissions</h2>
|
||||
<PermissionsInputField
|
||||
v-if="manage_folder_role_list"
|
||||
:id="folder_id"
|
||||
:permission_type="manage_type"
|
||||
:initial_value="manage_folder_role_list"
|
||||
:apiRootUrl="apiRootUrl"
|
||||
alert="User with <strong>any</strong> of these roles can manage permissions on this folder."
|
||||
title="Roles that can manage permissions on this folder"
|
||||
@input="setUserPermissionsPreferences"
|
||||
/>
|
||||
|
||||
<PermissionsInputField
|
||||
v-if="add_library_item_role_list"
|
||||
:id="folder_id"
|
||||
:permission_type="add_type"
|
||||
:initial_value="add_library_item_role_list"
|
||||
:apiRootUrl="apiRootUrl"
|
||||
title="Roles that can add items to this folder"
|
||||
alert="User with <strong>any</strong> of these roles can add items to this folder (folders and
|
||||
datasets)."
|
||||
@input="setUserPermissionsPreferences"
|
||||
/>
|
||||
|
||||
<PermissionsInputField
|
||||
v-if="modify_folder_role_list"
|
||||
:id="folder_id"
|
||||
:permission_type="modify_type"
|
||||
:initial_value="modify_folder_role_list"
|
||||
:apiRootUrl="apiRootUrl"
|
||||
title="Roles that can modify this folder"
|
||||
alert="User with <strong>any</strong> of these roles can modify this folder (name, etc.)."
|
||||
@input="setUserPermissionsPreferences"
|
||||
/>
|
||||
<button
|
||||
data-toggle="tooltip"
|
||||
data-placement="top"
|
||||
@@ -106,14 +73,13 @@ import { Toast } from "ui/toast";
|
||||
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
||||
import { getGalaxyInstance } from "app";
|
||||
import PermissionsInputField from "./PermissionsInputField.vue";
|
||||
import { initManageFolderIcons } from "components/LibraryFolder/icons";
|
||||
import LibraryPermissionsWarning from "components/LibraryFolder/LibraryFolderPermissions/LibraryPermissionsWarning.vue";
|
||||
import { extractRoles } from "./utils";
|
||||
|
||||
import "vue-multiselect/dist/vue-multiselect.min.css";
|
||||
import VueObserveVisibility from "vue-observe-visibility";
|
||||
import { initPermissionsIcons } from "components/LibraryFolder/icons";
|
||||
|
||||
Vue.use(VueObserveVisibility);
|
||||
Vue.use(BootstrapVue);
|
||||
initManageFolderIcons();
|
||||
initPermissionsIcons();
|
||||
|
||||
export default {
|
||||
props: {
|
||||
@@ -124,6 +90,7 @@ export default {
|
||||
},
|
||||
components: {
|
||||
PermissionsInputField,
|
||||
LibraryPermissionsWarning,
|
||||
FontAwesomeIcon,
|
||||
},
|
||||
data() {
|
||||
@@ -134,9 +101,10 @@ export default {
|
||||
add_library_item_role_list: undefined,
|
||||
modify_folder_role_list: undefined,
|
||||
manage_folder_role_list: undefined,
|
||||
add_type: "add_type",
|
||||
manage_type: "manage_type",
|
||||
modify_type: "modify_type",
|
||||
add_type: "add_library_item_role_list",
|
||||
manage_type: "manage_folder_role_list",
|
||||
modify_type: "modify_folder_role_list",
|
||||
apiRootUrl: `${getAppRoot()}api/folders`,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
@@ -145,9 +113,9 @@ export default {
|
||||
this.services = new Services({ root: this.root });
|
||||
this.is_admin = Galaxy.user.attributes.is_admin;
|
||||
this.services.getFolderPermissions(this.folder_id).then((fetched_permissions) => {
|
||||
this.add_library_item_role_list = this._serializeRoles(fetched_permissions.add_library_item_role_list);
|
||||
this.manage_folder_role_list = this._serializeRoles(fetched_permissions.manage_folder_role_list);
|
||||
this.modify_folder_role_list = this._serializeRoles(fetched_permissions.modify_folder_role_list);
|
||||
this.add_library_item_role_list = extractRoles(fetched_permissions.add_library_item_role_list);
|
||||
this.manage_folder_role_list = extractRoles(fetched_permissions.manage_folder_role_list);
|
||||
this.modify_folder_role_list = extractRoles(fetched_permissions.modify_folder_role_list);
|
||||
});
|
||||
this.services.getFolder(this.folder_id).then((response) => {
|
||||
this.folder = response;
|
||||
@@ -159,24 +127,17 @@ export default {
|
||||
return `${this.root}library/folders/${this.folder.parent_id}`;
|
||||
},
|
||||
setUserPermissionsPreferences(ids, permission_type) {
|
||||
switch (permission_type) {
|
||||
case "manage_type":
|
||||
this.manage_folder_role_list = ids;
|
||||
break;
|
||||
case "add_type":
|
||||
this.add_library_item_role_list = ids;
|
||||
break;
|
||||
case "modify_type":
|
||||
this.modify_folder_role_list = ids;
|
||||
break;
|
||||
}
|
||||
this[permission_type] = ids;
|
||||
},
|
||||
postPermissions() {
|
||||
this.services.setPermissions(
|
||||
this.apiRootUrl,
|
||||
this.folder_id,
|
||||
this.add_library_item_role_list,
|
||||
this.manage_folder_role_list,
|
||||
this.modify_folder_role_list,
|
||||
[
|
||||
{ "add_ids[]": this.add_library_item_role_list },
|
||||
{ "manage_ids[]": this.manage_folder_role_list },
|
||||
{ "modify_ids[]": this.modify_folder_role_list },
|
||||
],
|
||||
(fetched_permissions) => {
|
||||
Toast.success("Permissions saved.");
|
||||
this.permissions = fetched_permissions;
|
||||
@@ -187,15 +148,6 @@ export default {
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
_serializeRoles: function (role_list) {
|
||||
const selected_roles = [];
|
||||
role_list.forEach((item) => {
|
||||
selected_roles.push({ name: item[0], id: item[1] });
|
||||
});
|
||||
|
||||
return selected_roles;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="text-center">
|
||||
<b-alert show variant="warning" v-if="is_admin">
|
||||
You are logged in as an <strong>administrator</strong> therefore you can manage any folder on this
|
||||
Galaxy instance. Please make sure you understand the consequences.
|
||||
</b-alert>
|
||||
<b-alert show variant="warning" v-else>
|
||||
You can assign any number of roles to any of the following permission types. However please read
|
||||
carefully the implications of such actions.
|
||||
</b-alert>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
is_admin: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
+55
-21
@@ -1,33 +1,56 @@
|
||||
<template>
|
||||
<div v-if="options && value">
|
||||
<multiselect
|
||||
v-model="value"
|
||||
:options="fetched_options"
|
||||
:clear-on-select="true"
|
||||
:preserve-search="true"
|
||||
:multiple="true"
|
||||
label="name"
|
||||
track-by="id"
|
||||
@input="valueChanged"
|
||||
@search-change="searchChanged"
|
||||
:internal-search="false"
|
||||
>
|
||||
<template slot="afterList">
|
||||
<div v-observe-visibility="reachedEndOfList" v-if="hasMorePages">
|
||||
<span class="spinner fa fa-spinner fa-spin fa-1x" />
|
||||
<div>
|
||||
<h4>
|
||||
{{ title }}
|
||||
</h4>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<div v-if="options && value">
|
||||
<multiselect
|
||||
v-model="value"
|
||||
:options="fetched_options"
|
||||
:clear-on-select="true"
|
||||
:preserve-search="true"
|
||||
:multiple="true"
|
||||
label="name"
|
||||
track-by="id"
|
||||
@input="valueChanged"
|
||||
@search-change="searchChanged"
|
||||
:internal-search="false"
|
||||
>
|
||||
<template slot="afterList">
|
||||
<div v-observe-visibility="reachedEndOfList" v-if="hasMorePages">
|
||||
<span class="spinner fa fa-spinner fa-spin fa-1x" />
|
||||
</div>
|
||||
</template>
|
||||
</multiselect>
|
||||
</div>
|
||||
</template>
|
||||
</multiselect>
|
||||
</b-col>
|
||||
<b-col>
|
||||
<b-alert show variant="info">
|
||||
<div v-html="alert" />
|
||||
</b-alert>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from "vue";
|
||||
|
||||
import VueObserveVisibility from "vue-observe-visibility";
|
||||
import Multiselect from "vue-multiselect";
|
||||
import { Services } from "./services";
|
||||
import "vue-multiselect/dist/vue-multiselect.min.css";
|
||||
|
||||
Vue.use(VueObserveVisibility);
|
||||
export default {
|
||||
props: {
|
||||
folder_id: {
|
||||
id: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
@@ -39,6 +62,14 @@ export default {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
apiRootUrl: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
alert: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
components: {
|
||||
Multiselect,
|
||||
@@ -59,7 +90,7 @@ export default {
|
||||
created() {
|
||||
this.services = new Services({ root: this.root });
|
||||
// Avoid mutating a prop directly
|
||||
this.value = this.initial_value;
|
||||
this.assignValue(this.initial_value);
|
||||
this.getSelectOptions();
|
||||
},
|
||||
computed: {
|
||||
@@ -70,7 +101,7 @@ export default {
|
||||
methods: {
|
||||
getSelectOptions(searchChanged = false) {
|
||||
this.services
|
||||
.getSelectOptions(this.folder_id, true, this.page, this.page_limit, this.searchValue)
|
||||
.getSelectOptions(this.apiRootUrl, this.id, true, this.page, this.page_limit, this.searchValue)
|
||||
.then((response) => {
|
||||
this.options = response;
|
||||
if (searchChanged) this.fetched_options = this.options.roles;
|
||||
@@ -91,6 +122,9 @@ export default {
|
||||
this.searchValue = searchValue;
|
||||
this.getSelectOptions(true);
|
||||
},
|
||||
assignValue(value) {
|
||||
this.value = value;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -16,6 +16,24 @@ export class Services {
|
||||
rethrowSimple(e);
|
||||
}
|
||||
}
|
||||
async getDatasetPermissions(id) {
|
||||
const url = `${this.root}api/libraries/datasets/${id}/permissions?scope=current`;
|
||||
try {
|
||||
const response = await axios.get(url);
|
||||
return response.data;
|
||||
} catch (e) {
|
||||
rethrowSimple(e);
|
||||
}
|
||||
}
|
||||
async getDataset(id) {
|
||||
const url = `${this.root}api/libraries/datasets/${id}`;
|
||||
try {
|
||||
const response = await axios.get(url);
|
||||
return response.data;
|
||||
} catch (e) {
|
||||
rethrowSimple(e);
|
||||
}
|
||||
}
|
||||
async getFolder(id) {
|
||||
const url = `${this.root}api/folders/${id}`;
|
||||
try {
|
||||
@@ -25,9 +43,9 @@ export class Services {
|
||||
rethrowSimple(e);
|
||||
}
|
||||
}
|
||||
async getSelectOptions(id, is_library_access, page, page_limit, searchQuery) {
|
||||
async getSelectOptions(apiRootUrl, id, is_library_access, page, page_limit, searchQuery) {
|
||||
searchQuery = searchQuery ? `&q=${searchQuery}` : "";
|
||||
const url = `${this.root}api/folders/${id}/permissions?scope=available&is_library_access=${is_library_access}&page_limit=${page_limit}&page=${page}${searchQuery}`;
|
||||
const url = `${apiRootUrl}/${id}/permissions?scope=available&is_library_access=${is_library_access}&page_limit=${page_limit}&page=${page}${searchQuery}`;
|
||||
try {
|
||||
const response = await axios.get(url);
|
||||
return response.data;
|
||||
@@ -35,24 +53,19 @@ export class Services {
|
||||
rethrowSimple(e);
|
||||
}
|
||||
}
|
||||
async setPermissions(id, add_ids, manage_ids, modify_ids, onSuccess, onError) {
|
||||
|
||||
async setPermissions(apiRootUrl, id, new_roles_ids, onSuccess, onError) {
|
||||
var formData = new FormData();
|
||||
formData.append(
|
||||
"add_ids[]",
|
||||
add_ids.map((a) => a.id)
|
||||
);
|
||||
formData.append(
|
||||
"manage_ids[]",
|
||||
manage_ids.map((a) => a.id)
|
||||
);
|
||||
formData.append(
|
||||
"modify_ids[]",
|
||||
modify_ids.map((a) => a.id)
|
||||
);
|
||||
new_roles_ids.forEach((permissionType) => {
|
||||
Object.keys(permissionType).map(function (k) {
|
||||
const ids = permissionType[k].map((a) => a.id);
|
||||
formData.append(k, ids);
|
||||
});
|
||||
});
|
||||
|
||||
axios({
|
||||
method: "post",
|
||||
url: `${getAppRoot()}api/folders/${id}/permissions?action=set_permissions`,
|
||||
url: `${apiRootUrl}/${id}/permissions?action=set_permissions`,
|
||||
data: formData,
|
||||
headers: { "Content-Type": "multipart/form-data" },
|
||||
})
|
||||
@@ -63,4 +76,18 @@ export class Services {
|
||||
onError(response);
|
||||
});
|
||||
}
|
||||
async toggleDatasetPrivacy(id, isMakePrivate, onSuccess, onError) {
|
||||
await axios
|
||||
.post(
|
||||
`${getAppRoot()}api/libraries/datasets/${id}/permissions?action=${
|
||||
isMakePrivate ? "make_private" : "remove_restrictions"
|
||||
}`
|
||||
)
|
||||
.then((fetched_permissions) => {
|
||||
onSuccess(fetched_permissions.data);
|
||||
})
|
||||
.catch((response) => {
|
||||
onError(response);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
// legacy code
|
||||
export function extractRoles(role_list) {
|
||||
const selected_roles = [];
|
||||
role_list.forEach((item) => {
|
||||
selected_roles.push({ name: item[0], id: item[1] });
|
||||
});
|
||||
|
||||
return selected_roles;
|
||||
}
|
||||
@@ -2,8 +2,9 @@
|
||||
import { getAppRoot } from "onload/loadConfig";
|
||||
import Vue from "vue";
|
||||
import VueRouter from "vue-router";
|
||||
import LibraryFolderPermissions from "./LibraryFolderPermissions/LibraryFolderPermissions.vue";
|
||||
import LibraryFolderPermissions from "components/LibraryFolder/LibraryFolderPermissions/LibraryFolderPermissions.vue";
|
||||
import LibraryFolder from "components/LibraryFolder/LibraryFolder.vue";
|
||||
import LibraryFolderDatasetPermissions from "components/LibraryFolder/LibraryFolderPermissions/LibraryFolderDatasetPermissions.vue";
|
||||
|
||||
Vue.use(VueRouter);
|
||||
|
||||
@@ -23,6 +24,12 @@ export default new VueRouter({
|
||||
component: LibraryFolderPermissions,
|
||||
props: true,
|
||||
},
|
||||
{
|
||||
path: "/permissions/:folder_id/dataset/:dataset_id",
|
||||
name: "LibraryFolder",
|
||||
component: LibraryFolderDatasetPermissions,
|
||||
props: true,
|
||||
},
|
||||
],
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -38,7 +38,7 @@ const tableIcons = [
|
||||
faMinusSquare,
|
||||
];
|
||||
|
||||
const manageIcons = [faAngleDoubleLeft, faSave];
|
||||
const manageIcons = [faAngleDoubleLeft, faSave, faFile];
|
||||
const topBarIcons = [faHome, faPlus, faInfoCircle, faTrash, faDownload, faBook];
|
||||
|
||||
export function initFolderTableIcons() {
|
||||
@@ -47,7 +47,7 @@ export function initFolderTableIcons() {
|
||||
});
|
||||
}
|
||||
|
||||
export function initManageFolderIcons() {
|
||||
export function initPermissionsIcons() {
|
||||
manageIcons.forEach((icon) => {
|
||||
library.add(icon);
|
||||
});
|
||||
|
||||
@@ -101,6 +101,7 @@ export const getAnalysisRouter = (Galaxy) => {
|
||||
"(/)interactivetool_entry_points(/)list": "show_interactivetool_list",
|
||||
"(/)library/folders(/)(:folder_id)": "show_library_folder",
|
||||
"(/)library/folders/permissions(/)(:folder_id)": "show_library_folder",
|
||||
"(/)library/folders/permissions(/)(:folder_id)(/)dataset(/)(:dataset_id)": "show_library_folder",
|
||||
},
|
||||
|
||||
require_login: ["show_user", "show_user_form", "show_workflows", "show_cloud_auth", "show_external_ids"],
|
||||
|
||||
@@ -27,9 +27,6 @@ var LibraryDatasetView = Backbone.View.extend({
|
||||
"click .toolbtn-download-dataset": "downloadDataset",
|
||||
"click .toolbtn-import-dataset": "importIntoHistory",
|
||||
"click .copy-link-to-clipboard": "copyToClipboard",
|
||||
"click .make-private": "makeDatasetPrivate",
|
||||
"click .remove-restrictions": "removeDatasetRestrictions",
|
||||
"click .toolbtn_save_permissions": "savePermissions",
|
||||
"click .toolbtn_save_modifications": "saveModifications",
|
||||
"click .toolbtn_detect_datatype": "detectDatatype",
|
||||
},
|
||||
@@ -76,9 +73,7 @@ var LibraryDatasetView = Backbone.View.extend({
|
||||
var self = this;
|
||||
this.model.fetch({
|
||||
success: function () {
|
||||
if (self.options.show_permissions) {
|
||||
self.showPermissions();
|
||||
} else if (self.options.show_version) {
|
||||
if (self.options.show_version) {
|
||||
self.fetchVersion();
|
||||
} else {
|
||||
self.render();
|
||||
@@ -298,122 +293,6 @@ var LibraryDatasetView = Backbone.View.extend({
|
||||
);
|
||||
},
|
||||
|
||||
showPermissions: function (options) {
|
||||
const Galaxy = getGalaxyInstance();
|
||||
var template = this.templateDatasetPermissions();
|
||||
var self = this;
|
||||
this.options = _.extend(this.options, options);
|
||||
$(".tooltip").remove();
|
||||
if (this.options.fetched_permissions !== undefined) {
|
||||
if (this.options.fetched_permissions.access_dataset_roles.length === 0) {
|
||||
this.model.set({ is_unrestricted: true });
|
||||
} else {
|
||||
this.model.set({ is_unrestricted: false });
|
||||
}
|
||||
}
|
||||
this.$el.html(
|
||||
template({
|
||||
item: this.model,
|
||||
is_admin: Galaxy.config.is_admin_user,
|
||||
rootPath: getAppRoot(),
|
||||
})
|
||||
);
|
||||
$.get(`${getAppRoot()}api/libraries/datasets/${self.id}/permissions?scope=current`)
|
||||
.done((fetched_permissions) => {
|
||||
self.prepareSelectBoxes({
|
||||
fetched_permissions: fetched_permissions,
|
||||
is_admin: Galaxy.config.is_admin_user,
|
||||
});
|
||||
})
|
||||
.fail(() => {
|
||||
Toast.error("An error occurred while attempting to fetch dataset permissions.");
|
||||
});
|
||||
$('#center [data-toggle="tooltip"]').tooltip({ trigger: "hover" });
|
||||
$("#center").css("overflow", "auto");
|
||||
},
|
||||
|
||||
_serializeRoles: function (role_list) {
|
||||
var selected_roles = [];
|
||||
for (var i = 0; i < role_list.length; i++) {
|
||||
// Replace the : and , in role's name since these are select2 separators for initialData
|
||||
selected_roles.push(`${role_list[i][1]}:${role_list[i][0].replace(":", " ").replace(",", " &")}`);
|
||||
}
|
||||
return selected_roles;
|
||||
},
|
||||
|
||||
prepareSelectBoxes: function (options) {
|
||||
this.options = _.extend(this.options, options);
|
||||
this.accessSelectObject = new mod_select.View(
|
||||
this._generate_select_options({
|
||||
selector: "access_perm",
|
||||
initialData: this._serializeRoles(this.options.fetched_permissions.access_dataset_roles),
|
||||
})
|
||||
);
|
||||
this.modifySelectObject = new mod_select.View(
|
||||
this._generate_select_options({
|
||||
selector: "modify_perm",
|
||||
initialData: this._serializeRoles(this.options.fetched_permissions.modify_item_roles),
|
||||
})
|
||||
);
|
||||
this.manageSelectObject = new mod_select.View(
|
||||
this._generate_select_options({
|
||||
selector: "manage_perm",
|
||||
initialData: this._serializeRoles(this.options.fetched_permissions.manage_dataset_roles),
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
_generate_select_options: function (options) {
|
||||
var select_options = {
|
||||
minimumInputLength: 0,
|
||||
multiple: true,
|
||||
placeholder: "Click to select a role",
|
||||
formatResult: function roleFormatResult(role) {
|
||||
return `${role.name} type: ${role.type}`;
|
||||
},
|
||||
formatSelection: function roleFormatSelection(role) {
|
||||
return role.name;
|
||||
},
|
||||
initSelection: function (element, callback) {
|
||||
// the input tag has a value attribute preloaded that points to a preselected role's id
|
||||
// this function resolves that id attribute to an object that select2 can render
|
||||
// using its formatResult renderer - that way the role name is shown preselected
|
||||
var data = [];
|
||||
$(element.val().split(",")).each(function () {
|
||||
var item = this.split(":");
|
||||
data.push({
|
||||
id: item[0],
|
||||
name: item[1],
|
||||
});
|
||||
});
|
||||
callback(data);
|
||||
},
|
||||
dropdownCssClass: "bigdrop", // apply css that makes the dropdown taller
|
||||
};
|
||||
select_options.container = this.$el.find(`#${options.selector}`);
|
||||
select_options.css = options.selector;
|
||||
select_options.initialData = options.initialData.join(",");
|
||||
select_options.ajax = {
|
||||
url: `${getAppRoot()}api/libraries/datasets/${this.id}/permissions?scope=available`,
|
||||
dataType: "json",
|
||||
quietMillis: 100,
|
||||
data: function (term, page) {
|
||||
// page is the one-based page number tracked by Select2
|
||||
return {
|
||||
q: term, //search term
|
||||
page_limit: 10, // page size, should be same as used in 'more' variable below
|
||||
page: page, // page number
|
||||
};
|
||||
},
|
||||
results: function (data, page) {
|
||||
var more = page * 10 < data.total; // whether or not there are more results available
|
||||
// notice we return the value of more so Select2 knows if more results can be loaded
|
||||
return { results: data.roles, more: more };
|
||||
},
|
||||
};
|
||||
return select_options;
|
||||
},
|
||||
|
||||
detectDatatype: function (options) {
|
||||
const ld = this.model;
|
||||
ld.set("file_ext", "auto");
|
||||
@@ -490,36 +369,6 @@ var LibraryDatasetView = Backbone.View.extend({
|
||||
window.prompt("Copy to clipboard: Ctrl+C, Enter", href);
|
||||
},
|
||||
|
||||
makeDatasetPrivate: function () {
|
||||
var self = this;
|
||||
$.post(`${getAppRoot()}api/libraries/datasets/${self.id}/permissions?action=make_private`)
|
||||
.done((fetched_permissions) => {
|
||||
self.model.set({ is_unrestricted: false });
|
||||
self.showPermissions({
|
||||
fetched_permissions: fetched_permissions,
|
||||
});
|
||||
Toast.success("The dataset is now private to you.");
|
||||
})
|
||||
.fail(() => {
|
||||
Toast.error("An error occurred while attempting to make dataset private.");
|
||||
});
|
||||
},
|
||||
|
||||
removeDatasetRestrictions: function () {
|
||||
var self = this;
|
||||
$.post(`${getAppRoot()}api/libraries/datasets/${self.id}/permissions?action=remove_restrictions`)
|
||||
.done((fetched_permissions) => {
|
||||
self.model.set({ is_unrestricted: true });
|
||||
self.showPermissions({
|
||||
fetched_permissions: fetched_permissions,
|
||||
});
|
||||
Toast.success("Access to this dataset is now unrestricted.");
|
||||
})
|
||||
.fail(() => {
|
||||
Toast.error("An error occurred while attempting to make dataset unrestricted.");
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Extract the role ids from Select2 elements's 'data'
|
||||
*/
|
||||
@@ -531,30 +380,6 @@ var LibraryDatasetView = Backbone.View.extend({
|
||||
return ids_list;
|
||||
},
|
||||
|
||||
/**
|
||||
* Save the permissions for roles entered in the select boxes.
|
||||
*/
|
||||
savePermissions: function (event) {
|
||||
var self = this;
|
||||
var access_ids = this._extractIds(this.accessSelectObject.$el.select2("data"));
|
||||
var manage_ids = this._extractIds(this.manageSelectObject.$el.select2("data"));
|
||||
var modify_ids = this._extractIds(this.modifySelectObject.$el.select2("data"));
|
||||
$.post(`${getAppRoot()}api/libraries/datasets/${self.id}/permissions?action=set_permissions`, {
|
||||
"access_ids[]": access_ids,
|
||||
"manage_ids[]": manage_ids,
|
||||
"modify_ids[]": modify_ids,
|
||||
})
|
||||
.done((fetched_permissions) => {
|
||||
self.showPermissions({
|
||||
fetched_permissions: fetched_permissions,
|
||||
});
|
||||
Toast.success("Permissions saved.");
|
||||
})
|
||||
.fail(() => {
|
||||
Toast.error("An error occurred while attempting to set dataset permissions.");
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* If needed request all extensions and/or genomes from Galaxy
|
||||
* and save them in sorted arrays.
|
||||
@@ -653,7 +478,7 @@ var LibraryDatasetView = Backbone.View.extend({
|
||||
</button>
|
||||
<% } %>
|
||||
<% if (item.get("can_user_manage")) { %>
|
||||
<a href="#folders/<%- item.get("folder_id") %>/datasets/<%- item.id %>/permissions">
|
||||
<a href="<% rootPath %>/library/folders/permissions/<%- item.get("folder_id") %>/dataset/<%- item.id %>">
|
||||
<button data-toggle="tooltip" data-placement="top" title="Manage permissions"
|
||||
class="btn btn-secondary toolbtn_change_permissions toolbar-item mr-1"
|
||||
type="button">
|
||||
@@ -1110,101 +935,6 @@ var LibraryDatasetView = Backbone.View.extend({
|
||||
</div>`
|
||||
);
|
||||
},
|
||||
|
||||
templateDatasetPermissions: function () {
|
||||
return _.template(
|
||||
`<!-- CONTAINER START -->
|
||||
<div class="library_style_container">
|
||||
<div class="d-flex mb-2">
|
||||
<a href="#folders/<%- item.get("folder_id") %>/datasets/<%- item.id %>">
|
||||
<button data-toggle="tooltip" data-placement="top" title="Go back to dataset"
|
||||
class="btn btn-secondary toolbar-item mr-1" type="button">
|
||||
<span class="fa fa-file-o"></span>
|
||||
Dataset Details
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- BREADCRUMBS -->
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item">
|
||||
<a title="Return to the list of libraries" href="#">Libraries</a>
|
||||
</li>
|
||||
<% _.each(item.get("full_path"), function(path_item) { %>
|
||||
<% if (path_item[0] != item.id) { %>
|
||||
<li class="breadcrumb-item">
|
||||
<a title="Return to this folder" href="<% rootPath %>folders/<%- path_item[0] %>">
|
||||
<%- path_item[1] %>
|
||||
</a>
|
||||
</li>
|
||||
<% } else { %>
|
||||
<li class="breadcrumb-item active">
|
||||
<span title="You are here">
|
||||
<%- path_item[1] %>
|
||||
</span>
|
||||
</li>
|
||||
<% } %>
|
||||
<% }); %>
|
||||
</ol>
|
||||
|
||||
<h1>Dataset: <%= _.escape(item.get("name")) %></h1>
|
||||
<div class="alert alert-warning">
|
||||
<% if (is_admin) { %>
|
||||
You are logged in as an <strong>administrator</strong> therefore you can manage any dataset
|
||||
on this Galaxy instance. Please make sure you understand the consequences.
|
||||
<% } else { %>
|
||||
You can assign any number of roles to any of the following permission types. However please
|
||||
read carefully the implications of such actions.
|
||||
<% } %>
|
||||
</div>
|
||||
<div class="dataset_table">
|
||||
<h2>Library-related permissions</h2>
|
||||
<h4>Roles that can modify the library item</h4>
|
||||
<div id="modify_perm" class="modify_perm roles-selection"></div>
|
||||
<div class="alert alert-info roles-selection">
|
||||
User with <strong>any</strong> of these roles can modify name, metadata,
|
||||
and other information about this library item.
|
||||
</div>
|
||||
<hr/>
|
||||
<h2>Dataset-related permissions</h2>
|
||||
<div class="alert alert-warning">
|
||||
Changes made below will affect <strong>every</strong> library item that was created from
|
||||
this dataset and also every history this dataset is part of.
|
||||
</div>
|
||||
<% if (!item.get("is_unrestricted")) { %>
|
||||
<p>
|
||||
You can <span class="remove-restrictions">
|
||||
<a href="javascript:void(0)">remove all access restrictions</a></span> on this dataset.
|
||||
</p>
|
||||
<% } else { %>
|
||||
<p>
|
||||
You can <span class="make-private">
|
||||
<a href="javascript:void(0)">make this dataset private</a></span> to you.</p>
|
||||
<% } %>
|
||||
<h4>Roles that can access the dataset</h4>
|
||||
<div id="access_perm" class="access_perm roles-selection"></div>
|
||||
<div class="alert alert-info roles-selection">
|
||||
User has to have <strong>all these roles</strong> in order to access this dataset.
|
||||
Users without access permission <strong>cannot</strong> have other permissions on this dataset.
|
||||
If there are no access roles set on the dataset it is considered <strong>unrestricted</strong>.
|
||||
</div>
|
||||
<h4>Roles that can manage permissions on the dataset</h4>
|
||||
<div id="manage_perm" class="manage_perm roles-selection"></div>
|
||||
<div class="alert alert-info roles-selection">
|
||||
User with <strong>any</strong> of these roles can manage permissions of this dataset.
|
||||
If you remove yourself you will lose the ability manage this dataset unless you are an admin.
|
||||
</div>
|
||||
<button data-toggle="tooltip" data-placement="top" title="Save modifications made on this page"
|
||||
class="btn btn-secondary toolbtn_save_permissions type="button">
|
||||
<span class="fa fa-floppy-o"></span>
|
||||
Save
|
||||
</button>
|
||||
</div>
|
||||
<!-- CONTAINER END -->
|
||||
</div>`
|
||||
);
|
||||
},
|
||||
|
||||
templateBulkImportInModal: function () {
|
||||
return _.template(
|
||||
`<div>
|
||||
|
||||
@@ -193,6 +193,7 @@ def app_pair(global_conf, load_app_kwds=None, wsgi_preflight=True, **kwargs):
|
||||
webapp.add_client_route('/interactivetool_entry_points/list')
|
||||
webapp.add_client_route('/library/folders/{folder_id}')
|
||||
webapp.add_client_route('/library/folders/permissions/{folder_id}')
|
||||
webapp.add_client_route('/library/folders/permissions/{folder_id}/dataset/{dataset_id}')
|
||||
|
||||
# ==== Done
|
||||
# Indicate that all configuration settings have been provided
|
||||
|
||||
Reference in New Issue
Block a user