From 60ad9e934b3e4c50389a624a28578aa9fc326f32 Mon Sep 17 00:00:00 2001 From: Eric Rasche Date: Sat, 22 Nov 2014 13:18:08 -0600 Subject: [PATCH 1/5] Enable user/email list for sharing of datasets --- config/galaxy.ini.sample | 8 ++++ lib/galaxy/config.py | 3 ++ lib/galaxy/webapps/galaxy/api/users.py | 10 ++++- templates/webapps/galaxy/history/share.mako | 46 +++++++++++++++++++-- 4 files changed, 63 insertions(+), 4 deletions(-) diff --git a/config/galaxy.ini.sample b/config/galaxy.ini.sample index 57521ce8950..99c79abfac9 100644 --- a/config/galaxy.ini.sample +++ b/config/galaxy.ini.sample @@ -740,6 +740,14 @@ use_interactive = True # public. #new_user_dataset_access_role_default_private = False +# Expose user list. Setting this to true will expose the user list to authenticated users. This +# makes sharing datasets in smaller galaxy instances much easier as they can type a name/email and +# have the correct user show up. This makes less sense on large public galaxy instances where +# that data shouldn't be exposed. For semi-public galaxies, it may make sense to expose just the +# username and not email, or vice versa. +#expose_user_name = False +#expose_user_email = False + # -- Beta features # Use new tool form diff --git a/lib/galaxy/config.py b/lib/galaxy/config.py index 0f660b11ea7..a0707e89ea3 100644 --- a/lib/galaxy/config.py +++ b/lib/galaxy/config.py @@ -92,6 +92,9 @@ class Configuration( object ): self.user_label_filters = listify( kwargs.get( "user_tool_label_filters", [] ), do_strip=True ) self.user_section_filters = listify( kwargs.get( "user_tool_section_filters", [] ), do_strip=True ) + self.expose_user_name = kwargs.get( "expose_user_name", False ) + self.expose_user_email = kwargs.get( "expose_user_email", False ) + # Check for tools defined in the above non-shed tool configs (i.e., tool_conf.xml) tht have # been migrated from the Galaxy code distribution to the Tool Shed. self.check_migrate_tools = string_as_bool( kwargs.get( 'check_migrate_tools', True ) ) diff --git a/lib/galaxy/webapps/galaxy/api/users.py b/lib/galaxy/webapps/galaxy/api/users.py index ef8bcdf206e..4265d7f12e0 100644 --- a/lib/galaxy/webapps/galaxy/api/users.py +++ b/lib/galaxy/webapps/galaxy/api/users.py @@ -37,11 +37,19 @@ class UserAPIController( BaseAPIController, UsesTagsMixin, CreatesUsersMixin, Cr else: query = query.filter( trans.app.model.User.table.c.deleted == False ) # noqa # special case: user can see only their own user - if not trans.user_is_admin(): + # special case2: if the galaxy admin has specified that other user email/names are + # exposed, we don't want special case #1 + if not trans.user_is_admin() and not trans.app.config.expose_user_name and not trans.app.config.expose_user_email: item = trans.user.to_dict( value_mapper={ 'id': trans.security.encode_id } ) return [item] for user in query: item = user.to_dict( value_mapper={ 'id': trans.security.encode_id } ) + # If NOT configured to expose_email, do not expose email UNLESS the user is self, or + # the user is an admin + if not trans.app.config.expose_user_name and user is not trans.user and not trans.user_is_admin(): + del item['username'] + if not trans.app.config.expose_user_email and user is not trans.user and not trans.user_is_admin(): + del item['email'] # TODO: move into api_values rval.append( item ) return rval diff --git a/templates/webapps/galaxy/history/share.mako b/templates/webapps/galaxy/history/share.mako index 48aca6e5ed4..fa5f32044fb 100644 --- a/templates/webapps/galaxy/history/share.mako +++ b/templates/webapps/galaxy/history/share.mako @@ -37,9 +37,8 @@
-
- -
+ +
Enter a Galaxy user email address or a comma-separated list of addresses if sharing with multiple users
@@ -55,6 +54,47 @@
+ %else: ## We are sharing restricted histories %if no_change_needed or can_change: From 7eb51aa895951824347c0e28b1f6169881b14b1e Mon Sep 17 00:00:00 2001 From: Eric Rasche Date: Tue, 25 Nov 2014 13:19:28 -0600 Subject: [PATCH 2/5] Must expose username in controller as well --- lib/galaxy/model/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/galaxy/model/__init__.py b/lib/galaxy/model/__init__.py index e0984d8288a..db2fc6f8fdc 100644 --- a/lib/galaxy/model/__init__.py +++ b/lib/galaxy/model/__init__.py @@ -130,7 +130,7 @@ class User( object, Dictifiable ): histories, credentials, and roles. """ # attributes that will be accessed and returned when calling to_dict( view='collection' ) - dict_collection_visible_keys = ( 'id', 'email' ) + dict_collection_visible_keys = ( 'id', 'email', 'username' ) # attributes that will be accessed and returned when calling to_dict( view='element' ) dict_element_visible_keys = ( 'id', 'email', 'username', 'total_disk_usage', 'nice_total_disk_usage' ) From 918f8b674ec8ccf7674c31d5eea5ae1ab57fe3ba Mon Sep 17 00:00:00 2001 From: Eric Rasche Date: Thu, 5 Feb 2015 17:37:10 -0600 Subject: [PATCH 3/5] Fixes for allowing custom entry --- templates/webapps/galaxy/history/share.mako | 89 ++++++++++++++++----- 1 file changed, 68 insertions(+), 21 deletions(-) diff --git a/templates/webapps/galaxy/history/share.mako b/templates/webapps/galaxy/history/share.mako index 2cb9104db85..191a37bb393 100644 --- a/templates/webapps/galaxy/history/share.mako +++ b/templates/webapps/galaxy/history/share.mako @@ -59,38 +59,85 @@ /* This should be ripped out and made generic at some point for the * various API bindings available, and once the API can filter list * queries (term, below) */ + + var user_id = "${trans.security.encode_id(trans.user.id)}"; + var history_id = "${trans.security.encode_id( history.id )}"; + + function item_to_label(item){ + var text = ""; + if(typeof(item.username) === "string" && typeof(item.email) === "string"){ + text = item.username + " <" + item.email + ">"; + }else if(typeof(item.username) === "string"){ + text = item.username; + }else{ + text = item.email; + } + return text; + //return "id:" + item.id + "|e:" + item.email + "|u:" + item.username; + } + $("#email_select").select2({ placeholder: "Select a user", + multiple: true, + initSelection: function(element, callback) { + var data = [ + // Must be here to loop across the users that this has been shared with. + %for i, association in enumerate( history.users_shared_with ): + <% shared_with = association.user %> + { + email: "${ shared_with.email }", + id: "${trans.security.encode_id(shared_with.id)}", + text: item_to_label({"email": "${ shared_with.email }", "username": "${ shared_with.username }" }) + }, + %endfor + ]; + callback(data); + }, + tokenSeparators: [',', ' '], + // Required for initSelection + id: function(object) { + return object.id; + }, ajax: { url: "${h.url_for(controller="/api/users", action="index")}", - dataType: 'json', - quietMillis: 250, - matcher: function(term, text) { return text.toUpperCase().indexOf(term.toUpperCase())>=0; }, data: function (term) { return { f_email: term }; }, + dataType: 'json', + quietMillis: 250, results: function (data) { - var results = []; - $.each(data, function(index, item){ - var text = ""; - if(typeof(item.username) === "string" && typeof(item.email) === "string"){ - text = item.username + " <" + item.email + ">"; - }else if(typeof(item.username) === "string"){ - text = item.username; - }else{ - text = item.email; + var results = []; + // For every user returned by the API call, + $.each(data, function(index, item){ + // If they aren't the requesting user, add to the + // list that will populate the select + if(item.id != "${trans.security.encode_id(trans.user.id)}"){ + results.push({ + id: item.id, + name: item.username, + text: item_to_label(item), + }); } - results.push({ - id: item.email, - name: item.username, - text: text - }); - }); - return { - results: results - }; + }); + return { + results: results + }; + } + }, + createSearchChoice: function(term, data) { + // Check for a user with a matching email. + var matches = _.filter(data, function(user){ + return user.text.indexOf(term) > -1; + }); + // If there aren't any users with matching object labels, then + // display a "default" entry with whatever text they're entering. + // id is set to term as that will be used in + if(matches.length == 0){ + return {id: term, text:term}; + }else{ + // No extra needed } } }); From 0785677d403aaac6cc3de0e2944e966bbd891d12 Mon Sep 17 00:00:00 2001 From: Eric Rasche Date: Mon, 9 Feb 2015 15:17:40 -0600 Subject: [PATCH 4/5] Use suggestion from Carl to fix initial selection --- templates/webapps/galaxy/history/share.mako | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/templates/webapps/galaxy/history/share.mako b/templates/webapps/galaxy/history/share.mako index 191a37bb393..ba533028cd4 100644 --- a/templates/webapps/galaxy/history/share.mako +++ b/templates/webapps/galaxy/history/share.mako @@ -36,8 +36,9 @@
+ <% existing_emails = [ d.user.email for d in history.users_shared_with ] %> - +
Enter a Galaxy user email address or a comma-separated list of addresses if sharing with multiple users From 04fa989efc681d7c1e1ef1add97f3285a057f566 Mon Sep 17 00:00:00 2001 From: Eric Rasche Date: Thu, 12 Feb 2015 14:32:10 -0600 Subject: [PATCH 5/5] Works correctly now --- templates/webapps/galaxy/history/share.mako | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/webapps/galaxy/history/share.mako b/templates/webapps/galaxy/history/share.mako index ba533028cd4..98fea0911ba 100644 --- a/templates/webapps/galaxy/history/share.mako +++ b/templates/webapps/galaxy/history/share.mako @@ -36,7 +36,7 @@
- <% existing_emails = [ d.user.email for d in history.users_shared_with ] %> + <% existing_emails = ','.join([ d.user.email for d in history.users_shared_with ]) %>