Merged in erasche2/galaxy-central (pull request #570)

Enable user/email list for sharing of datasets
This commit is contained in:
Dannon Baker
2015-02-17 09:46:09 -05:00
5 changed files with 112 additions and 5 deletions
+8
View File
@@ -786,6 +786,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
+3
View File
@@ -106,6 +106,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 ) )
+1 -1
View File
@@ -131,7 +131,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' )
+9 -1
View File
@@ -43,11 +43,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
+91 -3
View File
@@ -36,10 +36,10 @@
</div>
<div style="clear: both"></div>
<div class="form-row">
<% existing_emails = ','.join([ d.user.email for d in history.users_shared_with ]) %>
<label>Galaxy user emails with which to share histories</label>
<div style="float: left; width: 250px; margin-right: 10px;">
<input type="text" name="email" value="${email}" size="40">
</div>
<input type="hidden" id="email_select" name="email" value="${ existing_emails }" style="float: left; width: 250px; margin-right: 10px;">
</input>
<div class="toolParamHelp" style="clear: both;">
Enter a Galaxy user email address or a comma-separated list of addresses if sharing with multiple users
</div>
@@ -55,6 +55,94 @@
<input type="submit" name="share_button" value="Submit">
</div>
</form>
<script type="text/javascript">
// stolen from templates/admin/impersonate.mako
/* 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")}",
data: function (term) {
return {
f_email: term
};
},
dataType: 'json',
quietMillis: 250,
results: function (data) {
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),
});
}
});
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
}
}
});
</script>
%else:
## We are sharing restricted histories
%if no_change_needed or can_change: