From 99bb0f69f7157e62f6847983fd48acf524fc85b9 Mon Sep 17 00:00:00 2001 From: Oleg Zharkov Date: Thu, 28 Jan 2021 19:01:36 +0100 Subject: [PATCH 01/16] initial impl --- client/package.json | 3 +- .../LibraryFolderPermissions.vue | 143 ++++++++++++++++++ .../LibraryFolderPermissions/services.js | 38 +++++ client/src/entry/analysis/AnalysisRouter.js | 8 + client/yarn.lock | 5 + lib/galaxy/webapps/galaxy/buildapp.py | 1 + 6 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 client/src/components/LibraryFolder/LibraryFolderPermissions/LibraryFolderPermissions.vue create mode 100644 client/src/components/LibraryFolder/LibraryFolderPermissions/services.js diff --git a/client/package.json b/client/package.json index 04561397485..44eaae21e1a 100644 --- a/client/package.json +++ b/client/package.json @@ -82,7 +82,8 @@ "vueisotope": "^3.1.2", "vuex": "^3.4.0", "vuex-cache": "^3.2.0", - "vuex-persist": "^3.1.3" + "vuex-persist": "^3.1.3", + "vue-observe-visibility": "^1.0.0" }, "scripts": { "watch": "gulp && yarn run save-build-hash && yarn run webpack-watch", diff --git a/client/src/components/LibraryFolder/LibraryFolderPermissions/LibraryFolderPermissions.vue b/client/src/components/LibraryFolder/LibraryFolderPermissions/LibraryFolderPermissions.vue new file mode 100644 index 00000000000..c4fae4d6d27 --- /dev/null +++ b/client/src/components/LibraryFolder/LibraryFolderPermissions/LibraryFolderPermissions.vue @@ -0,0 +1,143 @@ + + + diff --git a/client/src/components/LibraryFolder/LibraryFolderPermissions/services.js b/client/src/components/LibraryFolder/LibraryFolderPermissions/services.js new file mode 100644 index 00000000000..7ef7f581279 --- /dev/null +++ b/client/src/components/LibraryFolder/LibraryFolderPermissions/services.js @@ -0,0 +1,38 @@ +import axios from "axios"; +import { rethrowSimple } from "utils/simple-error"; +import { getAppRoot } from "onload/loadConfig"; + +export class Services { + constructor(options = {}) { + this.root = options.root || getAppRoot(); + } + + async getFolderPermissions(id) { + const url = `${this.root}api/folders/${id}/permissions?scope=current`; + 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 { + const response = await axios.get(url); + return response.data; + } catch (e) { + rethrowSimple(e); + } + } + async getSelectOptions(id, is_library_access, page, query) { + const page_limit = 10; + const url = `${this.root}api/folders/${id}/permissions?scope=available&is_library_access=${is_library_access}&page_limit=${page_limit}&page=${page}`; + try { + const response = await axios.get(url); + return response.data; + } catch (e) { + rethrowSimple(e); + } + } +} diff --git a/client/src/entry/analysis/AnalysisRouter.js b/client/src/entry/analysis/AnalysisRouter.js index 57b307aecb4..bbc21f1386f 100644 --- a/client/src/entry/analysis/AnalysisRouter.js +++ b/client/src/entry/analysis/AnalysisRouter.js @@ -30,6 +30,7 @@ import TrsImport from "components/Workflow/TrsImport.vue"; import TrsSearch from "components/Workflow/TrsSearch.vue"; import InteractiveTools from "components/InteractiveTools/InteractiveTools.vue"; import LibraryFolder from "components/LibraryFolder/LibraryFolder.vue"; +import LibraryFolderPermissions from "components/LibraryFolder/LibraryFolderPermissions/LibraryFolderPermissions.vue"; import WorkflowList from "components/Workflow/WorkflowList.vue"; import HistoryImport from "components/HistoryImport.vue"; import { HistoryExport } from "components/HistoryExport/index"; @@ -99,6 +100,7 @@ export const getAnalysisRouter = (Galaxy) => "(/)datasets/error": "show_dataset_error", "(/)interactivetool_entry_points(/)list": "show_interactivetool_list", "(/)library/folders(/)(:folder_id)": "show_library_folder", + "(/)library/folders-permissions(/)(:folder_id)": "manage_library_folder", }, require_login: ["show_user", "show_user_form", "show_workflows", "show_cloud_auth", "show_external_ids"], @@ -155,6 +157,12 @@ export const getAnalysisRouter = (Galaxy) => this._display_vue_helper(LibraryFolder, { folder_id: folder_id }); }, + manage_library_folder: function (folder_id) { + this.page.toolPanel?.component.hide(0); + this.page.panels.right.hide(); + this._display_vue_helper(LibraryFolderPermissions, { folder_id: folder_id }); + }, + show_cloud_auth: function () { this._display_vue_helper(CloudAuth); }, diff --git a/client/yarn.lock b/client/yarn.lock index b013e24e90e..cfabc39cf9c 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -15291,6 +15291,11 @@ vue-multiselect@^2.1.0: resolved "https://registry.yarnpkg.com/vue-multiselect/-/vue-multiselect-2.1.6.tgz#5be5d811a224804a15c43a4edbb7485028a89c7f" integrity sha512-s7jmZPlm9FeueJg1RwJtnE9KNPtME/7C8uRWSfp9/yEN4M8XcS/d+bddoyVwVnvFyRh9msFo0HWeW0vTL8Qv+w== +vue-observe-visibility@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/vue-observe-visibility/-/vue-observe-visibility-1.0.0.tgz#17cf1b2caf74022f0f3c95371468ddf2b9573152" + integrity sha512-s5TFh3s3h3Mhd3jaz3zGzkVHKHnc/0C/gNr30olO99+yw2hl3WBhK3ng3/f9OF+qkW4+l7GkmwfAzDAcY3lCFg== + vue-router@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.3.1.tgz#7d0545dd8ebf4f45494ca185b7eccb38d67689c1" diff --git a/lib/galaxy/webapps/galaxy/buildapp.py b/lib/galaxy/webapps/galaxy/buildapp.py index 411679e1cf6..181646c95a1 100644 --- a/lib/galaxy/webapps/galaxy/buildapp.py +++ b/lib/galaxy/webapps/galaxy/buildapp.py @@ -192,6 +192,7 @@ def app_pair(global_conf, load_app_kwds=None, wsgi_preflight=True, **kwargs): webapp.add_client_route('/custom_builds') 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}') # ==== Done # Indicate that all configuration settings have been provided From a0719278f50cc31f31a303cbdbcb7acaaa6b397e Mon Sep 17 00:00:00 2001 From: Oleg Zharkov Date: Fri, 29 Jan 2021 17:59:22 +0100 Subject: [PATCH 02/16] permission input fields as a sep component --- .../LibraryFolderPermissions.vue | 78 ++++++++++------- .../PermissionsInputField.vue | 85 +++++++++++++++++++ .../LibraryFolderPermissions/services.js | 22 ++++- 3 files changed, 152 insertions(+), 33 deletions(-) create mode 100644 client/src/components/LibraryFolder/LibraryFolderPermissions/PermissionsInputField.vue diff --git a/client/src/components/LibraryFolder/LibraryFolderPermissions/LibraryFolderPermissions.vue b/client/src/components/LibraryFolder/LibraryFolderPermissions/LibraryFolderPermissions.vue index c4fae4d6d27..e3dca804b09 100644 --- a/client/src/components/LibraryFolder/LibraryFolderPermissions/LibraryFolderPermissions.vue +++ b/client/src/components/LibraryFolder/LibraryFolderPermissions/LibraryFolderPermissions.vue @@ -33,18 +33,7 @@

Roles that can manage permissions on this folder

- - - +
User with any of these roles can manage permissions on this folder. @@ -52,14 +41,14 @@

Roles that can add items to this folder

-
+
User with any of these roles can add items to this folder (folders and datasets).

Roles that can modify this folder

-
+
User with any of these roles can modify this folder (name, etc.).
@@ -69,6 +58,7 @@ title="Save modifications" class="btn btn-secondary toolbtn_save_permissions primary-button" type="button" + @click="postPermissions" >  Save @@ -86,9 +76,12 @@ import Utils from "utils/utils"; import { Toast } from "ui/toast"; import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; import { getGalaxyInstance } from "app"; -import Multiselect from "vue-multiselect"; -import "vue-multiselect/dist/vue-multiselect.min.css"; +import PermissionsInputField from "./PermissionsInputField.vue"; +import "vue-multiselect/dist/vue-multiselect.min.css"; +import VueObserveVisibility from "vue-observe-visibility"; + +Vue.use(VueObserveVisibility); Vue.use(BootstrapVue); export default { @@ -99,15 +92,20 @@ export default { }, }, components: { - Multiselect, + PermissionsInputField, }, data() { return { - permissisons: undefined, + permissions: undefined, folder: undefined, is_admin: undefined, - options: { roles: [] }, value: null, + add_ids: [], + modify_ids: [], + manage_ids: [], + add_type: "add_type", + manage_type: "manage_type", + modify_type: "moddify_type", }; }, created() { @@ -117,27 +115,45 @@ export default { this.is_admin = Galaxy.user.attributes.is_admin; this.services.getFolderPermissions(this.folder_id).then((response) => { - this.permissisons = response; + this.permissions = response; }); this.services.getFolder(this.folder_id).then((response) => { this.folder = response; }); - this.getSelectOptions(); }, + methods: { - getSelectOptions() { - this.services.getSelectOptions(this.folder_id, true, 1).then((response) => { - console.log(response) - if (this.options.page > 1) { - this.options.roles.concat(response.roles); - } else { - this.options = response; - } - }); - }, getParentLink() { return `${this.root}library/folders/${this.folder.parent_id}`; }, + setUserPermissionsPreferences(ids, type) { + switch (type) { + case "manage": + this.manage_ids = ids; + break; + case "add": + this.add_ids = ids; + break; + case "modify": + this.modify_ids = ids; + break; + } + }, + postPermissions() { + this.services.setPermissions( + this.add_ids, + this.manage_ids, + this.modify_ids, + (fetched_permissions) => { + Toast.success("Permissions saved."); + this.permissions = fetched_permissions; + }, + (error) => { + Toast.error("An error occurred while attempting to set folder permissions."); + console.error(error); + } + ); + }, }, }; diff --git a/client/src/components/LibraryFolder/LibraryFolderPermissions/PermissionsInputField.vue b/client/src/components/LibraryFolder/LibraryFolderPermissions/PermissionsInputField.vue new file mode 100644 index 00000000000..5a3b5f4589c --- /dev/null +++ b/client/src/components/LibraryFolder/LibraryFolderPermissions/PermissionsInputField.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/client/src/components/LibraryFolder/LibraryFolderPermissions/services.js b/client/src/components/LibraryFolder/LibraryFolderPermissions/services.js index 7ef7f581279..77ed6121a87 100644 --- a/client/src/components/LibraryFolder/LibraryFolderPermissions/services.js +++ b/client/src/components/LibraryFolder/LibraryFolderPermissions/services.js @@ -25,8 +25,7 @@ export class Services { rethrowSimple(e); } } - async getSelectOptions(id, is_library_access, page, query) { - const page_limit = 10; + async getSelectOptions(id, is_library_access, page, page_limit, query) { const url = `${this.root}api/folders/${id}/permissions?scope=available&is_library_access=${is_library_access}&page_limit=${page_limit}&page=${page}`; try { const response = await axios.get(url); @@ -35,4 +34,23 @@ export class Services { rethrowSimple(e); } } + async setPermisions(access_ids, add_ids, manage_ids, modify_ids, onSuccess, onError) { + var formData = new FormData(); + formData.append("add_ids[]", access_ids); + formData.append("manage_ids[]", manage_ids); + formData.append("modify_ids[]", modify_ids); + + axios({ + method: "post", + url: "`${getAppRoot()}api/libraries/${self.id}/permissions?action=set_permissions`", + data: formData, + headers: { "Content-Type": "multipart/form-data" }, + }) + .then(function (response) { + onSuccess(response); + }) + .catch((response) => { + onError(response); + }); + } } From 90f39549c379f78421f71e4a56fbb97bcb961994 Mon Sep 17 00:00:00 2001 From: Oleg Zharkov Date: Fri, 29 Jan 2021 18:02:10 +0100 Subject: [PATCH 03/16] typo --- .../LibraryFolder/LibraryFolderPermissions/services.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/LibraryFolder/LibraryFolderPermissions/services.js b/client/src/components/LibraryFolder/LibraryFolderPermissions/services.js index 77ed6121a87..59f01357058 100644 --- a/client/src/components/LibraryFolder/LibraryFolderPermissions/services.js +++ b/client/src/components/LibraryFolder/LibraryFolderPermissions/services.js @@ -34,7 +34,7 @@ export class Services { rethrowSimple(e); } } - async setPermisions(access_ids, add_ids, manage_ids, modify_ids, onSuccess, onError) { + async setPermissions(access_ids, add_ids, manage_ids, modify_ids, onSuccess, onError) { var formData = new FormData(); formData.append("add_ids[]", access_ids); formData.append("manage_ids[]", manage_ids); From 22a7036a41fe9e24df96b2f17522077337c510ea Mon Sep 17 00:00:00 2001 From: Oleg Zharkov Date: Fri, 29 Jan 2021 18:07:02 +0100 Subject: [PATCH 04/16] fix SetPermissions --- .../LibraryFolderPermissions/LibraryFolderPermissions.vue | 8 ++++---- .../LibraryFolderPermissions/PermissionsInputField.vue | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/client/src/components/LibraryFolder/LibraryFolderPermissions/LibraryFolderPermissions.vue b/client/src/components/LibraryFolder/LibraryFolderPermissions/LibraryFolderPermissions.vue index e3dca804b09..55bce10b6b3 100644 --- a/client/src/components/LibraryFolder/LibraryFolderPermissions/LibraryFolderPermissions.vue +++ b/client/src/components/LibraryFolder/LibraryFolderPermissions/LibraryFolderPermissions.vue @@ -33,7 +33,7 @@

Roles that can manage permissions on this folder

- +
User with any of these roles can manage permissions on this folder. @@ -41,14 +41,14 @@

Roles that can add items to this folder

- +
User with any of these roles can add items to this folder (folders and datasets).

Roles that can modify this folder

- +
User with any of these roles can modify this folder (name, etc.).
@@ -105,7 +105,7 @@ export default { manage_ids: [], add_type: "add_type", manage_type: "manage_type", - modify_type: "moddify_type", + modify_type: "modify_type", }; }, created() { diff --git a/client/src/components/LibraryFolder/LibraryFolderPermissions/PermissionsInputField.vue b/client/src/components/LibraryFolder/LibraryFolderPermissions/PermissionsInputField.vue index 5a3b5f4589c..d285b8d6054 100644 --- a/client/src/components/LibraryFolder/LibraryFolderPermissions/PermissionsInputField.vue +++ b/client/src/components/LibraryFolder/LibraryFolderPermissions/PermissionsInputField.vue @@ -72,6 +72,7 @@ export default { } }, valueChanged() { + console.log(this.value) this.$emit("input", this.value, this.type); }, }, From be19c0a3da9ac31d8138d2cbb210e7e63a470bd0 Mon Sep 17 00:00:00 2001 From: Oleg Zharkov Date: Mon, 1 Feb 2021 18:13:32 +0100 Subject: [PATCH 05/16] butify view, fix bugs --- .../LibraryFolderPermissions.vue | 174 ++++++++++-------- .../PermissionsInputField.vue | 22 ++- .../LibraryFolderPermissions/services.js | 19 +- client/src/components/LibraryFolder/icons.js | 9 + 4 files changed, 136 insertions(+), 88 deletions(-) diff --git a/client/src/components/LibraryFolder/LibraryFolderPermissions/LibraryFolderPermissions.vue b/client/src/components/LibraryFolder/LibraryFolderPermissions/LibraryFolderPermissions.vue index 55bce10b6b3..8725957175e 100644 --- a/client/src/components/LibraryFolder/LibraryFolderPermissions/LibraryFolderPermissions.vue +++ b/client/src/components/LibraryFolder/LibraryFolderPermissions/LibraryFolderPermissions.vue @@ -1,69 +1,81 @@ @@ -72,17 +84,18 @@ import Vue from "vue"; import { getAppRoot } from "onload/loadConfig"; import BootstrapVue from "bootstrap-vue"; import { Services } from "./services"; -import Utils from "utils/utils"; 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 "vue-multiselect/dist/vue-multiselect.min.css"; import VueObserveVisibility from "vue-observe-visibility"; Vue.use(VueObserveVisibility); Vue.use(BootstrapVue); +initManageFolderIcons(); export default { props: { @@ -93,16 +106,16 @@ export default { }, components: { PermissionsInputField, + FontAwesomeIcon, }, data() { return { permissions: undefined, folder: undefined, is_admin: undefined, - value: null, - add_ids: [], - modify_ids: [], - manage_ids: [], + 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", @@ -113,9 +126,10 @@ export default { this.root = getAppRoot(); this.services = new Services({ root: this.root }); this.is_admin = Galaxy.user.attributes.is_admin; - - this.services.getFolderPermissions(this.folder_id).then((response) => { - this.permissions = response; + 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.services.getFolder(this.folder_id).then((response) => { this.folder = response; @@ -126,24 +140,25 @@ export default { getParentLink() { return `${this.root}library/folders/${this.folder.parent_id}`; }, - setUserPermissionsPreferences(ids, type) { - switch (type) { - case "manage": - this.manage_ids = ids; + setUserPermissionsPreferences(ids, permission_type) { + switch (permission_type) { + case "manage_type": + this.manage_folder_role_list = ids; break; - case "add": - this.add_ids = ids; + case "add_type": + this.add_library_item_role_list = ids; break; - case "modify": - this.modify_ids = ids; + case "modify_type": + this.modify_folder_role_list = ids; break; } }, postPermissions() { this.services.setPermissions( - this.add_ids, - this.manage_ids, - this.modify_ids, + this.folder_id, + this.add_library_item_role_list, + this.manage_folder_role_list, + this.modify_folder_role_list, (fetched_permissions) => { Toast.success("Permissions saved."); this.permissions = fetched_permissions; @@ -154,6 +169,15 @@ 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; + }, }, }; diff --git a/client/src/components/LibraryFolder/LibraryFolderPermissions/PermissionsInputField.vue b/client/src/components/LibraryFolder/LibraryFolderPermissions/PermissionsInputField.vue index d285b8d6054..9991bb87b44 100644 --- a/client/src/components/LibraryFolder/LibraryFolderPermissions/PermissionsInputField.vue +++ b/client/src/components/LibraryFolder/LibraryFolderPermissions/PermissionsInputField.vue @@ -1,8 +1,8 @@