Merge pull request #11347 from OlegZharkov/dataset-lib-permissions

Dataset lib permissions Vue rewrite
This commit is contained in:
Dannon
2021-02-18 08:20:42 -05:00
committed by GitHub
12 changed files with 447 additions and 417 deletions
@@ -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) {
@@ -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']" />
&nbsp;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']" />
&nbsp;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>
@@ -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>
@@ -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>
@@ -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>
+2 -2
View File
@@ -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"],
+2 -272
View File
@@ -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>
&nbsp;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>
&nbsp;Save
</button>
</div>
<!-- CONTAINER END -->
</div>`
);
},
templateBulkImportInModal: function () {
return _.template(
`<div>
+1
View File
@@ -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