Merge pull request #3118 from bgruening/remove_mako_user_pref

New User Preferences User Interface
This commit is contained in:
Martin Cech
2016-11-30 08:58:25 -05:00
committed by GitHub
55 changed files with 1292 additions and 1614 deletions
+9 -4
View File
@@ -8,6 +8,7 @@ var jQuery = require( 'jquery' ),
HistoryPanel = require( './history-panel' ),
PAGE = require( 'layout/page' ),
ToolForm = require( 'mvc/tool/tool-form' ),
UserPreferences = require( 'mvc/user/user-preferences' );
Tours = require( 'mvc/tours' );
/** define the 'Analyze Data'/analysis/main/home page for Galaxy
@@ -100,17 +101,21 @@ window.app = function app( options, bootstrapped ){
// TODO: remove annoying 'root' from root urls
'(/)root*' : 'home',
'(/)tours(/)(:tour_id)' : 'show_tours',
'(/)users(/)' : 'show_users',
},
show_tours : function( tour_id ){
if (tour_id){
Tours.giveTour(tour_id);
}
else{
if ( tour_id ){
Tours.giveTour( tour_id );
} else {
centerPanel.display( new Tours.ToursView() );
}
},
show_users : function(){
centerPanel.display( new UserPreferences.View() );
},
/** */
home : function( params ){
// TODO: to router, remove Globals
+6 -12
View File
@@ -235,8 +235,11 @@ var Collection = Backbone.Collection.extend({
title : 'Logged in as ' + Galaxy.user.get( 'email' )
},{
title : 'Preferences',
url : 'user?cntrller=user',
target : 'galaxy_main'
url : 'users',
target : 'galaxy_main',
onclick : function() {
window.location = Galaxy.root + 'users';
}
},{
title : 'Custom Builds',
url : 'user/dbkeys',
@@ -258,17 +261,8 @@ var Collection = Backbone.Collection.extend({
title : 'Saved Pages',
url : 'page/list',
target : '_top'
},{
title : 'API Keys',
url : 'user/api_keys?cntrller=user',
target : 'galaxy_main'
}]
}]
};
options.use_remote_user && userTab.menu.push({
title : 'Public Name',
url : 'user/edit_username?cntrller=user',
target : 'galaxy_main'
});
this.add( userTab );
}
var activeView = this.get( options.active_view );
+3 -2
View File
@@ -138,14 +138,15 @@ var PageLayoutView = Backbone.View.extend( BaseMVC.LoggableMixin ).extend({
_checkCommunicationServerOnline: function(){
var host = window.Galaxy.config.communication_server_host,
port = window.Galaxy.config.communication_server_port,
preferences = window.Galaxy.user.attributes.preferences,
$chat_icon_element = $( "#show-chat-online" );
/** Check if the user has deactivated the communication in it's personal settings */
if (window.Galaxy.user.attributes.preferences !== undefined && window.Galaxy.user.attributes.preferences.communication_server === '1') {
if ( preferences && [ '1', 'true' ].indexOf( preferences.communication_server ) != -1 ) {
// See if the configured communication server is available
$.ajax({
url: host + ":" + port,
})
.success( function( data ) {
.success( function( data ) {
// enable communication only when a user is logged in
if( window.Galaxy.user.id !== null ) {
if( $chat_icon_element.css( "visibility") === "hidden" ) {
@@ -14,6 +14,7 @@ define(['utils/utils',
/** Available parameter types */
types: {
'text' : '_fieldText',
'password' : '_fieldText',
'select' : '_fieldSelect',
'data_column' : '_fieldSelect',
'genomebuild' : '_fieldSelect',
@@ -146,7 +147,9 @@ define(['utils/utils',
// create input element
return new Ui.Input({
id : 'field-' + input_def.id,
type : input_def.type,
area : input_def.area,
readonly : input_def.readonly,
placeholder : input_def.placeholder,
onchange : input_def.onchange
});
@@ -104,7 +104,7 @@ function( Utils, Ui, Portlet, Repeat, InputElement, Parameters ) {
// add parsed/minimum number of repeat blocks
//
var n_cache = _.size( input_def.cache );
for ( var i = 0; i < Math.max( Math.max( n_cache, input_def.min ), input_def.default || 0 ); i++ ) {
for ( var i = 0; i < Math.max( Math.max( n_cache, input_def.min || 0 ), input_def.default || 0 ); i++ ) {
create( i < n_cache ? input_def.cache[ i ] : input_def.inputs );
}
+5 -1
View File
@@ -85,6 +85,7 @@ define(['utils/utils',
type : 'text',
placeholder : '',
disabled : false,
readonly : false,
visible : true,
cls : '',
area : false,
@@ -104,6 +105,7 @@ define(['utils/utils',
return this.model.get( 'value' );
},
render: function() {
var self = this;
this.$el.removeClass()
.addClass( 'ui-' + this.tagName )
.addClass( this.model.get( 'cls' ) )
@@ -116,7 +118,9 @@ define(['utils/utils',
if ( this.model.get( 'value' ) !== this.$el.val() ) {
this.$el.val( this.model.get( 'value' ) );
}
this.model.get( 'disabled' ) ? this.$el.attr( 'disabled', true ) : this.$el.removeAttr( 'disabled' );
_.each( [ 'readonly', 'disabled' ], function( attr_name ) {
self.model.get( attr_name ) ? self.$el.attr( attr_name, true ) : self.$el.removeAttr( attr_name );
});
this.$el[ this.model.get( 'visible' ) ? 'show' : 'hide' ]();
return this;
},
@@ -0,0 +1,198 @@
/** User Preferences view */
define( [ 'mvc/form/form-view', 'mvc/ui/ui-misc' ], function( Form, Ui ) {
var View = Backbone.View.extend({
initialize: function() {
this.defs = {
'information': {
title : 'Manage information',
description : 'Edit your email, addresses and custom parameters or change your username.',
url : 'api/users/' + Galaxy.user.id + '/information/inputs',
icon : 'fa-user'
},
'password': {
title : 'Change password',
description : 'Allows you to change your login credentials.',
icon : 'fa-unlock-alt',
url : 'api/users/' + Galaxy.user.id + '/password/inputs',
submit_title : 'Save password',
},
'communication': {
title : 'Change communication settings',
description : 'Enable or disable the communication feature to chat with other users.',
url : 'api/users/' + Galaxy.user.id + '/communication/inputs',
icon : 'fa-comments-o'
},
'permissions': {
title : 'Set dataset permissions for new histories',
description : 'Grant others default access to newly created histories. Changes made here will only affect histories created after these settings have been stored.',
url : 'api/users/' + Galaxy.user.id + '/permissions/inputs',
icon : 'fa-users',
submit_title : 'Save permissions'
},
'api_key': {
title : 'Manage API key',
description : 'Access your current API key or create a new one.',
url : 'api/users/' + Galaxy.user.id + '/api_key/inputs',
icon : 'fa-key',
submit_title : 'Create a new key',
submit_icon : 'fa-check'
},
'toolbox_filters': {
title : 'Manage Toolbox filters',
description : 'Customize your Toolbox by displaying or omitting sets of Tools.',
url : 'api/users/' + Galaxy.user.id + '/toolbox_filters/inputs',
icon : 'fa-filter',
submit_title : 'Save filters'
},
'openids': {
title : 'Manage OpenIDs',
description : 'Associate OpenIDs with your account.',
icon : 'fa-openid',
onclick : function() {
window.location.href = Galaxy.root + 'user/openid_manage?cntrller=user&use_panels=True';
}
},
'logout': {
title : 'Sign out',
description : 'Click here to sign out of all sessions.',
icon : 'fa-sign-out',
onclick : function() {
Galaxy.modal.show({
title : 'Sign out',
body : 'Do you want to continue and sign out of all active sessions?',
buttons : {
'Cancel' : function() { Galaxy.modal.hide(); },
'Sign out' : function() { window.location.href = Galaxy.root + 'user/logout'; }
}
});
}
}
}
this.message = new Ui.Message();
this.setElement( '<div/>' );
this.render();
},
render: function() {
var self = this;
var config = Galaxy.config;
$.getJSON( Galaxy.root + 'api/users/' + Galaxy.user.id, function( data ) {
self.$preferences = $( '<div/>' ).addClass( 'ui-panel' )
.append( self.message.$el )
.append( $( '<h2/>' ).append( 'User preferences' ) )
.append( $( '<p/>' ).append( 'You are logged in as <strong>' + _.escape( data.email ) + '</strong>.' ) )
.append( self.$table = $( '<table/>' ).addClass( 'ui-panel-table' ) );
if( !config.use_remote_user ) {
self._link( self.defs.information );
self._link( self.defs.password );
}
if( config.enable_communication_server ) {
self._link( self.defs.communication );
}
self._link( self.defs.permissions );
self._link( self.defs.api_key );
if( config.has_user_tool_filters ) {
self._link( self.defs.toolbox_filters );
}
if( config.enable_openid && !config.use_remote_user ) {
self._link( self.defs.openids );
}
self._link( self.defs.logout );
self.$preferences.append( self._templateFooter( data ) );
self.$el.empty().append( self.$preferences );
});
},
_link: function( page ) {
var self = this;
var $page_item = $( this._templateRow( page ) );
this.$table.append( $page_item );
$page_item.find( 'a' ).on( 'click', function() {
if ( page.url ) {
$.ajax({
url : Galaxy.root + page.url,
type : 'GET'
}).done( function( response ) {
var options = $.extend( {}, page, response );
var form = new Form({
title : options.title,
icon : options.icon,
inputs : options.inputs,
operations: {
'submit': new Ui.ButtonIcon({
tooltip : options.submit_tooltip,
title : options.submit_title || 'Save settings',
icon : options.submit_icon || 'fa-save',
onclick : function() { self._submit( form, options ) }
}),
'back': new Ui.ButtonIcon({
icon : 'fa-caret-left',
tooltip : 'Return to user preferences',
title : 'Preferences',
onclick : function() { form.remove(); self.$preferences.show(); }
})
}
});
self.$preferences.hide();
self.$el.append( form.$el );
}).fail( function( response ) {
self.message.update( { message: 'Failed to load resource ' + page.url + '.', status: 'danger' } );
})
} else {
page.onclick();
}
});
},
_submit: function( form, options ) {
var self = this;
$.ajax( {
url : options.url,
data : JSON.stringify(form.data.create()),
type : 'PUT',
contentType : 'application/json'
}).done( function( response ) {
var updated_values = false;
form.data.matchModel( response, function ( input, input_id ) {
form.field_list[ input_id ].value( input.value );
updated_values = true;
});
if ( updated_values ) {
form.message.update( { message: response.message, status: 'success' } );
} else {
form.remove();
self.$preferences.show();
self.message.update( { message: response.message, status: 'success' } );
}
}).fail( function( response ) {
form.message.update( { message: response.responseJSON.err_msg, status: 'danger' } );
});
},
_templateRow: function( options ) {
return '<tr>' +
'<td>' +
'<div class="ui-panel-icon fa ' + options.icon + '">' +
'</td>' +
'<td>' +
'<a class="ui-panel-anchor" href="javascript:void(0)">' + options.title + '</a>' +
'<div class="ui-form-info">' + options.description + '</div>' +
'</td>' +
'</tr>';
},
_templateFooter: function( options ) {
return '<p class="ui-panel-footer">' +
'You are using <strong>' + options.nice_total_disk_usage + '</strong> of disk space in this Galaxy instance. ' +
( Galaxy.config.enable_quotas ? 'Your disk quota is: <strong>' + options.quota + '</strong>. ' : '' ) +
'Is your usage more than expected? See the <a href="https://wiki.galaxyproject.org/Learn/ManagingDatasets" target="_blank">documentation</a> for tips on how to find all of the data in your account.' +
'</p>';
}
});
return {
View: View
};
});
+2 -4
View File
@@ -1732,7 +1732,6 @@ div.toolTitleNoSection
}
// communication channel bootstrap modal
.chat-modal {
overflow: hidden;
}
@@ -1758,7 +1757,7 @@ div.toolTitleNoSection
}
// password complexity monitor
#change_password,#registrationForm {
#change_password, #registrationForm {
.progress {
width:200px;
margin-left: 20px;
@@ -1767,5 +1766,4 @@ div.toolTitleNoSection
color:black;
text-align:left;
}
}
}
+20
View File
@@ -177,6 +177,25 @@
padding-right: 3px !important;
}
// panel
.ui-panel {
.ui-panel-table {
margin-left: 20px;
margin-right: 20px;
.ui-panel-icon {
margin: 10px;
margin-right: 20px;
font-size: 1.6em;
}
.ui-panel-anchor {
font-weight: bold;
}
}
.ui-panel-footer {
margin-top: 10px;
}
}
// tabs
.ui-tabs {
.tab-operations {
@@ -444,6 +463,7 @@
word-wrap: break-word;
display: inline;
vertical-align: middle;
font-weight: bold;
.portlet-title-text {
vertical-align: middle;
line-height: 22px;
+3
View File
@@ -1004,6 +1004,9 @@ use_interactive = True
# Enable new run workflow form
#run_workflow_toolform_upgrade = True
# Enable new preferences which showcases new UI for the user preferences
#enable_new_user_preferences = False
# Enable Galaxy to communicate directly with a sequencer
#enable_sequencer_communication = False
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3 -3
View File
@@ -61,7 +61,7 @@ class AuthManager(object):
if auth_result is True:
break
if auth_result is None:
message = 'Invalid email address/username or password'
message = 'Invalid email address/username or password.'
status = 'error'
break
elif allow_reg is True:
@@ -134,10 +134,10 @@ class AuthManager(object):
if _get_bool(options, "allow-password-change", False):
return (True, '') # accept user
else:
return (False, 'Password change not supported')
return (False, 'Password change not supported.')
elif auth_result is None:
break # end authentication (skip rest)
return (False, 'Invalid current password')
return (False, 'Invalid current password.')
def active_authenticators(self, email, username, password):
"""Yields AuthProvider instances for the provided configfile that match the
+5 -2
View File
@@ -98,8 +98,9 @@ class Configuration( object ):
self.tool_section_filters = listify( kwargs.get( "tool_section_filters", [] ), do_strip=True )
self.user_tool_filters = listify( kwargs.get( "user_tool_filters", [] ), do_strip=True )
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.user_tool_label_filters = listify( kwargs.get( "user_tool_label_filters", [] ), do_strip=True )
self.user_tool_section_filters = listify( kwargs.get( "user_tool_section_filters", [] ), do_strip=True )
self.has_user_tool_filters = bool( self.user_tool_filters or self.user_tool_label_filters or self.user_tool_section_filters )
self.tour_config_dir = resolve_path( kwargs.get("tour_config_dir", "config/plugins/tours"), self.root)
self.webhooks_dirs = resolve_path( kwargs.get("webhooks_dir", "config/plugins/webhooks"), self.root)
@@ -220,6 +221,8 @@ class Configuration( object ):
self.communication_server_host = kwargs.get( 'communication_server_host', 'http://localhost' )
self.communication_server_port = int( kwargs.get( 'communication_server_port', '7070' ) )
self.persistent_communication_rooms = listify( kwargs.get( "persistent_communication_rooms", [] ), do_strip=True )
self.enable_openid = string_as_bool( kwargs.get( 'enable_openid', 'False' ) )
self.enable_quotas = string_as_bool( kwargs.get( 'enable_quotas', 'False' ) )
# External Service types used in sample tracking
self.external_service_type_path = resolve_path( kwargs.get( 'external_service_type_path', 'external_service_types' ), self.root )
# Tasked job runner.
+43 -40
View File
@@ -33,50 +33,53 @@ class ConfigSerializer( base.ModelSerializer ):
self.serializers = {
# TODO: this is available from user data, remove
'is_admin_user' : lambda *a, **c: False,
'is_admin_user' : lambda *a, **c: False,
'brand' : _defaults_to( '' ),
'brand' : _defaults_to( '' ),
# TODO: this doesn't seem right
'logo_url' : lambda i, k, **c: self.url_for( i.get( k, '/' ) ),
'logo_src' : lambda i, k, **c: self.url_for( '/static/images/galaxyIcon_noText.png' ),
'terms_url' : _defaults_to( '' ),
'logo_url' : lambda i, k, **c: self.url_for( i.get( k, '/' ) ),
'logo_src' : lambda i, k, **c: self.url_for( '/static/images/galaxyIcon_noText.png' ),
'terms_url' : _defaults_to( '' ),
# TODO: don't hardcode here - hardcode defaults once in config.py
'wiki_url' : _defaults_to( "http://galaxyproject.org/" ),
'search_url' : _defaults_to( "http://galaxyproject.org/search/usegalaxy/" ),
'mailing_lists' : _defaults_to( "https://wiki.galaxyproject.org/MailingLists" ),
'screencasts_url' : _defaults_to( "https://vimeo.com/galaxyproject" ),
'citation_url' : _defaults_to( "https://wiki.galaxyproject.org/CitingGalaxy" ),
'support_url' : _defaults_to( "https://wiki.galaxyproject.org/Support" ),
'lims_doc_url' : _defaults_to( "https://usegalaxy.org/u/rkchak/p/sts" ),
'biostar_url' : _defaults_to( '' ),
'biostar_url_redirect' : lambda *a, **c: self.url_for( controller='biostar', action='biostar_redirect',
qualified=True ),
'wiki_url' : _defaults_to( "http://galaxyproject.org/" ),
'search_url' : _defaults_to( "http://galaxyproject.org/search/usegalaxy/" ),
'mailing_lists' : _defaults_to( "https://wiki.galaxyproject.org/MailingLists" ),
'screencasts_url' : _defaults_to( "https://vimeo.com/galaxyproject" ),
'citation_url' : _defaults_to( "https://wiki.galaxyproject.org/CitingGalaxy" ),
'support_url' : _defaults_to( "https://wiki.galaxyproject.org/Support" ),
'lims_doc_url' : _defaults_to( "https://usegalaxy.org/u/rkchak/p/sts" ),
'biostar_url' : _defaults_to( '' ),
'biostar_url_redirect' : lambda *a, **c: self.url_for( controller='biostar', action='biostar_redirect', qualified=True ),
'communication_server_host' : _defaults_to( None ),
'communication_server_port' : _defaults_to( None ),
'persistent_communication_rooms' : _defaults_to( None ),
'allow_user_creation' : _defaults_to( False ),
'use_remote_user' : _defaults_to( None ),
'remote_user_logout_href' : _defaults_to( '' ),
'datatypes_disable_auto' : _defaults_to( False ),
'allow_user_dataset_purge' : _defaults_to( False ),
'ga_code' : _defaults_to( None ),
'enable_unique_workflow_defaults' : _defaults_to( False ),
'enable_communication_server' : _defaults_to( False ),
'communication_server_port' : _defaults_to( None ),
'communication_server_host' : _defaults_to( None ),
'persistent_communication_rooms' : _defaults_to( None ),
'allow_user_creation' : _defaults_to( False ),
'use_remote_user' : _defaults_to( None ),
'enable_openid' : _defaults_to( False ),
'enable_quotas' : _defaults_to( False ),
'remote_user_logout_href' : _defaults_to( '' ),
'datatypes_disable_auto' : _defaults_to( False ),
'allow_user_dataset_purge' : _defaults_to( False ),
'ga_code' : _defaults_to( None ),
'enable_unique_workflow_defaults' : _defaults_to( False ),
'has_user_tool_filters' : _defaults_to( False ),
# TODO: is there no 'correct' way to get an api url? controller='api', action='tools' is a hack
# at any rate: the following works with path_prefix but is still brittle
# TODO: change this to (more generic) upload_path and incorporate config.nginx_upload_path into building it
'nginx_upload_path' : lambda i, k, **c: getattr( i, k, False ) or self.url_for( '/api/tools' ),
'ftp_upload_dir' : _defaults_to( None ),
'ftp_upload_site' : _defaults_to( None ),
'version_major' : _defaults_to( None ),
'require_login' : _defaults_to( None ),
'inactivity_box_content' : _defaults_to( None ),
'message_box_content' : _defaults_to( None ),
'message_box_visible' : _defaults_to( False ),
'message_box_class' : _defaults_to( 'info' ),
'server_startttime' : lambda i, k, **c: server_starttime,
'nginx_upload_path' : lambda i, k, **c: getattr( i, k, False ) or self.url_for( '/api/tools' ),
'ftp_upload_dir' : _defaults_to( None ),
'ftp_upload_site' : _defaults_to( None ),
'version_major' : _defaults_to( None ),
'require_login' : _defaults_to( None ),
'inactivity_box_content' : _defaults_to( None ),
'message_box_content' : _defaults_to( None ),
'message_box_visible' : _defaults_to( False ),
'message_box_class' : _defaults_to( 'info' ),
'server_startttime' : lambda i, k, **c: server_starttime,
}
@@ -91,10 +94,10 @@ class AdminConfigSerializer( ConfigSerializer ):
self.serializers.update({
# TODO: this is available from user serialization: remove
'is_admin_user' : lambda *a: True,
'is_admin_user' : lambda *a: True,
'library_import_dir' : _defaults_to( None ),
'user_library_import_dir' : _defaults_to( None ),
'allow_library_path_paste' : _defaults_to( False ),
'allow_user_deletion' : _defaults_to( False ),
'library_import_dir' : _defaults_to( None ),
'user_library_import_dir' : _defaults_to( None ),
'allow_library_path_paste' : _defaults_to( False ),
'allow_user_deletion' : _defaults_to( False ),
})
+5 -2
View File
@@ -201,8 +201,9 @@ class UserManager( base.ModelManager, deletable.PurgableManagerMixin ):
def default_permissions( self, user ):
return self.app.security_agent.user_get_default_permissions( user )
def quota( self, user ):
# TODO: use quota manager
def quota( self, user, total=False ):
if total:
return self.app.quota_agent.get_quota( user, nice_size=True )
return self.app.quota_agent.get_percent( user=user )
def tags_used( self, user, tag_models=None ):
@@ -263,6 +264,7 @@ class UserSerializer( base.ModelSerializer, deletable.PurgableSerializerMixin ):
'total_disk_usage',
'nice_total_disk_usage',
'quota_percent',
'quota',
'deleted',
'purged',
# 'active',
@@ -288,6 +290,7 @@ class UserSerializer( base.ModelSerializer, deletable.PurgableSerializerMixin ):
'total_disk_usage' : lambda i, k, **c: float( i.total_disk_usage ),
'quota_percent' : lambda i, k, **c: self.user_manager.quota( i ),
'quota' : lambda i, k, **c: self.user_manager.quota( i, total=True ),
'tags_used' : lambda i, k, **c: self.user_manager.tags_used( i ),
'has_requests' : lambda i, k, trans=None, **c: self.user_manager.has_requests( i, trans )
+28 -6
View File
@@ -4208,6 +4208,21 @@ class FormDefinition( object, Dictifiable ):
self.type = form_type
self.layout = layout
def to_dict( self, user=None, values=None, security=None ):
values = values or {}
form_def = { 'id': security.encode_id( self.id ) if security else self.id, 'name': self.name, 'inputs': [] }
for field in self.fields:
FieldClass = ( { 'AddressField' : AddressField,
'CheckboxField' : CheckboxField,
'HistoryField' : HistoryField,
'PasswordField' : PasswordField,
'SelectField' : SelectField,
'TextArea' : TextArea,
'TextField' : TextField,
'WorkflowField' : WorkflowField } ).get( field[ 'type' ], TextField )
form_def[ 'inputs' ].append( FieldClass( user=user, value=values.get( field[ 'name' ], field[ 'default' ] ), security=security, **field ).to_dict() )
return form_def
def grid_fields( self, grid_index ):
# Returns a dictionary whose keys are integers corresponding to field positions
# on the grid and whose values are the field.
@@ -4278,13 +4293,11 @@ class FormDefinition( object, Dictifiable ):
field_widget.params = params
elif field_type == 'SelectField':
for option in field[ 'selectlist' ]:
if option == value:
field_widget.add_option( option, option, selected=True )
else:
field_widget.add_option( option, option )
elif field_type == 'CheckboxField':
field_widget.set_checked( value )
if field[ 'required' ] == 'required':
req = 'Required'
@@ -4294,10 +4307,7 @@ class FormDefinition( object, Dictifiable ):
helptext = '%s (%s)' % ( field[ 'helptext' ], req )
else:
helptext = '(%s)' % req
widgets.append( dict( label=field[ 'label' ],
widget=field_widget,
helptext=helptext ) )
widgets.append( dict( label=field[ 'label' ], widget=field_widget, helptext=helptext ) )
return widgets
def field_as_html( self, field ):
@@ -4832,6 +4842,18 @@ class UserAddress( object ):
self.country = country
self.phone = phone
def to_dict( self, trans ):
return { 'id' : trans.security.encode_id( self.id ),
'name' : sanitize_html( self.name ),
'desc' : sanitize_html( self.desc ),
'institution' : sanitize_html( self.institution ),
'address' : sanitize_html( self.address ),
'city' : sanitize_html( self.city ),
'state' : sanitize_html( self.state ),
'postal_code' : sanitize_html( self.postal_code ),
'country' : sanitize_html( self.country ),
'phone' : sanitize_html( self.phone ) }
def get_html(self):
# This should probably be deprecated eventually. It should currently
# sanitize.
+2 -2
View File
@@ -25,8 +25,8 @@ class Action( object ):
class RBACAgent:
"""Class that handles galaxy security"""
permitted_actions = Bunch(
DATASET_MANAGE_PERMISSIONS=Action( "manage permissions", "Users having associated role can manage the roles associated with permissions on this dataset", "grant" ),
DATASET_ACCESS=Action( "access", "Users having associated role can import this dataset into their history for analysis", "restrict" ),
DATASET_MANAGE_PERMISSIONS=Action( "manage permissions", "Users having associated role can manage the roles associated with permissions on this dataset.", "grant" ),
DATASET_ACCESS=Action( "access", "Users having associated role can import this dataset into their history for analysis.", "restrict" ),
LIBRARY_ACCESS=Action( "access library", "Restrict access to this library to only users having associated role", "restrict" ),
LIBRARY_ADD=Action( "add library item", "Users having associated role can add library items to this library item", "grant" ),
LIBRARY_MODIFY=Action( "modify library item", "Users having associated role can modify this library item", "grant" ),
+2 -2
View File
@@ -56,13 +56,13 @@ class FilterFactory( object ):
def __init_filters( self, key, filters, toolbox_filters, validate=None ):
for filter in filters:
if validate is None or filter in validate or filter in self.default_filters:
filter_function = self._build_filter_function( filter )
filter_function = self.build_filter_function( filter )
toolbox_filters[ key ].append( filter_function )
else:
log.warning( "Refusing to load %s filter '%s' which is not defined in config", key, filter )
return toolbox_filters
def _build_filter_function( self, filter_name ):
def build_filter_function( self, filter_name ):
"""Obtain python function (importing a submodule if needed)
corresponding to filter_name.
"""
+119 -270
View File
@@ -1,21 +1,24 @@
"""
Classes for generating HTML forms
"""
import os
import time
import logging
from six import string_types
from operator import itemgetter
from cgi import escape
from galaxy.util import restore_text, relpath, nice_size, unicodify
from galaxy.web import url_for
from binascii import hexlify
from galaxy.util import restore_text, unicodify
log = logging.getLogger(__name__)
class BaseField(object):
def __init__( self, name, value=None, label=None, **kwds ):
self.name = name
self.label = label
self.value = value
self.disabled = kwds.get( 'disabled', False )
self.optional = kwds.get( 'optional', True ) and kwds.get( 'required', 'optional' ) == 'optional'
self.help = kwds.get( 'helptext' )
def get_html( self, prefix="" ):
"""Returns the html widget corresponding to the parameter"""
raise TypeError( "Abstract Method" )
@@ -26,6 +29,16 @@ class BaseField(object):
else:
return ''
def to_dict( self ):
return {
'name' : self.name,
'label' : self.label,
'disabled' : self.disabled,
'optional' : self.optional,
'value' : self.value,
'help' : self.help
}
class TextField(BaseField):
"""
@@ -36,20 +49,23 @@ class TextField(BaseField):
>>> print TextField( "bins", size=4, value="default" ).get_html()
<input type="text" name="bins" size="4" value="default">
"""
def __init__( self, name, size=None, value=None ):
self.name = name
def __init__( self, name, size=None, value=None, **kwds ):
super( TextField, self ).__init__( name, value, **kwds )
self.size = int( size or 10 )
self.value = value or ""
def get_html( self, prefix="", disabled=False ):
value = self.value
value = unicodify( value )
value = unicodify( self.value or "" )
return unicodify( '<input type="text" name="%s%s" size="%d" value="%s"%s>'
% ( prefix, self.name, self.size, escape( value, quote=True ), self.get_disabled_str( disabled ) ) )
def set_size(self, size):
self.size = int( size )
def to_dict( self ):
d = super( TextField, self ).to_dict()
d[ 'type' ] = 'text'
return d
class PasswordField(BaseField):
"""
@@ -60,7 +76,8 @@ class PasswordField(BaseField):
>>> print PasswordField( "bins", size=4, value="default" ).get_html()
<input type="password" name="bins" size="4" value="default">
"""
def __init__( self, name, size=None, value=None ):
def __init__( self, name, size=None, value=None, **kwds ):
super( PasswordField, self ).__init__( name, value, **kwds )
self.name = name
self.size = int( size or 10 )
self.value = value or ""
@@ -72,6 +89,11 @@ class PasswordField(BaseField):
def set_size(self, size):
self.size = int( size )
def to_dict( self ):
d = super( PasswordField, self ).to_dict()
d[ 'type' ] = 'password'
return d
class TextArea(BaseField):
"""
@@ -84,7 +106,8 @@ class TextArea(BaseField):
"""
_DEFAULT_SIZE = "5x25"
def __init__( self, name, size=None, value=None ):
def __init__( self, name, size=None, value=None, **kwds ):
super( TextArea, self ).__init__( name, value, **kwds )
self.name = name
size = size or self._DEFAULT_SIZE
self.size = size.split("x")
@@ -100,6 +123,12 @@ class TextArea(BaseField):
self.rows = rows
self.cols = cols
def to_dict( self ):
d = super( TextArea, self ).to_dict()
d[ 'type' ] = 'text'
d[ 'area' ] = True
return d
class CheckboxField(BaseField):
"""
@@ -111,7 +140,8 @@ class CheckboxField(BaseField):
<input type="checkbox" id="bar" name="bar" value="__CHECKED__" checked="checked"><input type="hidden" name="bar" value="__NOTHING__">
"""
def __init__( self, name, checked=None, refresh_on_change=False, refresh_on_change_values=None ):
def __init__( self, name, checked=None, refresh_on_change=False, refresh_on_change_values=None, value=None, **kwds ):
super( CheckboxField, self ).__init__( name, value, **kwds )
self.name = name
self.checked = ( checked is True ) or ( isinstance( checked, string_types ) and ( checked.lower() in ( "yes", "true", "on" ) ) )
self.refresh_on_change = refresh_on_change
@@ -134,7 +164,7 @@ class CheckboxField(BaseField):
@staticmethod
def is_checked( value ):
if value is True:
if value in [ True, "true" ]:
return True
return isinstance( value, list ) and ( '__CHECKED__' in value or len( value ) == 2 )
@@ -144,6 +174,11 @@ class CheckboxField(BaseField):
else:
self.checked = value
def to_dict( self ):
d = super( CheckboxField, self ).to_dict()
d[ 'type' ] = 'boolean'
return d
class FileField(BaseField):
"""
@@ -155,7 +190,8 @@ class FileField(BaseField):
<input type="file" name="foo" galaxy-ajax-upload="true">
"""
def __init__( self, name, value=None, ajax=False ):
def __init__( self, name, value=None, ajax=False, **kwds ):
super( FileField, self ).__init__( name, value, **kwds )
self.name = name
self.ajax = ajax
self.value = value
@@ -170,72 +206,6 @@ class FileField(BaseField):
return unicodify( '<input type="file" name="%s%s"%s%s>' % ( prefix, self.name, ajax_text, value_text ) )
class FTPFileField(BaseField):
"""
An FTP file upload input.
"""
thead = '''
<table id="grid-table" class="grid">
<thead id="grid-table-header">
<tr>
<th id="select-header"></th>
<th id="name-header">
File
</th>
<th id="size-header">
Size
</th>
<th id="date-header">
Date
</th>
</tr>
</thead>
<tbody id="grid-table-body">
'''
trow = '''
<tr>
<td><input type="checkbox" name="%s%s" value="%s"/></td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
</tr>
'''
tfoot = '''
</tbody>
</table>
'''
def __init__( self, name, dir, ftp_site, value=None ):
self.name = name
self.dir = dir
self.ftp_site = ftp_site
self.value = value
def get_html( self, prefix="" ):
rval = FTPFileField.thead
if self.dir is None:
rval += '<tr><td colspan="4"><em>Please <a href="%s">create</a> or <a href="%s">log in to</a> a Galaxy account to view files uploaded via FTP.</em></td></tr>' % ( url_for( controller='user', action='create', cntrller='user', referer=url_for( controller='root' ) ), url_for( controller='user', action='login', cntrller='user', referer=url_for( controller='root' ) ) )
elif not os.path.exists( self.dir ):
rval += '<tr><td colspan="4"><em>Your FTP upload directory contains no files.</em></td></tr>'
else:
uploads = []
for ( dirpath, dirnames, filenames ) in os.walk( self.dir ):
for filename in filenames:
path = relpath( os.path.join( dirpath, filename ), self.dir )
statinfo = os.lstat( os.path.join( dirpath, filename ) )
uploads.append( dict( path=path,
size=nice_size( statinfo.st_size ),
ctime=time.strftime( "%m/%d/%Y %I:%M:%S %p", time.localtime( statinfo.st_ctime ) ) ) )
if not uploads:
rval += '<tr><td colspan="4"><em>Your FTP upload directory contains no files.</em></td></tr>'
uploads = sorted(uploads, key=itemgetter("path"))
for upload in uploads:
rval += FTPFileField.trow % ( prefix, self.name, upload['path'], upload['path'], upload['size'], upload['ctime'] )
rval += FTPFileField.tfoot
rval += '<div class="toolParamHelp">This Galaxy server allows you to upload files via FTP. To upload some files, log in to the FTP server at <strong>%s</strong> using your Galaxy credentials (email address and password).</div>' % self.ftp_site
return rval
class HiddenField(BaseField):
"""
A hidden field.
@@ -243,13 +213,20 @@ class HiddenField(BaseField):
>>> print HiddenField( "foo", 100 ).get_html()
<input type="hidden" name="foo" value="100">
"""
def __init__( self, name, value=None ):
def __init__( self, name, value=None, **kwds ):
super( HiddenField, self ).__init__( name, value, **kwds )
self.name = name
self.value = value or ""
def get_html( self, prefix="" ):
return unicodify( '<input type="hidden" name="%s%s" value="%s">' % ( prefix, self.name, escape( str( self.value ), quote=True ) ) )
def to_dict( self ):
d = super( HiddenField, self ).to_dict()
d[ 'type' ] = 'hidden'
d[ 'hidden' ] = True
return d
class SelectField(BaseField):
"""
@@ -288,10 +265,13 @@ class SelectField(BaseField):
<div><input type="checkbox" name="bar" value="3" id="bar|3"><label class="inline" for="bar|3">automatic</label></div>
<div><input type="checkbox" name="bar" value="4" id="bar|4" checked='checked'><label class="inline" for="bar|4">bazooty</label></div>
"""
def __init__( self, name, multiple=None, display=None, refresh_on_change=False, refresh_on_change_values=None, size=None, field_id=None ):
def __init__( self, name, multiple=None, display=None, refresh_on_change=False, refresh_on_change_values=None, size=None, field_id=None, value=None, selectlist=None, **kwds ):
super( SelectField, self ).__init__( name, value, **kwds )
self.name = name
self.field_id = field_id
self.multiple = multiple or False
self.selectlist = selectlist or []
self.value = value
self.size = size
self.options = list()
if display == "checkboxes":
@@ -432,163 +412,33 @@ class SelectField(BaseField):
return None
def to_dict( self ):
return dict(
name=self.name,
multiple=self.multiple,
options=self.options
)
class DrillDownField( BaseField ):
"""
A hierarchical select field, which allows users to 'drill down' a tree-like set of options.
>>> t = DrillDownField( "foo", multiple=True, display="checkbox", options=[{'name': 'Heading 1', 'value': 'heading1', 'options': [{'name': 'Option 1', 'value': 'option1', 'options': []}, {'name': 'Option 2', 'value': 'option2', 'options': []}, {'name': 'Heading 1', 'value': 'heading1', 'options': [{'name': 'Option 3', 'value': 'option3', 'options': []}, {'name': 'Option 4', 'value': 'option4', 'options': []}]}]}, {'name': 'Option 5', 'value': 'option5', 'options': []}] )
>>> print t.get_html()
<div class="form-row drilldown-container" id="drilldown--666f6f">
<div class="form-row-input">
<div><span class="form-toggle icon-button toggle-expand" id="drilldown--666f6f-68656164696e6731-click"></span>
<input type="checkbox" name="foo" value="heading1" >Heading 1
</div><div class="form-row" id="drilldown--666f6f-68656164696e6731-container" style="float: left; margin-left: 1em;">
<div class="form-row-input">
<input type="checkbox" name="foo" value="option1" >Option 1
</div>
<div class="form-row-input">
<input type="checkbox" name="foo" value="option2" >Option 2
</div>
<div class="form-row-input">
<div><span class="form-toggle icon-button toggle-expand" id="drilldown--666f6f-68656164696e6731-68656164696e6731-click"></span>
<input type="checkbox" name="foo" value="heading1" >Heading 1
</div><div class="form-row" id="drilldown--666f6f-68656164696e6731-68656164696e6731-container" style="float: left; margin-left: 1em;">
<div class="form-row-input">
<input type="checkbox" name="foo" value="option3" >Option 3
</div>
<div class="form-row-input">
<input type="checkbox" name="foo" value="option4" >Option 4
</div>
</div>
</div>
</div>
</div>
<div class="form-row-input">
<input type="checkbox" name="foo" value="option5" >Option 5
</div>
</div>
>>> t = DrillDownField( "foo", multiple=False, display="radio", options=[{'name': 'Heading 1', 'value': 'heading1', 'options': [{'name': 'Option 1', 'value': 'option1', 'options': []}, {'name': 'Option 2', 'value': 'option2', 'options': []}, {'name': 'Heading 1', 'value': 'heading1', 'options': [{'name': 'Option 3', 'value': 'option3', 'options': []}, {'name': 'Option 4', 'value': 'option4', 'options': []}]}]}, {'name': 'Option 5', 'value': 'option5', 'options': []}] )
>>> print t.get_html()
<div class="form-row drilldown-container" id="drilldown--666f6f">
<div class="form-row-input">
<div><span class="form-toggle icon-button toggle-expand" id="drilldown--666f6f-68656164696e6731-click"></span>
<input type="radio" name="foo" value="heading1" >Heading 1
</div><div class="form-row" id="drilldown--666f6f-68656164696e6731-container" style="float: left; margin-left: 1em;">
<div class="form-row-input">
<input type="radio" name="foo" value="option1" >Option 1
</div>
<div class="form-row-input">
<input type="radio" name="foo" value="option2" >Option 2
</div>
<div class="form-row-input">
<div><span class="form-toggle icon-button toggle-expand" id="drilldown--666f6f-68656164696e6731-68656164696e6731-click"></span>
<input type="radio" name="foo" value="heading1" >Heading 1
</div><div class="form-row" id="drilldown--666f6f-68656164696e6731-68656164696e6731-container" style="float: left; margin-left: 1em;">
<div class="form-row-input">
<input type="radio" name="foo" value="option3" >Option 3
</div>
<div class="form-row-input">
<input type="radio" name="foo" value="option4" >Option 4
</div>
</div>
</div>
</div>
</div>
<div class="form-row-input">
<input type="radio" name="foo" value="option5" >Option 5
</div>
</div>
"""
def __init__( self, name, multiple=None, display=None, refresh_on_change=False, options=[], value=[], refresh_on_change_values=[] ):
self.name = name
self.multiple = multiple or False
self.options = options
if value and not isinstance( value, list ):
value = [ value ]
elif not value:
value = []
self.value = value
if display == "checkbox":
assert multiple, "Checkbox display only supported for multiple select"
elif display == "radio":
assert not( multiple ), "Radio display only supported for single select"
else:
raise Exception( "Unknown display type: %s" % display )
self.display = display
self.refresh_on_change = refresh_on_change
self.refresh_on_change_values = refresh_on_change_values
if self.refresh_on_change:
self.refresh_on_change_text = ' refresh_on_change="true"'
if self.refresh_on_change_values:
self.refresh_on_change_text = '%s refresh_on_change_values="%s"' % ( self.refresh_on_change_text, ",".join( self.refresh_on_change_values ) )
else:
self.refresh_on_change_text = ''
def get_html( self, prefix="" ):
def find_expanded_options( expanded_options, options, parent_options=[] ):
for option in options:
if option['value'] in self.value:
expanded_options.extend( parent_options )
if option['options']:
new_parents = list( parent_options ) + [ option['value'] ]
find_expanded_options( expanded_options, option['options'], new_parents )
def recurse_options( html, options, base_id, expanded_options=[] ):
for option in options:
escaped_option_value = escape( str( option['value'] ), quote=True )
selected = ( option['value'] in self.value )
if selected:
selected = ' checked'
else:
selected = ''
span_class = 'form-toggle icon-button toggle'
if option['value'] not in expanded_options:
span_class = "%s-expand" % ( span_class )
html.append( '<div class="form-row-input">')
drilldown_group_id = "%s-%s" % ( base_id, hexlify( option['value'] ) )
if option['options']:
html.append( '<div><span class="%s" id="%s-click"></span>' % ( span_class, drilldown_group_id ) )
html.append( '<input type="%s" name="%s%s" value="%s" %s>%s' % ( self.display, prefix, self.name, escaped_option_value, selected, option['name']) )
if option['options']:
html.append( '</div><div class="form-row" id="%s-container" style="float: left; margin-left: 1em;">' % ( drilldown_group_id ) )
recurse_options( html, option['options'], drilldown_group_id, expanded_options )
html.append( '</div>')
html.append( '</div>')
drilldown_id = "drilldown-%s-%s" % ( hexlify( prefix ), hexlify( self.name ) )
rval = []
rval.append( '<div class="form-row drilldown-container" id="%s">' % ( drilldown_id ) )
expanded_options = []
find_expanded_options( expanded_options, self.options )
recurse_options( rval, self.options, drilldown_id, expanded_options )
rval.append( '</div>' )
return unicodify( '\n'.join( rval ) )
d = super( SelectField, self ).to_dict()
d[ 'type' ] = 'select'
d[ 'display' ] = self.display
d[ 'multiple' ] = self.multiple
d[ 'data' ] = []
for value in self.selectlist:
d[ 'data' ].append( { 'label': value, 'value': value } )
return d
class AddressField(BaseField):
@staticmethod
def fields():
return [ ( "short_desc", "Short address description", "Required" ),
( "name", "Name", "Required" ),
( "institution", "Institution", "Required" ),
( "address", "Address", "Required" ),
( "city", "City", "Required" ),
( "state", "State/Province/Region", "Required" ),
( "postal_code", "Postal Code", "Required" ),
( "country", "Country", "Required" ),
return [ ( "desc", "Short address description", "Required" ),
( "name", "Name", "" ),
( "institution", "Institution", "" ),
( "address", "Address", "" ),
( "city", "City", "" ),
( "state", "State/Province/Region", "" ),
( "postal_code", "Postal Code", "" ),
( "country", "Country", "" ),
( "phone", "Phone", "" ) ]
def __init__(self, name, user=None, value=None, params=None):
self.name = name
def __init__(self, name, user=None, value=None, params=None, security=None, **kwds):
super( AddressField, self ).__init__( name, value, **kwds )
self.user = user
self.value = value
self.security = security
self.select_address = None
self.params = params
@@ -643,12 +493,24 @@ class AddressField(BaseField):
self.select_address.add_option( 'Add a new address', 'new' )
return self.select_address.get_html( disabled=disabled ) + address_html
def to_dict( self ):
d = super( AddressField, self ).to_dict()
d[ 'type' ] = 'select'
d[ 'data' ] = []
if self.user and self.security:
for a in self.user.addresses:
if not a.deleted:
d[ 'data' ].append( { 'label': a.desc, 'value': self.security.encode_id( a.id ) } )
return d
class WorkflowField( BaseField ):
def __init__( self, name, user=None, value=None, params=None ):
def __init__( self, name, user=None, value=None, params=None, security=None, **kwds ):
super( WorkflowField, self ).__init__( name, value, **kwds )
self.name = name
self.user = user
self.value = value
self.security = security
self.select_workflow = None
self.params = params
@@ -667,8 +529,18 @@ class WorkflowField( BaseField ):
self.select_workflow.add_option( a.name, str( a.id ) )
return self.select_workflow.get_html( disabled=disabled )
def to_dict( self ):
d = super( WorkflowField, self ).to_dict()
d[ 'type' ] = 'select'
d[ 'data' ] = []
if self.user and self.security:
for a in self.user.stored_workflows:
if not a.deleted:
d[ 'data' ].append( { 'label': a.name, 'value': self.security.encode_id( a.id ) } )
return d
class WorkflowMappingField( BaseField):
class WorkflowMappingField( BaseField ):
def __init__( self, name, user=None, value=None, params=None, **kwd ):
# DBTODO integrate this with the new __build_workflow approach in requests_common. As it is, not particularly useful.
self.name = name
@@ -703,18 +575,14 @@ class WorkflowMappingField( BaseField):
# Do something more appropriate here and allow selection of inputs
return self.select_workflow.get_html( disabled=disabled ) + ''.join(['<div class="form-row"><label>%s</label>%s</div>' % (s[0], s[1].get_html()) for s in workflow_inputs])
def get_display_text(self):
if self.value:
return self.value
else:
return '-'
class HistoryField( BaseField ):
def __init__( self, name, user=None, value=None, params=None ):
def __init__( self, name, user=None, value=None, params=None, security=None, **kwds ):
super( HistoryField, self ).__init__( name, value, **kwds )
self.name = name
self.user = user
self.value = value
self.security = security
self.select_history = None
self.params = params
@@ -738,34 +606,15 @@ class HistoryField( BaseField ):
self.select_history.add_option( a.name, str( a.id ) )
return self.select_history.get_html( disabled=disabled )
def get_display_text(self):
if self.value:
return self.value
else:
return '-'
class LibraryField( BaseField ):
def __init__( self, name, value=None, trans=None ):
self.name = name
self.lddas = value
self.trans = trans
def get_html( self, prefix="", disabled=False ):
if not self.lddas:
ldda_ids = ""
text = "Select library dataset(s)"
else:
ldda_ids = "||".join( [ self.trans.security.encode_id( ldda.id ) for ldda in self.lddas ] )
text = "<br />".join( [ "%s. %s" % (i + 1, ldda.name) for i, ldda in enumerate(self.lddas)] )
return unicodify( '<a href="javascript:void(0);" class="add-librarydataset">%s</a> \
<input type="hidden" name="%s%s" value="%s">' % ( text, prefix, self.name, escape( str(ldda_ids), quote=True ) ) )
def get_display_text(self):
if self.ldda:
return self.ldda.name
else:
return 'None'
def to_dict( self ):
d = super( HistoryField, self ).to_dict()
d[ 'type' ] = 'select'
d[ 'data' ] = [{ 'label': 'New History', 'value': 'new' }]
if self.user and self.security:
for a in self.user.histories:
if not a.deleted:
d[ 'data' ].append( { 'label': a.name, 'value': self.security.encode_id( a.id ) } )
return d
def get_suite():
+403 -15
View File
@@ -3,10 +3,13 @@ API operations on User objects.
"""
import logging
import datetime
import re
from sqlalchemy import false, true, or_
from sqlalchemy import false, true, and_, or_
from galaxy import exceptions, util, web
from galaxy.exceptions import MessageException
from galaxy.managers import users
from galaxy.security.validate_user_input import validate_email
from galaxy.security.validate_user_input import validate_password
@@ -17,11 +20,18 @@ from galaxy.web.base.controller import BaseAPIController
from galaxy.web.base.controller import CreatesApiKeysMixin
from galaxy.web.base.controller import CreatesUsersMixin
from galaxy.web.base.controller import UsesTagsMixin
from galaxy.web.base.controller import BaseUIController
from galaxy.web.base.controller import UsesFormDefinitionsMixin
from galaxy.web.form_builder import AddressField
from galaxy.tools.toolbox.filters import FilterFactory
from galaxy.util import docstring_trim, listify
from galaxy.util.odict import odict
log = logging.getLogger( __name__ )
class UserAPIController( BaseAPIController, UsesTagsMixin, CreatesUsersMixin, CreatesApiKeysMixin ):
class UserAPIController( BaseAPIController, UsesTagsMixin, CreatesUsersMixin, CreatesApiKeysMixin, BaseUIController, UsesFormDefinitionsMixin ):
def __init__(self, app):
super(UserAPIController, self).__init__(app)
@@ -110,8 +120,8 @@ class UserAPIController( BaseAPIController, UsesTagsMixin, CreatesUsersMixin, Cr
@expose_api_anonymous
def show( self, trans, id, deleted='False', **kwd ):
"""
GET /api/users/{encoded_user_id}
GET /api/users/deleted/{encoded_user_id}
GET /api/users/{encoded_id}
GET /api/users/deleted/{encoded_id}
GET /api/users/current
Displays information about a user.
"""
@@ -164,17 +174,6 @@ class UserAPIController( BaseAPIController, UsesTagsMixin, CreatesUsersMixin, Cr
'total_disk_usage': float } )
return item
@expose_api
@web.require_admin
def api_key( self, trans, user_id, **kwd ):
"""
POST /api/users/{encoded_user_id}/api_key
Creates a new API key for specified user.
"""
user = self.get_user( trans, user_id )
key = self.create_api_key( trans, user )
return key
@expose_api
def update( self, trans, id, payload, **kwd ):
"""
@@ -240,3 +239,392 @@ class UserAPIController( BaseAPIController, UsesTagsMixin, CreatesUsersMixin, Cr
return {'total_disk_usage': int( usage ),
'nice_total_disk_usage': util.nice_size( usage ),
'quota_percent': percent}
@expose_api
def get_information(self, trans, id, **kwd):
'''
Returns user details such as public username, type, addresses, etc.
'''
user = self._get_user(trans, id)
email = user.email
username = user.username
inputs = list()
inputs.append({
'id': 'email_input',
'name': 'email',
'type': 'text',
'label': 'Email address',
'value': email,
'help': 'If you change your email address you will receive an activation link in the new mailbox and you have to activate your account by visiting it.'})
if trans.webapp.name == 'galaxy':
inputs.append({
'id': 'name_input',
'name': 'username',
'type': 'text',
'label': 'Public name',
'value': username,
'help': 'Your public name is an identifier that will be used to generate addresses for information you share publicly. Public names must be at least three characters in length and contain only lower-case letters, numbers, and the "-" character.'})
info_form_models = self.get_all_forms(trans, filter=dict(deleted=False), form_type=trans.app.model.FormDefinition.types.USER_INFO)
if info_form_models:
info_form_id = trans.security.encode_id(user.values.form_definition.id) if user.values else None
info_field = {
'type': 'conditional',
'name': 'info',
'cases': [],
'test_param': {
'name': 'form_id',
'label': 'User type',
'type': 'select',
'value': info_form_id,
'help': '',
'data': []
}
}
for f in info_form_models:
values = None
if info_form_id == trans.security.encode_id(f.id) and user.values:
values = user.values.content
info_form = f.to_dict(user=user, values=values, security=trans.security)
info_field['test_param']['data'].append({'label': info_form['name'], 'value': info_form['id']})
info_field['cases'].append({'value': info_form['id'], 'inputs': info_form['inputs']})
inputs.append(info_field)
address_inputs = [{'type': 'hidden', 'name': 'id', 'hidden': True}]
for field in AddressField.fields():
address_inputs.append({'type': 'text', 'name': field[0], 'label': field[1], 'help': field[2]})
address_repeat = {'title': 'Address', 'name': 'address', 'type': 'repeat', 'inputs': address_inputs, 'cache': []}
address_values = [address.to_dict(trans) for address in user.addresses]
for address in address_values:
address_cache = []
for input in address_inputs:
input_copy = input.copy()
input_copy['value'] = address.get(input['name'])
address_cache.append(input_copy)
address_repeat['cache'].append(address_cache)
inputs.append(address_repeat)
else:
if user.active_repositories:
inputs.append(dict(id='name_input', name='username', label='Public name:', type='hidden', value=username, help='You cannot change your public name after you have created a repository in this tool shed.'))
else:
inputs.append(dict(id='name_input', name='username', label='Public name:', type='text', value=username, help='Your public name provides a means of identifying you publicly within this tool shed. Public names must be at least three characters in length and contain only lower-case letters, numbers, and the "-" character. You cannot change your public name after you have created a repository in this tool shed.'))
return {
'email': email,
'username': username,
'addresses': [address.to_dict(trans) for address in user.addresses],
'inputs': inputs,
}
@expose_api
def set_information(self, trans, id, payload={}, **kwd):
'''
Save a user's email address, public username, type, addresses etc.
'''
user = self._get_user(trans, id)
email = payload.get('email')
username = payload.get('username')
if email or username:
message = self._validate_email_publicname(email, username) or validate_email(trans, email, user)
if not message and username:
message = validate_publicname(trans, username, user)
if message:
raise MessageException(message)
# Update user email and user's private role name which must match
if user.email != email:
private_role = trans.app.security_agent.get_private_user_role(user)
private_role.name = email
private_role.description = 'Private role for ' + email
user.email = email
trans.sa_session.add(private_role)
if trans.app.config.user_activation_on:
user.active = False
if self.send_verification_email(trans, user.email, user.username):
message = 'The login information has been updated with the changes.<br>Verification email has been sent to your new email address. Please verify it by clicking the activation link in the email.<br>Please check your spam/trash folder in case you cannot find the message.'
else:
message = 'Unable to send activation email, please contact your local Galaxy administrator.'
if trans.app.config.error_email_to is not None:
message += ' Contact: %s' % trans.app.config.error_email_to
raise MessageException(message)
# Update public name
if user.username != username:
user.username = username
# Update user custom form
user_info_form_id = payload.get('info|form_id')
if user_info_form_id:
prefix = 'info|'
user_info_form = trans.sa_session.query(trans.app.model.FormDefinition).get(trans.security.decode_id(user_info_form_id))
user_info_values = {}
for item in payload:
if item.startswith(prefix):
user_info_values[item[len(prefix):]] = payload[item]
form_values = trans.model.FormValues(user_info_form, user_info_values)
trans.sa_session.add(form_values)
user.values = form_values
# Update user addresses
address_dicts = {}
address_count = 0
for item in payload:
match = re.match(r'^address_(?P<index>\d+)\|(?P<attribute>\S+)', item)
if match:
groups = match.groupdict()
index = int(groups['index'])
attribute = groups['attribute']
address_dicts[index] = address_dicts.get(index) or {}
address_dicts[index][attribute] = payload[item]
address_count = max(address_count, index + 1)
user.addresses = []
for index in range(0, address_count):
d = address_dicts[index]
if d.get('id'):
try:
user_address = trans.sa_session.query(trans.app.model.UserAddress).get(trans.security.decode_id(d['id']))
except Exception as e:
raise MessageException('Failed to access user address (%s). %s' % (d['id'], e))
else:
user_address = trans.model.UserAddress()
trans.log_event('User address added')
for field in AddressField.fields():
if str(field[2]).lower() == 'required' and not d.get(field[0]):
raise MessageException('Address %s: %s (%s) required.' % (index + 1, field[1], field[0]))
setattr(user_address, field[0], str(d.get(field[0], '')))
user_address.user = user
user.addresses.append(user_address)
trans.sa_session.add(user_address)
trans.sa_session.add(user)
trans.sa_session.flush()
trans.log_event('User information added')
return {'message': 'User information has been saved.'}
def _validate_email_publicname(self, email, username):
''' Validate email and username using regex '''
if email == '' or not isinstance( email, basestring ):
return 'Please provide your email address.'
if not re.match('^[a-z0-9\-]{3,255}$', username):
return 'Public name must contain only lowercase letters, numbers and "-". It also has to be shorter than 255 characters but longer than 2.'
if not re.match('^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$', email):
return 'Please provide your valid email address.'
if len(email) > 255:
return 'Email cannot be more than 255 characters in length.'
@expose_api
def get_password(self, trans, id, payload={}, **kwd):
"""
Return available password inputs.
"""
return {'message': 'Password unchanged.',
'inputs': [ {'name': 'current', 'type': 'password', 'label': 'Current password'},
{'name': 'password', 'type': 'password', 'label': 'New password'},
{'name': 'confirm', 'type': 'password', 'label': 'Confirm password'},
{'name': 'token', 'type': 'hidden', 'hidden': True, 'ignore': None} ]}
@expose_api
def set_password(self, trans, id, payload={}, **kwd):
"""
Allows to change a user password.
"""
password = payload.get('password')
confirm = payload.get('confirm')
current = payload.get('current')
token = payload.get('token')
token_result = None
if token:
# If a token was supplied, validate and set user
token_result = trans.sa_session.query(trans.app.model.PasswordResetToken).get(token)
if not token_result or not token_result.expiration_time > datetime.utcnow():
raise MessageException('Invalid or expired password reset token, please request a new one.')
user = token_result.user
else:
# The user is changing their own password, validate their current password
user = self._get_user(trans, id)
(ok, message) = trans.app.auth_manager.check_change_password(user, current)
if not ok:
raise MessageException(message)
if user:
# Validate the new password
message = validate_password(trans, password, confirm)
if message:
raise MessageException(message)
else:
# Save new password
user.set_password_cleartext(password)
# if we used a token, invalidate it and log the user in.
if token_result:
trans.handle_user_login(token_result.user)
token_result.expiration_time = datetime.utcnow()
trans.sa_session.add(token_result)
# Invalidate all other sessions
for other_galaxy_session in trans.sa_session.query(trans.app.model.GalaxySession) \
.filter(and_(trans.app.model.GalaxySession.table.c.user_id == user.id,
trans.app.model.GalaxySession.table.c.is_valid == true(),
trans.app.model.GalaxySession.table.c.id != trans.galaxy_session.id)):
other_galaxy_session.is_valid = False
trans.sa_session.add(other_galaxy_session)
trans.sa_session.add(user)
trans.sa_session.flush()
trans.log_event('User change password')
return {'message': 'Password has been saved.'}
raise MessageException('Failed to determine user, access denied.')
@expose_api
def get_permissions(self, trans, id, payload={}, **kwd):
"""
Get the user's default permissions for the new histories
"""
user = self._get_user(trans, id)
roles = user.all_roles()
permitted_actions = trans.app.model.Dataset.permitted_actions.items()
inputs = []
for index, action in permitted_actions:
inputs.append({'type': 'select',
'multiple': True,
'optional': True,
'name': index,
'label': action.action,
'help': action.description,
'options': [(r.name, r.id) for r in roles],
'value': [a.role.id for a in user.default_permissions if a.action == action.action]})
return {'message': 'Permissions unchanged.', 'inputs': inputs}
@expose_api
def set_permissions(self, trans, id, payload={}, **kwd):
"""
Set the user's default permissions for the new histories
"""
user = self._get_user(trans, id)
permitted_actions = trans.app.model.Dataset.permitted_actions.items()
permissions = {}
for index, action in permitted_actions:
action_id = trans.app.security_agent.get_action(action.action).action
permissions[action_id] = [trans.sa_session.query(trans.app.model.Role).get(x) for x in (payload.get(index) or [])]
trans.app.security_agent.user_set_default_permissions(user, permissions)
return {'message': 'Permissions have been saved.'}
@expose_api
def get_toolbox_filters(self, trans, id, payload={}, **kwd):
"""
API call for fetching toolbox filters data. Toolbox filters are specified in galaxy.ini.
The user can activate them and the choice is stored in user_preferences.
"""
user = self._get_user(trans, id)
filter_types = self._get_filter_types(trans)
saved_values = {}
for name, value in user.preferences.items():
if name in filter_types:
saved_values[name] = listify(value, do_strip=True)
inputs = []
factory = FilterFactory(trans.app.toolbox)
for filter_type in filter_types:
self._add_filter_inputs(factory, filter_types, inputs, filter_type, saved_values)
return {'message': 'Toolbox filters unchanged.', 'inputs': inputs}
@expose_api
def set_toolbox_filters(self, trans, id, payload={}, **kwd):
"""
API call to update toolbox filters data.
"""
user = self._get_user(trans, id)
filter_types = self._get_filter_types(trans)
for filter_type in filter_types:
new_filters = []
for prefixed_name in payload:
prefix = filter_type + '|'
if prefixed_name.startswith(filter_type):
new_filters.append(prefixed_name[len(prefix):])
user.preferences[filter_type] = ','.join(new_filters)
trans.sa_session.add(user)
trans.sa_session.flush()
return {'message': 'Toolbox filters have been saved.'}
def _add_filter_inputs(self, factory, filter_types, inputs, filter_type, saved_values):
filter_inputs = list()
filter_values = saved_values.get(filter_type, [])
filter_config = filter_types[filter_type]['config']
filter_title = filter_types[filter_type]['title']
for filter_name in filter_config:
function = factory.build_filter_function(filter_name)
filter_inputs.append({
'type': 'boolean',
'name': filter_name,
'label': filter_name,
'help': docstring_trim(function.__doc__) or 'No description available.',
'value': 'true' if filter_name in filter_values else 'false',
'ignore': 'false'
})
if filter_inputs:
inputs.append({'type': 'section', 'title': filter_title, 'name': filter_type, 'expanded': True, 'inputs': filter_inputs})
def _get_filter_types(self, trans):
return odict([('toolbox_tool_filters', {'title': 'Tools', 'config': trans.app.config.user_tool_filters}),
('toolbox_tool_section_filters', {'title': 'Sections', 'config': trans.app.config.user_tool_section_filters}),
('toolbox_tool_label_filters', {'title': 'Labels', 'config': trans.app.config.user_tool_label_filters})])
@expose_api
def api_key(self, trans, id, payload={}, **kwd):
"""
Create API key.
"""
user = self._get_user(trans, id)
return self.create_api_key(trans, user)
@expose_api
def get_api_key(self, trans, id, payload={}, **kwd):
"""
Get API key inputs.
"""
user = self._get_user(trans, id)
return self._build_inputs_api_key(user)
@expose_api
def set_api_key(self, trans, id, payload={}, **kwd):
"""
Get API key inputs with new API key.
"""
user = self._get_user(trans, id)
self.create_api_key(trans, user)
return self._build_inputs_api_key(user, message='Generated a new web API key.')
def _build_inputs_api_key(self, user, message='' ):
"""
Build API key inputs.
"""
inputs = [{'name': 'api-key',
'type': 'text',
'label': 'Current API key:',
'value': user.api_keys[0].key if user.api_keys else 'Not available.',
'readonly': True,
'help': ' An API key will allow you to access via web API. Please note that this key acts as an alternate means to access your account and should be treated with the same care as your login password.'}]
return {'message': message, 'inputs': inputs}
@expose_api
def get_communication(self, trans, id, payload={}, **kwd):
"""
Build communication server inputs.
"""
user = self._get_user(trans, id)
return {'message': 'Communication server settings unchanged.',
'inputs': [{'name': 'enable',
'type': 'boolean',
'label': 'Enable communication',
'value': user.preferences.get('communication_server', 'false')}]}
@expose_api
def set_communication(self, trans, id, payload={}, **kwd):
"""
Allows the user to activate/deactivate the communication server.
"""
user = self._get_user(trans, id)
enable = payload.get('enable', 'false')
if enable == 'true':
message = 'Your communication server has been activated.'
else:
message = 'Your communication server has been disabled.'
user.preferences['communication_server'] = enable
trans.sa_session.add(user)
trans.sa_session.flush()
return {'message': message}
def _get_user(self, trans, id):
user = self.get_user(trans, id)
if not user:
raise MessageException('Invalid user (%s).' % id)
if user != trans.user and not trans.user_is_admin():
raise MessageException('Access denied.')
return user
+83 -4
View File
@@ -71,6 +71,7 @@ def paste_app_factory( global_conf, **kwargs ):
webapp.add_client_route( '/tours' )
webapp.add_client_route( '/tours/{tour_id}' )
webapp.add_client_route( '/users' )
# STANDARD CONTROLLER ROUTES
webapp.add_ui_controllers( 'galaxy.webapps.galaxy.controllers', app )
@@ -327,10 +328,6 @@ def populate_api_routes( webapp, app ):
"/api/histories/{id}/exports/{jeha_id}", controller="histories",
action="archive_download", conditions=dict( method=[ "GET" ] ) )
webapp.mapper.connect( "create_api_key", "/api/users/{user_id}/api_key",
controller="users", action="api_key", user_id=None,
conditions=dict( method=["POST"] ) )
# ---- visualizations registry ---- generic template renderer
# @deprecated: this route should be considered deprecated
webapp.add_route( '/visualization/show/{visualization_name}', controller='visualization', action='render', visualization_name=None )
@@ -462,6 +459,88 @@ def populate_api_routes( webapp, app ):
action='update_tour',
conditions=dict( method=[ "POST" ] ) )
# ================================
# ===== USERS API =====
# ================================
webapp.mapper.connect( 'api_key',
'/api/users/{id}/api_key',
controller='users',
action='api_key',
conditions=dict( method=["POST"] ) )
webapp.mapper.connect( 'get_api_key',
'/api/users/{id}/api_key/inputs',
controller='users',
action='get_api_key',
conditions=dict( method=["GET"] ) )
webapp.mapper.connect( 'set_api_key',
'/api/users/{id}/api_key/inputs',
controller='users',
action='set_api_key',
conditions=dict( method=["PUT"] ) )
webapp.mapper.connect( 'get_information',
'/api/users/{id}/information/inputs',
controller='users',
action='get_information',
conditions=dict( method=["GET"] ) )
webapp.mapper.connect( 'set_information',
'/api/users/{id}/information/inputs',
controller='users',
action='set_information',
conditions=dict( method=["PUT"] ) )
webapp.mapper.connect( 'get_password',
'/api/users/{id}/password/inputs',
controller='users',
action='get_password',
conditions=dict( method=["GET"] ) )
webapp.mapper.connect( 'set_password',
'/api/users/{id}/password/inputs',
controller='users',
action='set_password',
conditions=dict( method=["PUT"] ) )
webapp.mapper.connect( 'get_permissions',
'/api/users/{id}/permissions/inputs',
controller='users',
action='get_permissions',
conditions=dict( method=["GET"] ) )
webapp.mapper.connect( 'set_permissions',
'/api/users/{id}/permissions/inputs',
controller='users',
action='set_permissions',
conditions=dict( method=["PUT"] ) )
webapp.mapper.connect( 'get_toolbox_filters',
'/api/users/{id}/toolbox_filters/inputs',
controller='users',
action='get_toolbox_filters',
conditions=dict( method=["GET"] ) )
webapp.mapper.connect( 'set_toolbox_filters',
'/api/users/{id}/toolbox_filters/inputs',
controller='users',
action='set_toolbox_filters',
conditions=dict( method=["PUT"] ) )
webapp.mapper.connect( 'get_communication',
'/api/users/{id}/communication/inputs',
controller='users',
action='get_communication',
conditions=dict( method=["GET"] ) )
webapp.mapper.connect( 'set_communication',
'/api/users/{id}/communication/inputs',
controller='users',
action='set_communication',
conditions=dict( method=["PUT"] ) )
# ========================
# ===== WEBHOOKS API =====
# ========================
+3 -766
View File
@@ -12,25 +12,23 @@ from datetime import datetime, timedelta
from json import dumps, loads
from markupsafe import escape
from sqlalchemy import and_, or_, true, func
from sqlalchemy import or_, func
from galaxy import model
from galaxy import util
from galaxy import web
from galaxy.util import string_as_bool
from galaxy.exceptions import ObjectInvalid
from galaxy.security.validate_user_input import (transform_publicname,
validate_email,
validate_password,
validate_publicname)
from galaxy.tools.toolbox.filters import FilterFactory
from galaxy.util import biostar, hash_util, docstring_trim, listify
from galaxy.util import biostar, hash_util
from galaxy.web import url_for
from galaxy.web.base.controller import (BaseUIController,
CreatesApiKeysMixin,
CreatesUsersMixin,
UsesFormDefinitionsMixin)
from galaxy.web.form_builder import build_select_field, CheckboxField
from galaxy.web.form_builder import CheckboxField
from galaxy.web.framework.helpers import grids, time_ago
log = logging.getLogger( __name__ )
@@ -78,10 +76,6 @@ class User( BaseUIController, UsesFormDefinitionsMixin, CreatesUsersMixin, Creat
user_openid_grid = UserOpenIDGrid()
installed_len_files = None
@web.expose
def index( self, trans, cntrller='user', **kwd ):
return trans.fill_template( '/user/index.mako', cntrller=cntrller )
@web.expose
def openid_auth( self, trans, **kwd ):
'''Handles user request to access an OpenID provider'''
@@ -370,17 +364,6 @@ class User( BaseUIController, UsesFormDefinitionsMixin, CreatesUsersMixin, Creat
else:
message = error
status = 'error'
if trans.webapp.name == 'galaxy':
user_type_form_definition = self.__get_user_type_form_definition( trans, user=user, **kwd )
user_type_fd_id = params.get( 'user_type_fd_id', 'none' )
if user_type_fd_id == 'none' and user_type_form_definition is not None:
user_type_fd_id = trans.security.encode_id( user_type_form_definition.id )
user_type_fd_id_select_field = self.__build_user_type_fd_id_select_field( trans, selected_value=user_type_fd_id )
widgets = self.__get_widgets( trans, user_type_form_definition, user=user, **kwd )
else:
user_type_fd_id_select_field = None
user_type_form_definition = None
widgets = []
return trans.fill_template( '/user/openid_associate.mako',
cntrller=cntrller,
email=email,
@@ -395,9 +378,6 @@ class User( BaseUIController, UsesFormDefinitionsMixin, CreatesUsersMixin, Creat
status=status,
active_view="user",
subscribe_checked=False,
user_type_fd_id_select_field=user_type_fd_id_select_field,
user_type_form_definition=user_type_form_definition,
widgets=widgets,
openids=openids )
@web.expose
@@ -733,27 +713,15 @@ class User( BaseUIController, UsesFormDefinitionsMixin, CreatesUsersMixin, Creat
else:
status = 'error'
if trans.webapp.name == 'galaxy':
user_type_form_definition = self.__get_user_type_form_definition( trans, user=None, **kwd )
user_type_fd_id = params.get( 'user_type_fd_id', 'none' )
if user_type_fd_id == 'none' and user_type_form_definition is not None:
user_type_fd_id = trans.security.encode_id( user_type_form_definition.id )
user_type_fd_id_select_field = self.__build_user_type_fd_id_select_field( trans, selected_value=user_type_fd_id )
widgets = self.__get_widgets( trans, user_type_form_definition, user=None, **kwd )
# Warning message that is shown on the registration page.
registration_warning_message = trans.app.config.registration_warning_message
else:
user_type_fd_id_select_field = None
user_type_form_definition = None
widgets = []
registration_warning_message = None
return trans.fill_template( '/user/register.mako',
cntrller=cntrller,
email=email,
username=transform_publicname( trans, username ),
subscribe_checked=subscribe_checked,
user_type_fd_id_select_field=user_type_fd_id_select_field,
user_type_form_definition=user_type_form_definition,
widgets=widgets,
use_panels=use_panels,
redirect=redirect,
redirect_url=redirect_url,
@@ -773,22 +741,6 @@ class User( BaseUIController, UsesFormDefinitionsMixin, CreatesUsersMixin, Creat
error = ''
success = True
if trans.webapp.name == 'galaxy':
# Save other information associated with the user, if any
user_info_forms = self.get_all_forms( trans,
filter=dict( deleted=False ),
form_type=trans.app.model.FormDefinition.types.USER_INFO )
# If there are no user forms available then there is nothing to save
if user_info_forms:
user_type_fd_id = kwd.get( 'user_type_fd_id', 'none' )
if user_type_fd_id not in [ 'none' ]:
user_type_form_definition = trans.sa_session.query( trans.app.model.FormDefinition ).get( trans.security.decode_id( user_type_fd_id ) )
values = self.get_form_values( trans, user, user_type_form_definition, **kwd )
form_values = trans.app.model.FormValues( user_type_form_definition, values )
trans.sa_session.add( form_values )
trans.sa_session.flush()
user.values = form_values
trans.sa_session.add( user )
trans.sa_session.flush()
if subscribe_checked:
# subscribe user to email list
if trans.app.config.smtp_server is None:
@@ -917,320 +869,6 @@ class User( BaseUIController, UsesFormDefinitionsMixin, CreatesUsersMixin, Creat
return trans.show_error_message( "You are using an invalid activation link. Try to log in and we will send you a new activation email. <br><a href='%s'>Go to login page.</a>" ) % web.url_for( controller='root', action='index' )
return
def __get_user_type_form_definition( self, trans, user=None, **kwd ):
params = util.Params( kwd )
if user and user.values:
user_type_fd_id = trans.security.encode_id( user.values.form_definition.id )
else:
user_type_fd_id = params.get( 'user_type_fd_id', 'none' )
if user_type_fd_id not in [ 'none' ]:
user_type_form_definition = trans.sa_session.query( trans.app.model.FormDefinition ).get( trans.security.decode_id( user_type_fd_id ) )
else:
user_type_form_definition = None
return user_type_form_definition
def __get_widgets( self, trans, user_type_form_definition, user=None, **kwd ):
widgets = []
if user_type_form_definition:
if user:
if user.values:
widgets = user_type_form_definition.get_widgets( user=user,
contents=user.values.content,
**kwd )
else:
widgets = user_type_form_definition.get_widgets( None, contents={}, **kwd )
else:
widgets = user_type_form_definition.get_widgets( None, contents={}, **kwd )
return widgets
@web.expose
def manage_user_info( self, trans, cntrller, **kwd ):
'''Manage a user's login, password, public username, type, addresses, etc.'''
params = util.Params( kwd )
user_id = params.get( 'id', None )
if user_id:
user = trans.sa_session.query( trans.app.model.User ).get( trans.security.decode_id( user_id ) )
else:
user = trans.user
if not user:
raise AssertionError("The user id (%s) is not valid" % str( user_id ))
email = util.restore_text( params.get( 'email', user.email ) )
username = util.restore_text( params.get( 'username', '' ) )
if not username:
username = user.username
message = escape( util.restore_text( params.get( 'message', '' ) ) )
status = params.get( 'status', 'done' )
if trans.webapp.name == 'galaxy':
user_type_form_definition = self.__get_user_type_form_definition( trans, user=user, **kwd )
user_type_fd_id = params.get( 'user_type_fd_id', 'none' )
if user_type_fd_id == 'none' and user_type_form_definition is not None:
user_type_fd_id = trans.security.encode_id( user_type_form_definition.id )
user_type_fd_id_select_field = self.__build_user_type_fd_id_select_field( trans, selected_value=user_type_fd_id )
widgets = self.__get_widgets( trans, user_type_form_definition, user=user, **kwd )
# user's addresses
show_filter = util.restore_text( params.get( 'show_filter', 'Active' ) )
if show_filter == 'All':
addresses = [address for address in user.addresses]
elif show_filter == 'Deleted':
addresses = [address for address in user.addresses if address.deleted]
else:
addresses = [address for address in user.addresses if not address.deleted]
user_info_forms = self.get_all_forms( trans,
filter=dict( deleted=False ),
form_type=trans.app.model.FormDefinition.types.USER_INFO )
return trans.fill_template( '/webapps/galaxy/user/manage_info.mako',
cntrller=cntrller,
user=user,
email=email,
username=username,
user_type_fd_id_select_field=user_type_fd_id_select_field,
user_info_forms=user_info_forms,
user_type_form_definition=user_type_form_definition,
user_type_fd_id=user_type_fd_id,
widgets=widgets,
addresses=addresses,
show_filter=show_filter,
message=message,
status=status )
else:
return trans.fill_template( '/webapps/tool_shed/user/manage_info.mako',
cntrller=cntrller,
user=user,
email=email,
username=username,
message=message,
status=status )
# For REMOTE_USER, we need the ability to just edit the username
@web.expose
@web.require_login( "to manage the public name" )
def edit_username( self, trans, cntrller, **kwd ):
params = util.Params( kwd )
is_admin = cntrller == 'admin' and trans.user_is_admin()
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
user_id = params.get( 'user_id', None )
if user_id and is_admin:
user = trans.sa_session.query( trans.app.model.User ).get( trans.security.decode_id( user_id ) )
else:
user = trans.user
if user and params.get( 'change_username_button', False ):
username = kwd.get( 'username', '' )
if username:
message = validate_publicname( trans, username, user )
if message:
status = 'error'
else:
user.username = username
trans.sa_session.add( user )
trans.sa_session.flush()
message = 'The username has been updated with the changes.'
return trans.fill_template( '/user/username.mako',
cntrller=cntrller,
user=user,
username=user.username,
message=message,
status=status )
@web.expose
def edit_info( self, trans, cntrller, **kwd ):
"""
Edit user information = username, email or password.
"""
params = util.Params( kwd )
is_admin = cntrller == 'admin' and trans.user_is_admin()
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
user_id = params.get( 'user_id', None )
if user_id and is_admin:
user = trans.sa_session.query( trans.app.model.User ).get( trans.security.decode_id( user_id ) )
elif user_id and ( not trans.user or trans.user.id != trans.security.decode_id( user_id ) ):
message = 'Invalid user id'
status = 'error'
user = None
else:
user = trans.user
if user and params.get( 'login_info_button', False ):
# Editing email and username
email = util.restore_text( params.get( 'email', '' ) )
username = util.restore_text( params.get( 'username', '' ) ).lower()
# Validate the new values for email and username
message = validate_email( trans, email, user )
if not message and username:
message = validate_publicname( trans, username, user )
if message:
status = 'error'
else:
if ( user.email != email ):
# The user's private role name must match the user's login ( email )
private_role = trans.app.security_agent.get_private_user_role( user )
private_role.name = email
private_role.description = 'Private role for ' + email
# Change the email itself
user.email = email
trans.sa_session.add_all( ( user, private_role ) )
trans.sa_session.flush()
if trans.webapp.name == 'galaxy' and trans.app.config.user_activation_on:
user.active = False
trans.sa_session.add( user )
trans.sa_session.flush()
is_activation_sent = self.send_verification_email( trans, user.email, user.username )
if is_activation_sent:
message = 'The login information has been updated with the changes.<br>Verification email has been sent to your new email address. Please verify it by clicking the activation link in the email.<br>Please check your spam/trash folder in case you cannot find the message.'
else:
message = 'Unable to send activation email, please contact your local Galaxy administrator.'
if trans.app.config.error_email_to is not None:
message += ' Contact: %s' % trans.app.config.error_email_to
if ( user.username != username ):
user.username = username
trans.sa_session.add( user )
trans.sa_session.flush()
message = 'The login information has been updated with the changes.'
elif user and params.get( 'edit_user_info_button', False ):
# Edit user information - webapp MUST BE 'galaxy'
user_type_fd_id = params.get( 'user_type_fd_id', 'none' )
if user_type_fd_id not in [ 'none' ]:
user_type_form_definition = trans.sa_session.query( trans.app.model.FormDefinition ).get( trans.security.decode_id( user_type_fd_id ) )
elif user.values:
user_type_form_definition = user.values.form_definition
else:
# User was created before any of the user_info forms were created
user_type_form_definition = None
if user_type_form_definition:
values = self.get_form_values( trans, user, user_type_form_definition, **kwd )
else:
values = {}
flush_needed = False
if user.values:
# Editing the user info of an existing user with existing user info
user.values.content = values
trans.sa_session.add( user.values )
flush_needed = True
elif values:
form_values = trans.model.FormValues( user_type_form_definition, values )
trans.sa_session.add( form_values )
user.values = form_values
flush_needed = True
if flush_needed:
trans.sa_session.add( user )
trans.sa_session.flush()
message = "The user information has been updated with the changes."
if user and trans.webapp.name == 'galaxy' and is_admin:
kwd[ 'user_id' ] = trans.security.encode_id( user.id )
kwd[ 'id' ] = user_id
if message:
kwd[ 'message' ] = util.sanitize_text( message )
if status:
kwd[ 'status' ] = status
return trans.response.send_redirect( web.url_for( controller='user',
action='manage_user_info',
cntrller=cntrller,
**kwd ) )
@web.expose
def change_password( self, trans, token=None, **kwd):
"""
Provides a form with which one can change their password. If token is
provided, don't require current password.
"""
status = None
message = kwd.get( 'message', '' )
user = None
if kwd.get( 'change_password_button', False ):
password = kwd.get( 'password', '' )
confirm = kwd.get( 'confirm', '' )
current = kwd.get( 'current', '' )
token_result = None
if token:
# If a token was supplied, validate and set user
token_result = trans.sa_session.query( trans.app.model.PasswordResetToken ).get(token)
if token_result and token_result.expiration_time > datetime.utcnow():
user = token_result.user
else:
return trans.show_error_message("Invalid or expired password reset token, please request a new one.")
else:
# The user is changing their own password, validate their current password
(ok, message) = trans.app.auth_manager.check_change_password(trans.user, current )
if ok:
user = trans.user
else:
status = 'error'
if user:
# Validate the new password
message = validate_password( trans, password, confirm )
if message:
status = 'error'
else:
# Save new password
user.set_password_cleartext( password )
# if we used a token, invalidate it and log the user in.
if token_result:
trans.handle_user_login(token_result.user)
token_result.expiration_time = datetime.utcnow()
trans.sa_session.add(token_result)
# Invalidate all other sessions
for other_galaxy_session in trans.sa_session.query( trans.app.model.GalaxySession ) \
.filter( and_( trans.app.model.GalaxySession.table.c.user_id == user.id,
trans.app.model.GalaxySession.table.c.is_valid == true(),
trans.app.model.GalaxySession.table.c.id != trans.galaxy_session.id ) ):
other_galaxy_session.is_valid = False
trans.sa_session.add( other_galaxy_session )
trans.sa_session.add( user )
trans.sa_session.flush()
trans.log_event( "User change password" )
if kwd.get('display_top', False) == 'True':
return trans.response.send_redirect( url_for( '/', message='Password has been changed' ))
else:
return trans.show_ok_message('The password has been changed and any other existing Galaxy sessions have been logged out (but jobs in histories in those sessions will not be interrupted).')
return trans.fill_template( '/user/change_password.mako',
token=token,
status=status,
message=message,
display_top=kwd.get('redirect_home', False)
)
@web.expose
def change_communication( self, trans, cntrller, **kwd):
"""
Provides a form with which the user can activate/deactivate
the commnication server.
"""
params = util.Params( kwd )
is_admin = cntrller == 'admin' and trans.user_is_admin()
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
user_id = params.get( 'user_id', None )
activated = ''
if user_id and is_admin:
user = trans.sa_session.query( trans.app.model.User ).get( trans.security.decode_id( user_id ) )
else:
user = trans.user
if user and params.get( 'change_communication_button', False ):
communication_enabled = kwd.get( 'enable_communication_server', False )
if communication_enabled:
activated = 'checked'
user.preferences['communication_server'] = True
message = 'Your communication settings has been updated and activated.'
else:
activated = ''
user.preferences['communication_server'] = False
message = 'Your communication settings has been updated and deactivated.'
trans.sa_session.add( user )
trans.sa_session.flush()
else:
if string_as_bool( user.preferences.get('communication_server', '0') ):
activated = 'checked'
return trans.fill_template( '/user/communication_settings.mako',
cntrller=cntrller,
status=status,
activated=activated,
message=message )
@web.expose
def reset_password( self, trans, email=None, **kwd ):
"""Reset the user's password. Send an email with token that allows a password change."""
@@ -1286,148 +924,8 @@ class User( BaseUIController, UsesFormDefinitionsMixin, CreatesUsersMixin, Creat
message = "\n".join( [ validate_email( trans, email ),
validate_password( trans, password, confirm ),
validate_publicname( trans, username ) ] ).rstrip()
if not message:
if trans.webapp.name == 'galaxy':
if self.get_all_forms( trans,
filter=dict( deleted=False ),
form_type=trans.app.model.FormDefinition.types.USER_INFO ):
user_type_fd_id = params.get( 'user_type_fd_id', 'none' )
if user_type_fd_id in [ 'none' ]:
return "Select the user's type and information"
return message
@web.expose
def set_default_permissions( self, trans, cntrller, **kwd ):
"""Set the user's default permissions for the new histories"""
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
if trans.user:
if 'update_roles_button' in kwd:
p = util.Params( kwd )
permissions = {}
for k, v in trans.app.model.Dataset.permitted_actions.items():
in_roles = p.get( k + '_in', [] )
if not isinstance( in_roles, list ):
in_roles = [ in_roles ]
in_roles = [ trans.sa_session.query( trans.app.model.Role ).get( x ) for x in in_roles ]
action = trans.app.security_agent.get_action( v.action ).action
permissions[ action ] = in_roles
trans.app.security_agent.user_set_default_permissions( trans.user, permissions )
message = 'Default new history permissions have been changed.'
return trans.fill_template( 'user/permissions.mako',
cntrller=cntrller,
message=message,
status=status )
else:
# User not logged in, history group must be only public
return trans.show_error_message( "You must be logged in to change your default permitted actions." )
@web.expose
@web.require_login()
def toolbox_filters( self, trans, cntrller, **kwd ):
"""
Sets the user's default filters for the toolbox.
Toolbox filters are specified in galaxy.ini.
The user can activate them and the choice is stored in user_preferences.
"""
def get_filter_mapping( db_filters, config_filters, factory ):
"""
Compare the allowed filters from the galaxy.ini config file with the previously saved or default filters from the database.
We need that to toogle the checkboxes for the formular in the right way.
Furthermore we extract all information associated to a filter to display them in the formular.
"""
filters = list()
for filter_name in config_filters:
function = factory._build_filter_function(filter_name)
doc_string = docstring_trim( function.__doc__ )
split = doc_string.split('\n\n')
if split:
sdesc = split[0]
else:
log.error( 'No description specified in the __doc__ string for %s.' % filter_name )
if len(split) > 1:
description = split[1]
else:
description = ''
if filter_name in db_filters:
filters.append( dict( filterpath=filter_name, short_desc=sdesc, desc=description, checked=True ) )
else:
filters.append( dict( filterpath=filter_name, short_desc=sdesc, desc=description, checked=False ) )
return filters
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
user_id = params.get( 'user_id', False )
if user_id:
user = trans.sa_session.query( trans.app.model.User ).get( trans.security.decode_id( user_id ) )
else:
user = trans.user
if user:
saved_user_tool_filters = list()
saved_user_section_filters = list()
saved_user_label_filters = list()
for name, value in user.preferences.items():
if name == 'toolbox_tool_filters':
saved_user_tool_filters = listify( value, do_strip=True )
elif name == 'toolbox_section_filters':
saved_user_section_filters = listify( value, do_strip=True )
elif name == 'toolbox_label_filters':
saved_user_label_filters = listify( value, do_strip=True )
ff = FilterFactory(trans.app.toolbox)
tool_filters = get_filter_mapping( saved_user_tool_filters, trans.app.config.user_tool_filters, ff )
section_filters = get_filter_mapping( saved_user_section_filters, trans.app.config.user_section_filters, ff )
label_filters = get_filter_mapping( saved_user_label_filters, trans.app.config.user_label_filters, ff )
return trans.fill_template( 'user/toolbox_filters.mako',
cntrller=cntrller,
message=message,
tool_filters=tool_filters,
section_filters=section_filters,
label_filters=label_filters,
user=user,
status=status )
else:
# User not logged in, history group must be only public
return trans.show_error_message( "You must be logged in to change private toolbox filters." )
@web.expose
@web.require_login( "to change the private toolbox filters" )
def edit_toolbox_filters( self, trans, cntrller, **kwd ):
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
if params.get( 'edit_toolbox_filter_button', False ):
tool_filters = list()
section_filters = list()
label_filters = list()
for name, state in params.flatten():
if state == 'on':
if name.startswith('t_'):
tool_filters.append( name[2:] )
elif name.startswith('l_'):
label_filters.append( name[2:] )
elif name.startswith('s_'):
section_filters.append( name[2:] )
trans.user.preferences['toolbox_tool_filters'] = ','.join( tool_filters )
trans.user.preferences['toolbox_section_filters'] = ','.join( section_filters )
trans.user.preferences['toolbox_label_filters'] = ','.join( label_filters )
trans.sa_session.add( trans.user )
trans.sa_session.flush()
message = 'ToolBox filters has been updated.'
kwd = dict( message=message, status='done' )
# Display the ToolBox filters form with the current values filled in
return self.toolbox_filters( trans, cntrller, **kwd )
@web.expose
@web.require_login( "to get most recently used tool" )
@web.json_pretty
@@ -1450,237 +948,6 @@ class User( BaseUIController, UsesFormDefinitionsMixin, CreatesUsersMixin, Creat
"description": tool.description}
return tool_info
@web.expose
def manage_addresses(self, trans, **kwd):
if trans.user:
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
show_filter = util.restore_text( params.get( 'show_filter', 'Active' ) )
if show_filter == 'All':
addresses = [address for address in trans.user.addresses]
elif show_filter == 'Deleted':
addresses = [address for address in trans.user.addresses if address.deleted]
else:
addresses = [address for address in trans.user.addresses if not address.deleted]
return trans.fill_template( 'user/address.mako',
addresses=addresses,
show_filter=show_filter,
message=message,
status=status)
else:
# User not logged in, history group must be only public
return trans.show_error_message( "You must be logged in to change your default permitted actions." )
@web.require_login( "to add addresses" )
@web.expose
def new_address( self, trans, cntrller, **kwd ):
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
is_admin = cntrller == 'admin' and trans.user_is_admin()
user_id = params.get( 'id', False )
if is_admin:
if not user_id:
return trans.show_error_message( "You must specify a user to add a new address to." )
user = trans.sa_session.query( trans.app.model.User ).get( trans.security.decode_id( user_id ) )
else:
user = trans.user
short_desc = util.restore_text( params.get( 'short_desc', '' ) )
name = util.restore_text( params.get( 'name', '' ) )
institution = util.restore_text( params.get( 'institution', '' ) )
address = util.restore_text( params.get( 'address', '' ) )
city = util.restore_text( params.get( 'city', '' ) )
state = util.restore_text( params.get( 'state', '' ) )
postal_code = util.restore_text( params.get( 'postal_code', '' ) )
country = util.restore_text( params.get( 'country', '' ) )
phone = util.restore_text( params.get( 'phone', '' ) )
ok = True
if not trans.app.config.allow_user_creation and not is_admin:
return trans.show_error_message( 'User registration is disabled. Please contact your local Galaxy administrator for an account.' )
if params.get( 'new_address_button', False ):
if not short_desc:
ok = False
message = 'Enter a short description for this address'
elif not name:
ok = False
message = 'Enter the name'
elif not institution:
ok = False
message = 'Enter the institution associated with the user'
elif not address:
ok = False
message = 'Enter the address'
elif not city:
ok = False
message = 'Enter the city'
elif not state:
ok = False
message = 'Enter the state/province/region'
elif not postal_code:
ok = False
message = 'Enter the postal code'
elif not country:
ok = False
message = 'Enter the country'
if ok:
user_address = trans.model.UserAddress( user=user,
desc=short_desc,
name=name,
institution=institution,
address=address,
city=city,
state=state,
postal_code=postal_code,
country=country,
phone=phone )
trans.sa_session.add( user_address )
trans.sa_session.flush()
message = 'Address (%s) has been added' % escape( user_address.desc )
new_kwd = dict( message=message, status=status )
if is_admin:
new_kwd[ 'id' ] = trans.security.encode_id( user.id )
return trans.response.send_redirect( web.url_for( controller='user',
action='manage_user_info',
cntrller=cntrller,
**new_kwd ) )
# Display the address form with the current values filled in
return trans.fill_template( 'user/new_address.mako',
cntrller=cntrller,
user=user,
short_desc=short_desc,
name=name,
institution=institution,
address=address,
city=city,
state=state,
postal_code=postal_code,
country=country,
phone=phone,
message=escape(message),
status=status )
@web.require_login( "to edit addresses" )
@web.expose
def edit_address( self, trans, cntrller, **kwd ):
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
is_admin = cntrller == 'admin' and trans.user_is_admin()
user_id = params.get( 'id', False )
if is_admin:
if not user_id:
return trans.show_error_message( "You must specify a user to add a new address to." )
user = trans.sa_session.query( trans.app.model.User ).get( trans.security.decode_id( user_id ) )
else:
user = trans.user
address_id = params.get( 'address_id', None )
if not address_id:
return trans.show_error_message( "Invalid address id." )
address_obj = trans.sa_session.query( trans.app.model.UserAddress ).get( trans.security.decode_id( address_id ) )
if address_obj.user_id != user.id:
return trans.show_error_message( "Invalid address id." )
if params.get( 'edit_address_button', False ):
short_desc = util.restore_text( params.get( 'short_desc', '' ) )
name = util.restore_text( params.get( 'name', '' ) )
institution = util.restore_text( params.get( 'institution', '' ) )
address = util.restore_text( params.get( 'address', '' ) )
city = util.restore_text( params.get( 'city', '' ) )
state = util.restore_text( params.get( 'state', '' ) )
postal_code = util.restore_text( params.get( 'postal_code', '' ) )
country = util.restore_text( params.get( 'country', '' ) )
phone = util.restore_text( params.get( 'phone', '' ) )
ok = True
if not short_desc:
ok = False
message = 'Enter a short description for this address'
elif not name:
ok = False
message = 'Enter the name'
elif not institution:
ok = False
message = 'Enter the institution associated with the user'
elif not address:
ok = False
message = 'Enter the address'
elif not city:
ok = False
message = 'Enter the city'
elif not state:
ok = False
message = 'Enter the state/province/region'
elif not postal_code:
ok = False
message = 'Enter the postal code'
elif not country:
ok = False
message = 'Enter the country'
if ok:
address_obj.desc = short_desc
address_obj.name = name
address_obj.institution = institution
address_obj.address = address
address_obj.city = city
address_obj.state = state
address_obj.postal_code = postal_code
address_obj.country = country
address_obj.phone = phone
trans.sa_session.add( address_obj )
trans.sa_session.flush()
message = 'Address (%s) has been updated.' % escape( address_obj.desc )
new_kwd = dict( message=message, status=status )
if is_admin:
new_kwd[ 'id' ] = trans.security.encode_id( user.id )
return trans.response.send_redirect( web.url_for( controller='user',
action='manage_user_info',
cntrller=cntrller,
**new_kwd ) )
# Display the address form with the current values filled in
return trans.fill_template( 'user/edit_address.mako',
cntrller=cntrller,
user=user,
address_obj=address_obj,
message=escape( message ),
status=status )
@web.require_login( "to delete addresses" )
@web.expose
def delete_address( self, trans, cntrller, address_id=None, **kwd ):
return self.__delete_undelete_address( trans, cntrller, 'delete', address_id=address_id, **kwd )
@web.require_login( "to undelete addresses" )
@web.expose
def undelete_address( self, trans, cntrller, address_id=None, **kwd ):
return self.__delete_undelete_address( trans, cntrller, 'undelete', address_id=address_id, **kwd )
def __delete_undelete_address( self, trans, cntrller, op, address_id=None, **kwd ):
is_admin = cntrller == 'admin' and trans.user_is_admin()
user_id = kwd.get( 'id', False )
if is_admin:
if not user_id:
return trans.show_error_message( "You must specify a user to %s an address from." % op )
user = trans.sa_session.query( trans.app.model.User ).get( trans.security.decode_id( user_id ) )
else:
user = trans.user
try:
user_address = trans.sa_session.query( trans.app.model.UserAddress ).get( trans.security.decode_id( address_id ) )
except:
return trans.show_error_message( "Invalid address id." )
if user_address:
if user_address.user_id != user.id:
return trans.show_error_message( "Invalid address id." )
user_address.deleted = True if op == 'delete' else False
trans.sa_session.add( user_address )
trans.sa_session.flush()
message = 'Address (%s) %sd' % ( escape( user_address.desc ), op )
status = 'done'
return trans.response.send_redirect( web.url_for( controller='user',
action='manage_user_info',
cntrller=cntrller,
id=trans.security.encode_id( user.id ),
message=message,
status=status ) )
@web.expose
def set_user_pref_async( self, trans, pref_name, pref_value ):
""" Set a user preference asynchronously. If user is not logged in, do nothing. """
@@ -1837,22 +1104,6 @@ class User( BaseUIController, UsesFormDefinitionsMixin, CreatesUsersMixin, Creat
fasta_hdas=fasta_hdas,
use_panels=kwds.get( 'use_panels', False ) )
@web.expose
@web.require_login()
def api_keys( self, trans, cntrller, **kwd ):
params = util.Params( kwd )
message = escape( util.restore_text( params.get( 'message', '' ) ) )
status = params.get( 'status', 'done' )
if params.get( 'new_api_key_button', False ):
self.create_api_key( trans, trans.user )
message = "Generated a new web API key"
status = "done"
return trans.fill_template( 'webapps/galaxy/user/api_keys.mako',
cntrller=cntrller,
user=trans.user,
message=message,
status=status )
def __get_redirect_url( self, redirect ):
root_url = url_for( '/', qualified=True )
# compare urls, to prevent a redirect from pointing (directly) outside of galaxy
@@ -1863,17 +1114,3 @@ class User( BaseUIController, UsesFormDefinitionsMixin, CreatesUsersMixin, Creat
elif util.compare_urls( url_for( controller='user', action='logout', qualified=True ), redirect ):
redirect = root_url
return redirect
# ===== Methods for building SelectFields ================================
def __build_user_type_fd_id_select_field( self, trans, selected_value ):
# Get all the user information forms
user_info_forms = self.get_all_forms( trans,
filter=dict( deleted=False ),
form_type=trans.model.FormDefinition.types.USER_INFO )
return build_select_field( trans,
objs=user_info_forms,
label_attr='name',
select_field_name='user_type_fd_id',
initial_value='none',
selected_value=selected_value,
refresh_on_change=True )
@@ -1,3 +1,250 @@
from galaxy.webapps.galaxy.controllers.user import User
from datetime import datetime
__all__ = ('User', )
from markupsafe import escape
from sqlalchemy import and_
from sqlalchemy import true
from galaxy import util
from galaxy import web
from galaxy.security.validate_user_input import validate_email, validate_password, validate_publicname
from galaxy.web import url_for
from galaxy.webapps.galaxy.controllers.user import User as BaseUser
class User( BaseUser ):
@web.expose
def index( self, trans, cntrller='user', **kwd ):
return trans.fill_template( '/webapps/tool_shed/user/index.mako', cntrller=cntrller )
@web.expose
def manage_user_info( self, trans, cntrller, **kwd ):
'''Manage a user's login, password, public username, type, addresses, etc.'''
params = util.Params( kwd )
user_id = params.get( 'id', None )
if user_id:
user = trans.sa_session.query( trans.app.model.User ).get( trans.security.decode_id( user_id ) )
else:
user = trans.user
if not user:
raise AssertionError("The user id (%s) is not valid" % str( user_id ))
email = util.restore_text( params.get( 'email', user.email ) )
username = util.restore_text( params.get( 'username', '' ) )
if not username:
username = user.username
message = escape( util.restore_text( params.get( 'message', '' ) ) )
status = params.get( 'status', 'done' )
return trans.fill_template( '/webapps/tool_shed/user/manage_info.mako',
cntrller=cntrller,
user=user,
email=email,
username=username,
message=message,
status=status )
@web.expose
@web.require_login()
def api_keys( self, trans, cntrller, **kwd ):
params = util.Params( kwd )
message = escape( util.restore_text( params.get( 'message', '' ) ) )
status = params.get( 'status', 'done' )
if params.get( 'new_api_key_button', False ):
self.create_api_key( trans, trans.user )
message = "Generated a new web API key"
status = "done"
return trans.fill_template( '/webapps/tool_shed/user/api_keys.mako',
cntrller=cntrller,
user=trans.user,
message=message,
status=status )
# For REMOTE_USER, we need the ability to just edit the username
@web.expose
@web.require_login( "to manage the public name" )
def edit_username( self, trans, cntrller, **kwd ):
params = util.Params( kwd )
is_admin = cntrller == 'admin' and trans.user_is_admin()
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
user_id = params.get( 'user_id', None )
if user_id and is_admin:
user = trans.sa_session.query( trans.app.model.User ).get( trans.security.decode_id( user_id ) )
else:
user = trans.user
if user and params.get( 'change_username_button', False ):
username = kwd.get( 'username', '' )
if username:
message = validate_publicname( trans, username, user )
if message:
status = 'error'
else:
user.username = username
trans.sa_session.add( user )
trans.sa_session.flush()
message = 'The username has been updated with the changes.'
return trans.fill_template( '/webapps/tool_shed/user/username.mako',
cntrller=cntrller,
user=user,
username=user.username,
message=message,
status=status )
@web.expose
def edit_info( self, trans, cntrller, **kwd ):
"""
Edit user information = username, email or password.
"""
params = util.Params( kwd )
is_admin = cntrller == 'admin' and trans.user_is_admin()
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
user_id = params.get( 'user_id', None )
if user_id and is_admin:
user = trans.sa_session.query( trans.app.model.User ).get( trans.security.decode_id( user_id ) )
elif user_id and ( not trans.user or trans.user.id != trans.security.decode_id( user_id ) ):
message = 'Invalid user id'
status = 'error'
user = None
else:
user = trans.user
if user and params.get( 'login_info_button', False ):
# Editing email and username
email = util.restore_text( params.get( 'email', '' ) )
username = util.restore_text( params.get( 'username', '' ) ).lower()
# Validate the new values for email and username
message = validate_email( trans, email, user )
if not message and username:
message = validate_publicname( trans, username, user )
if message:
status = 'error'
else:
if ( user.email != email ):
# The user's private role name must match the user's login ( email )
private_role = trans.app.security_agent.get_private_user_role( user )
private_role.name = email
private_role.description = 'Private role for ' + email
# Change the email itself
user.email = email
trans.sa_session.add_all( ( user, private_role ) )
trans.sa_session.flush()
if trans.webapp.name == 'galaxy' and trans.app.config.user_activation_on:
user.active = False
trans.sa_session.add( user )
trans.sa_session.flush()
is_activation_sent = self.send_verification_email( trans, user.email, user.username )
if is_activation_sent:
message = 'The login information has been updated with the changes.<br>Verification email has been sent to your new email address. Please verify it by clicking the activation link in the email.<br>Please check your spam/trash folder in case you cannot find the message.'
else:
message = 'Unable to send activation email, please contact your local Galaxy administrator.'
if trans.app.config.error_email_to is not None:
message += ' Contact: %s' % trans.app.config.error_email_to
if ( user.username != username ):
user.username = username
trans.sa_session.add( user )
trans.sa_session.flush()
message = 'The login information has been updated with the changes.'
elif user and params.get( 'edit_user_info_button', False ):
# Edit user information - webapp MUST BE 'galaxy'
user_type_fd_id = params.get( 'user_type_fd_id', 'none' )
if user_type_fd_id not in [ 'none' ]:
user_type_form_definition = trans.sa_session.query( trans.app.model.FormDefinition ).get( trans.security.decode_id( user_type_fd_id ) )
elif user.values:
user_type_form_definition = user.values.form_definition
else:
# User was created before any of the user_info forms were created
user_type_form_definition = None
if user_type_form_definition:
values = self.get_form_values( trans, user, user_type_form_definition, **kwd )
else:
values = {}
flush_needed = False
if user.values:
# Editing the user info of an existing user with existing user info
user.values.content = values
trans.sa_session.add( user.values )
flush_needed = True
elif values:
form_values = trans.model.FormValues( user_type_form_definition, values )
trans.sa_session.add( form_values )
user.values = form_values
flush_needed = True
if flush_needed:
trans.sa_session.add( user )
trans.sa_session.flush()
message = "The user information has been updated with the changes."
if user and trans.webapp.name == 'galaxy' and is_admin:
kwd[ 'user_id' ] = trans.security.encode_id( user.id )
kwd[ 'id' ] = user_id
if message:
kwd[ 'message' ] = util.sanitize_text( message )
if status:
kwd[ 'status' ] = status
return trans.response.send_redirect( web.url_for( controller='user',
action='manage_user_info',
cntrller=cntrller,
**kwd ) )
@web.expose
def change_password( self, trans, token=None, **kwd):
"""
Provides a form with which one can change their password. If token is
provided, don't require current password.
"""
status = None
message = kwd.get( 'message', '' )
user = None
if kwd.get( 'change_password_button', False ):
password = kwd.get( 'password', '' )
confirm = kwd.get( 'confirm', '' )
current = kwd.get( 'current', '' )
token_result = None
if token:
# If a token was supplied, validate and set user
token_result = trans.sa_session.query( trans.app.model.PasswordResetToken ).get(token)
if token_result and token_result.expiration_time > datetime.utcnow():
user = token_result.user
else:
return trans.show_error_message("Invalid or expired password reset token, please request a new one.")
else:
# The user is changing their own password, validate their current password
(ok, message) = trans.app.auth_manager.check_change_password(trans.user, current )
if ok:
user = trans.user
else:
status = 'error'
if user:
# Validate the new password
message = validate_password( trans, password, confirm )
if message:
status = 'error'
else:
# Save new password
user.set_password_cleartext( password )
# if we used a token, invalidate it and log the user in.
if token_result:
trans.handle_user_login(token_result.user)
token_result.expiration_time = datetime.utcnow()
trans.sa_session.add(token_result)
# Invalidate all other sessions
for other_galaxy_session in trans.sa_session.query( trans.app.model.GalaxySession ) \
.filter( and_( trans.app.model.GalaxySession.table.c.user_id == user.id,
trans.app.model.GalaxySession.table.c.is_valid == true(),
trans.app.model.GalaxySession.table.c.id != trans.galaxy_session.id ) ):
other_galaxy_session.is_valid = False
trans.sa_session.add( other_galaxy_session )
trans.sa_session.add( user )
trans.sa_session.flush()
trans.log_event( "User change password" )
if kwd.get('display_top', False) == 'True':
return trans.response.send_redirect( url_for( '/', message='Password has been changed' ))
else:
return trans.show_ok_message('The password has been changed and any other existing Galaxy sessions have been logged out (but jobs in histories in those sessions will not be interrupted).')
return trans.fill_template( '/webapps/tool_shed/user/change_password.mako',
token=token,
status=status,
message=message,
display_top=kwd.get('redirect_home', False)
)
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"page.js","sources":["../../src/layout/page.js"],"names":["define","Masthead","Panel","Modal","BaseMVC","PageLayoutView","Backbone","View","extend","LoggableMixin","_logNamespace","el","className","_panelIds","defaultOptions","message_box_visible","message_box_content","message_box_class","show_inactivity_warning","inactivity_box_content","initialize","options","this","log","_","pick","defaults","omit","config","Galaxy","modal","masthead","$el","attr","html","_template","append","frame","$","replaceWith","$messagebox","$inactivebox","render","remove","renderMessageBox","renderInactivityBox","renderPanels","_checkCommunicationServerOnline","content","level","addClass","toggle","show","removeClass","hide","verificationLink","root","text","page","forEach","panelId","has","setElement","left","center","css","right","join","hideSidePanels","toString","host","window","communication_server_host","port","communication_server_port","$chat_icon_element","undefined","user","attributes","preferences","communication_server","ajax","url","success","id","error"],"mappings":"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"}
{"version":3,"file":"page.js","sources":["../../src/layout/page.js"],"names":["define","Masthead","Panel","Modal","BaseMVC","PageLayoutView","Backbone","View","extend","LoggableMixin","_logNamespace","el","className","_panelIds","defaultOptions","message_box_visible","message_box_content","message_box_class","show_inactivity_warning","inactivity_box_content","initialize","options","this","log","_","pick","defaults","omit","config","Galaxy","modal","masthead","$el","attr","html","_template","append","frame","$","replaceWith","$messagebox","$inactivebox","render","remove","renderMessageBox","renderInactivityBox","renderPanels","_checkCommunicationServerOnline","content","level","addClass","toggle","show","removeClass","hide","verificationLink","root","text","page","forEach","panelId","has","setElement","left","center","css","right","join","hideSidePanels","toString","host","window","communication_server_host","port","communication_server_port","preferences","user","attributes","$chat_icon_element","indexOf","communication_server","ajax","url","success","id","error"],"mappings":"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"}
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"form-parameters.js","sources":["../../../src/mvc/form/form-parameters.js"],"names":["define","Utils","Ui","SelectContent","SelectLibrary","SelectFtp","ColorPicker","Backbone","Model","extend","types","text","select","data_column","genomebuild","data","data_collection","integer","float","boolean","drill_down","color","hidden","hidden_data","baseurl","library_data","ftpfile","create","input_def","fieldClass","this","type","field","call","options","_fieldSelect","_fieldText","Galaxy","emit","debug","undefined","value","_fieldData","View","id","extensions","optional","multiple","flavor","onchange","is_workflow","error_text","_","each","option","push","label","SelectClass","Select","display","Checkbox","Radio","RadioButton","searchable","_fieldDrilldown","Drilldown","area","isEmpty","$","isArray","str_value","i","String","Input","placeholder","_fieldSlider","Slider","precise","min","max","_fieldHidden","Hidden","info","_fieldBoolean","_fieldColor","_fieldLibrary","_fieldFtp"],"mappings":"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"}
{"version":3,"file":"form-parameters.js","sources":["../../../src/mvc/form/form-parameters.js"],"names":["define","Utils","Ui","SelectContent","SelectLibrary","SelectFtp","ColorPicker","Backbone","Model","extend","types","text","password","select","data_column","genomebuild","data","data_collection","integer","float","boolean","drill_down","color","hidden","hidden_data","baseurl","library_data","ftpfile","create","input_def","fieldClass","this","type","field","call","options","_fieldSelect","_fieldText","Galaxy","emit","debug","undefined","value","_fieldData","View","id","extensions","optional","multiple","flavor","onchange","is_workflow","error_text","_","each","option","push","label","SelectClass","Select","display","Checkbox","Radio","RadioButton","searchable","_fieldDrilldown","Drilldown","area","isEmpty","$","isArray","str_value","i","String","Input","readonly","placeholder","_fieldSlider","Slider","precise","min","max","_fieldHidden","Hidden","info","_fieldBoolean","_fieldColor","_fieldLibrary","_fieldFtp"],"mappings":"AAGAA,QAAQ,cACA,iBACA,2BACA,2BACA,uBACA,0BACJ,SAAUC,EAAOC,EAAIC,EAAeC,EAAeC,EAAWC,GAG9D,MAAOC,UAASC,MAAMC,QAElBC,OACIC,KAAsB,aACtBC,SAAsB,aACtBC,OAAsB,eACtBC,YAAsB,eACtBC,YAAsB,eACtBC,KAAsB,aACtBC,gBAAsB,aACtBC,QAAsB,eACtBC,QAAsB,eACtBC,UAAsB,gBACtBC,WAAsB,kBACtBC,MAAsB,cACtBC,OAAsB,eACtBC,YAAsB,eACtBC,QAAsB,eACtBC,aAAsB,gBACtBC,QAAsB,aAI1BC,OAAQ,SAAUC,GACd,GAAIC,GAAaC,KAAKrB,MAAOmB,EAAUG,MACnCC,EAAyC,kBAAzBF,MAAMD,GAAgCC,KAAMD,GAAaI,KAAMH,KAAMF,GAAc,IAOvG,OANMI,KACFA,EAAQJ,EAAUM,QAAUJ,KAAKK,aAAcP,GAAcE,KAAKM,WAAYR,GAC9ES,OAAOC,KAAKC,MAAM,6BAA8B,4BAA8BX,EAAUG,KAAO,OAE/ES,SAApBZ,EAAUa,QAAyBb,EAAUa,MAAQ,MACrDT,EAAMS,MAAOb,EAAUa,OAChBT,GAIXU,WAAY,SAAUd,GAClB,MAAO,IAAI1B,GAAcyC,MACrBC,GAAc,SAAWhB,EAAUgB,GACnCC,WAAcjB,EAAUiB,WACxBC,SAAclB,EAAUkB,SACxBC,SAAcnB,EAAUmB,SACxBhB,KAAcH,EAAUG,KACxBiB,OAAcpB,EAAUoB,OACxBjC,KAAca,EAAUM,QACxBe,SAAcrB,EAAUqB,YAKhCd,aAAc,SAAWP,GAErB,GAAIA,EAAUsB,YACV,MAAOpB,MAAKM,WAAYR,EAIL,gBAAlBA,EAAUG,OACXH,EAAUuB,WAAa,yCAI3B,IAAIpC,GAAOa,EAAUb,IAChBA,KACDA,KACAqC,EAAEC,KAAMzB,EAAUM,QAAS,SAAUoB,GACjCvC,EAAKwC,MAAQC,MAAOF,EAAQ,GAAKb,MAAOa,EAAQ,OAKxD,IAAIG,GAAcxD,EAAGyD,MACrB,QAAS9B,EAAU+B,SACf,IAAK,aACDF,EAAcxD,EAAG2D,QACjB,MACJ,KAAK,QACDH,EAAcxD,EAAG4D,KACjB,MACJ,KAAK,cACDJ,EAAcxD,EAAG6D,YAKzB,MAAO,IAAIL,GAAYd,MACnBC,GAAc,SAAWhB,EAAUgB,GACnC7B,KAAcA,EACdoC,WAAcvB,EAAUuB,YAAc,uBACtCJ,SAAcnB,EAAUmB,SACxBD,SAAclB,EAAUkB,SACxBG,SAAcrB,EAAUqB,SACxBc,WAAmC,aAArBnC,EAAUoB,UAKhCgB,gBAAiB,SAAWpC,GAExB,MAAIA,GAAUsB,YACHpB,KAAKM,WAAYR,GAIrB,GAAI3B,GAAGgE,UAAUtB,MACpBC,GAAc,SAAWhB,EAAUgB,GACnC7B,KAAca,EAAUM,QACxByB,QAAc/B,EAAU+B,QACxBb,SAAclB,EAAUkB,SACxBG,SAAcrB,EAAUqB,YAKhCb,WAAY,SAAUR,GAElB,GAAKA,EAAUM,SAAWN,EAAUb,KAEhC,GADAa,EAAUsC,KAAOtC,EAAUmB,SACtB/C,EAAMmE,QAASvC,EAAUa,OAC1Bb,EAAUa,MAAQ,SAElB,IAAK2B,EAAEC,QAASzC,EAAUa,OAAU,CAChC,GAAI6B,GAAY,EAChB,KAAM,GAAIC,KAAK3C,GAAUa,MAAQ,CAE7B,GADA6B,GAAaE,OAAQ5C,EAAUa,MAAO8B,KAChC3C,EAAUmB,SACZ,KAEJuB,IAAa,KAEjB1C,EAAUa,MAAQ6B,EAK9B,MAAO,IAAIrE,GAAGwE,OACV7B,GAAc,SAAWhB,EAAUgB,GACnCb,KAAcH,EAAUG,KACxBmC,KAActC,EAAUsC,KACxBQ,SAAc9C,EAAU8C,SACxBC,YAAc/C,EAAU+C,YACxB1B,SAAcrB,EAAUqB,YAKhC2B,aAAc,SAAUhD,GACpB,MAAO,IAAI3B,GAAG4E,OAAOlC,MACjBC,GAAc,SAAWhB,EAAUgB,GACnCkC,QAAgC,SAAlBlD,EAAUG,KACxBmB,YAActB,EAAUsB,YACxB6B,IAAcnD,EAAUmD,IACxBC,IAAcpD,EAAUoD,IACxB/B,SAAcrB,EAAUqB,YAKhCgC,aAAc,SAAUrD,GACpB,MAAO,IAAI3B,GAAGiF,QACVtC,GAAc,SAAWhB,EAAUgB,GACnCuC,KAAcvD,EAAUuD,QAKhCC,cAAe,SAAUxD,GACrB,MAAO,IAAI3B,GAAG6D,YAAYnB,MACtBC,GAAc,SAAWhB,EAAUgB,GACnC7B,OAAkByC,MAAQ,MAAOf,MAAQ,SACvBe,MAAQ,KAAOf,MAAQ,UACzCQ,SAAcrB,EAAUqB,YAKhCoC,YAAa,SAAUzD,GACnB,MAAO,IAAIvB,IACPuC,GAAc,SAAWhB,EAAUgB,GACnCK,SAAcrB,EAAUqB,YAKhCqC,cAAe,SAAU1D,GACrB,MAAO,IAAIzB,GAAcwC,MACrBC,GAAc,SAAWhB,EAAUgB,GACnCE,SAAclB,EAAUkB,SACxBC,SAAcnB,EAAUmB,SACxBE,SAAcrB,EAAUqB,YAKhCsC,UAAW,SAAU3D,GACjB,MAAO,IAAIxB,GAAUuC,MACjBC,GAAc,SAAWhB,EAAUgB,GACnCE,SAAclB,EAAUkB,SACxBC,SAAcnB,EAAUmB,SACxBE,SAAcrB,EAAUqB"}
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"form-section.js","sources":["../../../src/mvc/form/form-section.js"],"names":["define","Utils","Ui","Portlet","Repeat","InputElement","Parameters","View","Backbone","extend","initialize","app","options","this","inputs","parameters","setElement","$","render","self","$el","empty","_","each","input","add","input_def","jQuery","id","uid","input_list","type","_addConditional","_addRepeat","_addSection","_addRow","test_param","sustain_conditionals","disabled","field","model","set","value","selectedCase","data","matchCase","i","cases","case_def","section_row","nonhidden","j","hidden","fadeIn","hide","trigger","sub_section","_append","addClass","create","sub_section_id","block_index","repeat","ondel","del","title","min","max","onnew","n_cache","size","cache","Math","default","sustain_repeats","hideOptions","input_element","label","name","help","portlet","cls","collapsible","collapsible_button","collapsed","expanded","append","html","on","input_id","length","expand","onchange","field_list","text_value","collapsible_value","collapsible_preview","argument","color","style","backdrop","element_list","attr"],"mappings":"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"}
{"version":3,"file":"form-section.js","sources":["../../../src/mvc/form/form-section.js"],"names":["define","Utils","Ui","Portlet","Repeat","InputElement","Parameters","View","Backbone","extend","initialize","app","options","this","inputs","parameters","setElement","$","render","self","$el","empty","_","each","input","add","input_def","jQuery","id","uid","input_list","type","_addConditional","_addRepeat","_addSection","_addRow","test_param","sustain_conditionals","disabled","field","model","set","value","selectedCase","data","matchCase","i","cases","case_def","section_row","nonhidden","j","hidden","fadeIn","hide","trigger","sub_section","_append","addClass","create","sub_section_id","block_index","repeat","ondel","del","title","min","max","onnew","n_cache","size","cache","Math","default","sustain_repeats","hideOptions","input_element","label","name","help","portlet","cls","collapsible","collapsible_button","collapsed","expanded","append","html","on","input_id","length","expand","onchange","field_list","text_value","collapsible_value","collapsible_preview","argument","color","style","backdrop","element_list","attr"],"mappings":"AAGAA,QAAS,cAAe,iBAAkB,oBAAqB,uBAAwB,sBAAuB,4BAC9G,SAAUC,EAAOC,EAAIC,EAASC,EAAQC,EAAcC,GAChD,GAAIC,GAAOC,SAASD,KAAKE,QACrBC,WAAY,SAAUC,EAAKC,GACvBC,KAAKF,IAAMA,EACXE,KAAKC,OAASF,EAAQE,OACtBD,KAAKE,WAAa,GAAIT,GACtBO,KAAKG,WAAYC,EAAG,WACpBJ,KAAKK,UAITA,OAAQ,WACJ,GAAIC,GAAON,IACXA,MAAKO,IAAIC,QACTC,EAAEC,KAAMV,KAAKC,OAAQ,SAAUU,GAAUL,EAAKM,IAAKD,MAIvDC,IAAK,SAAUD,GACX,GAAIE,GAAYC,OAAOlB,QAAQ,KAAUe,EAGzC,QAFAE,EAAUE,GAAKJ,EAAMI,GAAK3B,EAAM4B,MAChChB,KAAKF,IAAImB,WAAYJ,EAAUE,IAAOF,EAC9BA,EAAUK,MACd,IAAK,cACDlB,KAAKmB,gBAAiBN,EACtB,MACJ,KAAK,SACDb,KAAKoB,WAAYP,EACjB,MACJ,KAAK,UACDb,KAAKqB,YAAaR,EAClB,MACJ,SACIb,KAAKsB,QAAST,KAK1BM,gBAAiB,SAAUN,GACvB,GAAIP,GAAON,IACXa,GAAUU,WAAWR,GAAKF,EAAUE,GACpCf,KAAKF,IAAIC,QAAQyB,uBAA0BX,EAAUU,WAAWE,UAAW,EAC3E,IAAIC,GAAQ1B,KAAKsB,QAAST,EAAUU,WAGpCG,GAAMC,OAASD,EAAMC,MAAMC,IAAK,WAAY,SAAUC,GAClD,GAAIC,GAAexB,EAAKR,IAAIiC,KAAKC,UAAWnB,EAAWgB,EACvD,KAAM,GAAII,KAAKpB,GAAUqB,MAAQ,CAC7B,GAAIC,GAAWtB,EAAUqB,MAAOD,GAC5BG,EAAc9B,EAAKF,EAAG,IAAMS,EAAUE,GAAK,YAAckB,GACzDI,GAAY,CAChB,KAAM,GAAIC,KAAKH,GAASlC,OACpB,IAAMkC,EAASlC,OAAQqC,GAAIC,OAAS,CAChCF,GAAY,CACZ,OAGHJ,GAAKH,GAAgBO,EACtBD,EAAYI,OAAQ,QAEpBJ,EAAYK,OAGpBnC,EAAKR,IAAI4C,QAAS,WAItB,KAAM,GAAIT,KAAKpB,GAAUqB,MAAQ,CAC7B,GAAIS,GAAc,GAAIjD,GAAMM,KAAKF,KAAOG,OAAQY,EAAUqB,MAAOD,GAAIhC,QACrED,MAAK4C,QAASD,EAAYpC,IAAIsC,SAAU,mBAAqBhC,EAAUE,GAAK,YAAckB,GAI9FP,EAAMgB,QAAS,WAInBtB,WAAY,SAAUP,GAalB,QAASiC,GAAS7C,GACd,GAAI8C,GAAiBlC,EAAUE,GAAK,YAAgBiC,IAChDL,EAAc,GAAIjD,GAAMY,EAAKR,KAAOG,OAAQA,GAChDgD,GAAOrC,KAAOG,GAAUgC,EACVxC,IAAUoC,EAAYpC,IACtB2C,MAAU,WAAaD,EAAOE,IAAKJ,GAAkBzC,EAAKR,IAAI4C,QAAS,aAOzF,IAAM,GAxBFpC,GAAON,KACPgD,EAAc,EAGdC,EAAS,GAAI1D,GAAOG,MACpB0D,MAAkBvC,EAAUuC,OAAS,SACrCC,IAAkBxC,EAAUwC,IAC5BC,IAAkBzC,EAAUyC,IAC5BC,MAAkB,WAAaT,EAAQjC,EAAUZ,QAAUK,EAAKR,IAAI4C,QAAS,aAe7Ec,EAAU/C,EAAEgD,KAAM5C,EAAU6C,OACtBzB,EAAI,EAAGA,EAAI0B,KAAKL,IAAKK,KAAKL,IAAKE,EAAS3C,EAAUwC,KAAO,GAAKxC,EAAU+C,SAAW,GAAK3B,IAC9Fa,EAAYU,EAAJvB,EAAcpB,EAAU6C,MAAOzB,GAAMpB,EAAUZ,OAI3DD,MAAKF,IAAIC,QAAQ8D,iBAAmBZ,EAAOa,aAG3C,IAAIC,GAAgB,GAAIvE,GAAcQ,KAAKF,KACvCkE,MAAUnD,EAAUuC,OAASvC,EAAUoD,KACvCC,KAAUrD,EAAUqD,KACpBxC,MAAUuB,GAEdjD,MAAK4C,QAASmB,EAAcxD,IAAKM,EAAUE,KAI/CM,YAAa,SAAUR,GACnB,GAAIsD,GAAU,GAAI7E,GAAQI,MACtB0D,MAAsBvC,EAAUuC,OAASvC,EAAUoD,KACnDG,IAAsB,qBACtBC,aAAsB,EACtBC,oBAAsB,EACtBC,WAAuB1D,EAAU2D,UAErCL,GAAQM,OAAQ,GAAI/E,GAAMM,KAAKF,KAAOG,OAAQY,EAAUZ,SAAWM,KACnE4D,EAAQM,OAAQrE,EAAG,UAAWyC,SAAU,gBAAiB6B,KAAM7D,EAAUqD,OACzElE,KAAKF,IAAI6E,GAAI,SAAU,SAAUC,GAAeT,EAAQ/D,EAAG,IAAMwE,GAAWC,OAAS,GAAOV,EAAQW,WACpG9E,KAAK4C,QAASuB,EAAQ5D,IAAKM,EAAUE,KAIzCO,QAAS,SAAUT,GACf,GAAIP,GAAON,KACPe,EAAKF,EAAUE,EACnBF,GAAUkE,SAAW,WAAazE,EAAKR,IAAI4C,QAAS,SAAU3B,GAC9D,IAAIW,GAAQ1B,KAAKE,WAAW4C,OAAQjC,EACpCb,MAAKF,IAAIkF,WAAYjE,GAAOW,CAC5B,IAAIqC,GAAgB,GAAIvE,GAAcQ,KAAKF,KACvCmE,KAAsBpD,EAAUoD,KAChCD,MAAsBnD,EAAUmD,OAASnD,EAAUoD,KACnDpC,MAAsBhB,EAAUgB,MAChCoD,WAAsBpE,EAAUoE,WAChCC,kBAAsBrE,EAAUqE,kBAChCC,oBAAsBtE,EAAUsE,oBAChCjB,KAAsBrD,EAAUqD,KAChCkB,SAAsBvE,EAAUuE,SAChC3D,SAAsBZ,EAAUY,SAChC4D,MAAsBxE,EAAUwE,MAChCC,MAAsBzE,EAAUyE,MAChCC,SAAsB1E,EAAU0E,SAChChD,OAAsB1B,EAAU0B,OAChCb,MAAsBA,GAI1B,OAFA1B,MAAKF,IAAI0F,aAAczE,GAAOgD,EAC9B/D,KAAK4C,QAASmB,EAAcxD,IAAKM,EAAUE,IACpCW,GAIXkB,QAAS,SAAUrC,EAAKQ,GACpBf,KAAKO,IAAIkE,OAAQlE,EAAIsC,SAAU,eAAgB4C,KAAM,KAAM1E,MAInE,QACIrB,KAAMA"}
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"form-view.js","sources":["../../../src/mvc/form/form-view.js"],"names":["define","Utils","Portlet","Ui","FormSection","FormData","Backbone","View","extend","initialize","options","this","merge","initial_errors","cls","icon","always_refresh","setElement","render","update","new_model","self","data","matchModel","node","input_id","input","input_list","_","isEqual","field","field_list","new_options","indexOf","type","i","opt","length","push","label","value","trigger","Galaxy","emit","debug","wait","active","is_dynamic","unwait","highlight","message","silent","input_element","element_list","error","portlet","expand","$panel","$el","parents","filter","$","css","first","animate","scrollTop","offset","top","errors","error_messages","matchResponse","off","Manager","_renderForm","create","current_check","checksum","on","refresh_on_change","new_check","onchange","each","reset","remove","Message","section","inputs","title","operations","buttons","collapsible","collapsed","append","empty","persistent","status"],"mappings":"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"}
{"version":3,"sources":["../../../src/mvc/form/form-view.js"],"names":["define","Utils","Portlet","Ui","FormSection","FormData","Backbone","View","extend","initialize","options","this","merge","initial_errors","cls","icon","always_refresh","setElement","render","update","new_model","self","data","matchModel","node","input_id","input","input_list","_","isEqual","field","field_list","new_options","indexOf","type","i","opt","length","push","label","value","trigger","Galaxy","emit","debug","wait","active","is_dynamic","unwait","highlight","message","silent","input_element","element_list","error","portlet","expand","$panel","$el","parents","filter","$","css","first","animate","scrollTop","offset","top","errors","error_messages","matchResponse","off","Manager","_renderForm","create","current_check","checksum","on","refresh_on_change","new_check","onchange","each","reset","remove","Message","section","inputs","title","operations","buttons","collapsible","collapsed","append","empty","persistent","status"],"mappings":"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","file":"form-view.js"}
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"ui-misc.js","sources":["../../../src/mvc/ui/ui-misc.js"],"names":["define","Utils","Select","Slider","Options","Drilldown","Buttons","Modal","Label","Backbone","View","extend","tagName","initialize","options","this","model","Model","setElement","$","listenTo","render","title","new_title","set","value","get","$el","removeClass","addClass","html","Message","message","status","cls","persistent","fade","update","timeout","window","clearTimeout","self","setTimeout","fadeOut","Input","type","placeholder","disabled","visible","area","color","style","events","input","new_val","undefined","attr","id","css","val","removeAttr","_onchange","Hidden","append","$info","$hidden","show","hide","Button","ButtonDefault","ButtonIcon","ButtonCheck","ButtonMenu","ButtonLink","RadioButton","Checkbox","Radio"],"mappings":"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"}
{"version":3,"file":"ui-misc.js","sources":["../../../src/mvc/ui/ui-misc.js"],"names":["define","Utils","Select","Slider","Options","Drilldown","Buttons","Modal","Label","Backbone","View","extend","tagName","initialize","options","this","model","Model","setElement","$","listenTo","render","title","new_title","set","value","get","$el","removeClass","addClass","html","Message","message","status","cls","persistent","fade","update","timeout","window","clearTimeout","self","setTimeout","fadeOut","Input","type","placeholder","disabled","readonly","visible","area","color","style","events","input","new_val","undefined","attr","id","css","val","_","each","attr_name","removeAttr","_onchange","Hidden","append","$info","$hidden","show","hide","Button","ButtonDefault","ButtonIcon","ButtonCheck","ButtonMenu","ButtonLink","RadioButton","Checkbox","Radio"],"mappings":"AAGAA,QAAQ,cACJ,2BACA,mBACA,oBACA,sBACA,oBACA,mBACA,SAAUC,EAAOC,EAAQC,EAAQC,EAASC,EAAWC,EAASC,GAG9D,GAAIC,GAAQC,SAASC,KAAKC,QACtBC,QAAS,QACTC,WAAY,SAAUC,GAClBC,KAAKC,MAAQF,GAAWA,EAAQE,OAAS,GAAIP,UAASQ,MAAOH,GAC7DC,KAAKH,QAAUE,EAAQF,SAAWG,KAAKH,QACvCG,KAAKG,WAAYC,EAAG,IAAMJ,KAAKH,QAAU,OACzCG,KAAKK,SAAUL,KAAKC,MAAO,SAAUD,KAAKM,OAAQN,MAClDA,KAAKM,UAETC,MAAO,SAAUC,GACbR,KAAKC,MAAMQ,IAAK,QAASD,IAE7BE,MAAO,WACH,MAAOV,MAAKC,MAAMU,IAAK,UAE3BL,OAAQ,WAKJ,MAJAN,MAAKY,IAAIC,cACAC,SAAU,YACVA,SAAUd,KAAKC,MAAMU,IAAK,QAC1BI,KAAMf,KAAKC,MAAMU,IAAK,UACxBX,QAKXgB,EAAUtB,SAASC,KAAKC,QACxBE,WAAY,SAAUC,GAClBC,KAAKC,MAAQF,GAAWA,EAAQE,OAAS,GAAIP,UAASQ,OAClDe,QAAc,KACdC,OAAc,OACdC,IAAc,GACdC,YAAc,EACdC,MAAc,IACfZ,IAAKV,GACRC,KAAKK,SAAUL,KAAKC,MAAO,SAAUD,KAAKM,OAAQN,MAClDA,KAAKM,UAETgB,OAAQ,SAAUvB,GACdC,KAAKC,MAAMQ,IAAKV,IAEpBO,OAAQ,WACJN,KAAKY,IAAIC,cAAcC,SAAU,cAAeA,SAAUd,KAAKC,MAAMU,IAAK,OAC1E,IAAIO,GAASlB,KAAKC,MAAMU,IAAK,SAQ7B,IAPKX,KAAKC,MAAMU,IAAK,SACjBX,KAAKY,IAAIE,UAAsB,WAAVI,GAAuB,QACb,UAAVA,GAAsB,SACtBA,GAAW,gBAEhClB,KAAKY,IAAIE,SAAU,SAAUA,SAAU,SAAWI,GAEjDlB,KAAKC,MAAMU,IAAK,YAIjB,GAHAX,KAAKY,IAAIG,KAAMf,KAAKC,MAAMU,IAAK,YAC/BX,KAAKY,IAAKZ,KAAKC,MAAMU,IAAK,QAAW,SAAW,UAChDX,KAAKuB,SAAWC,OAAOC,aAAczB,KAAKuB,UACpCvB,KAAKC,MAAMU,IAAK,cAAiB,CACnC,GAAIe,GAAO1B,IACXA,MAAKuB,QAAUC,OAAOG,WAAY,WAC9BD,EAAKzB,MAAMQ,IAAK,UAAW,KAC5B,UAGPT,MAAKY,IAAIgB,SAEb,OAAO5B,SAKX6B,EAAQnC,SAASC,KAAKC,QACtBE,WAAY,SAAUC,GAClBC,KAAKC,MAAQF,GAAWA,EAAQE,OAAS,GAAIP,UAASQ,OAClD4B,KAAkB,OAClBC,YAAkB,GAClBC,UAAkB,EAClBC,UAAkB,EAClBC,SAAkB,EAClBf,IAAkB,GAClBgB,MAAkB,EAClBC,MAAkB,KAClBC,MAAkB,OACnB5B,IAAKV,GACRC,KAAKH,QAAUG,KAAKC,MAAMU,IAAK,QAAW,WAAa,QACvDX,KAAKG,WAAYC,EAAG,IAAMJ,KAAKH,QAAU,OACzCG,KAAKK,SAAUL,KAAKC,MAAO,SAAUD,KAAKM,OAAQN,MAClDA,KAAKM,UAETgC,QACIC,MAAS,aAEb7B,MAAO,SAAU8B,GAEb,MADYC,UAAZD,GAAyBxC,KAAKC,MAAMQ,IAAK,QAA4B,gBAAZ+B,GAAuBA,EAAU,IACnFxC,KAAKC,MAAMU,IAAK,UAE3BL,OAAQ,WACJ,GAAIoB,GAAO1B,IAiBX,OAhBAA,MAAKY,IAAIC,cACAC,SAAU,MAAQd,KAAKH,SACvBiB,SAAUd,KAAKC,MAAMU,IAAK,QAC1BG,SAAUd,KAAKC,MAAMU,IAAK,UAC1B+B,KAAM,KAAM1C,KAAKC,MAAM0C,IACvBD,KAAM,OAAQ1C,KAAKC,MAAMU,IAAK,SAC9B+B,KAAM,cAAe1C,KAAKC,MAAMU,IAAK,gBACrCiC,IAAK,QAAS5C,KAAKC,MAAMU,IAAK,UAAa,IAC3CiC,IAAK,eAAgB5C,KAAKC,MAAMU,IAAK,UAAa,IACtDX,KAAKC,MAAMU,IAAK,WAAcX,KAAKY,IAAIiC,OACxC7C,KAAKY,IAAIiC,IAAK7C,KAAKC,MAAMU,IAAK,UAElCmC,EAAEC,MAAQ,WAAY,YAAc,SAAUC,GAC1CtB,EAAKzB,MAAMU,IAAKqC,GAActB,EAAKd,IAAI8B,KAAMM,GAAW,GAAStB,EAAKd,IAAIqC,WAAYD,KAE1FhD,KAAKY,IAAKZ,KAAKC,MAAMU,IAAK,WAAc,OAAS,UAC1CX,MAEXkD,UAAW,WACPlD,KAAKU,MAAOV,KAAKY,IAAIiC,OACrB7C,KAAKC,MAAMU,IAAK,aAAgBX,KAAKC,MAAMU,IAAK,YAAcX,KAAKC,MAAMU,IAAK,aAKlFwC,EAASzD,SAASC,KAAKC,QACvBE,WAAY,SAAUC,GAClBC,KAAKC,MAAQF,GAAWA,EAAQE,OAAS,GAAIP,UAASQ,MAAOH,GAC7DC,KAAKG,WAAYC,EAAI,UAAWgD,OAAQpD,KAAKqD,MAAQjD,EAAG,WACxBgD,OAAQpD,KAAKsD,QAAUlD,EAAG,YAC1DJ,KAAKK,SAAUL,KAAKC,MAAO,SAAUD,KAAKM,OAAQN,MAClDA,KAAKM,UAETI,MAAO,SAAU8B,GAEb,MADYC,UAAZD,GAAyBxC,KAAKC,MAAMQ,IAAK,QAAS+B,GAC3CxC,KAAKC,MAAMU,IAAK,UAE3BL,OAAQ,WAIJ,MAHAN,MAAKY,IAAI8B,KAAM,KAAM1C,KAAKC,MAAM0C,IAChC3C,KAAKsD,QAAQT,IAAK7C,KAAKC,MAAMU,IAAK,UAClCX,KAAKC,MAAMU,IAAK,QAAWX,KAAKqD,MAAME,OAAOxC,KAAMf,KAAKC,MAAMU,IAAK,SAAaX,KAAKqD,MAAMG,OACpFxD,OAIf,QACIyD,OAAclE,EAAQmE,cACtBC,WAAcpE,EAAQoE,WACtBC,YAAcrE,EAAQqE,YACtBC,WAActE,EAAQsE,WACtBC,WAAcvE,EAAQuE,WACtBjC,MAAcA,EACdpC,MAAcA,EACduB,QAAcA,EACdxB,MAAcA,EACduE,YAAc1E,EAAQ0E,YACtBC,SAAc3E,EAAQ2E,SACtBC,MAAc5E,EAAQ4E,MACtB9E,OAAcA,EACdgE,OAAcA,EACd/D,OAAcA,EACdE,UAAcA"}
@@ -0,0 +1 @@
{"version":3,"sources":["../../../src/mvc/user/user-preferences.js"],"names":["define","Form","Ui","View","Backbone","extend","initialize","this","defs","information","title","description","url","Galaxy","user","id","icon","password","submit_title","communication","permissions","api_key","submit_icon","toolbox_filters","openids","onclick","window","location","href","root","logout","modal","show","body","buttons","Cancel","hide","Sign out","message","Message","setElement","render","self","config","$","getJSON","data","$preferences","addClass","append","$el","_","escape","email","$table","use_remote_user","_link","enable_communication_server","has_user_tool_filters","enable_openid","_templateFooter","empty","page","$page_item","_templateRow","find","on","ajax","type","done","response","options","form","inputs","operations","submit","ButtonIcon","tooltip","submit_tooltip","_submit","back","remove","fail","update","status","JSON","stringify","create","contentType","updated_values","matchModel","input","input_id","field_list","value","responseJSON","err_msg","nice_total_disk_usage","enable_quotas","quota"],"mappings":"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","file":"user-preferences.js"}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1,2 +1,2 @@
define(["layout/masthead","layout/panel","mvc/ui/ui-modal","mvc/base-mvc"],function(a,b,c,d){var e=Backbone.View.extend(d.LoggableMixin).extend({_logNamespace:"layout",el:"body",className:"full-content",_panelIds:["left","center","right"],defaultOptions:{message_box_visible:!1,message_box_content:"",message_box_class:"info",show_inactivity_warning:!1,inactivity_box_content:""},initialize:function(b){this.log(this+".initialize:",b),_.extend(this,_.pick(b,this._panelIds)),this.options=_.defaults(_.omit(b.config,this._panelIds),this.defaultOptions),Galaxy.modal=this.modal=new c.View,this.masthead=new a.View(this.options),this.$el.attr("scroll","no"),this.$el.html(this._template()),this.$el.append(this.masthead.frame.$el),this.$("#masthead").replaceWith(this.masthead.$el),this.$el.append(this.modal.$el),this.$messagebox=this.$("#messagebox"),this.$inactivebox=this.$("#inactivebox")},render:function(){return $(".select2-hidden-accessible").remove(),this.log(this+".render:"),this.masthead.render(),this.renderMessageBox(),this.renderInactivityBox(),this.renderPanels(),this._checkCommunicationServerOnline(),this},renderMessageBox:function(){if(this.options.message_box_visible){var a=this.options.message_box_content||"",b=this.options.message_box_class||"info";this.$el.addClass("has-message-box"),this.$messagebox.attr("class","panel-"+b+"-message").html(a).toggle(!!a).show()}else this.$el.removeClass("has-message-box"),this.$messagebox.hide();return this},renderInactivityBox:function(){if(this.options.show_inactivity_warning){var a=this.options.inactivity_box_content||"",b=$("<a/>").attr("href",Galaxy.root+"user/resend_verification").text("Resend verification");this.$el.addClass("has-inactivity-box"),this.$inactivebox.html(a+" ").append(b).toggle(!!a).show()}else this.$el.removeClass("has-inactivity-box"),this.$inactivebox.hide();return this},renderPanels:function(){var a=this;return this._panelIds.forEach(function(b){_.has(a,b)&&(a[b].setElement("#"+b),a[b].render())}),this.left||this.center.$el.css("left",0),this.right||this.center.$el.css("right",0),this},_template:function(){return['<div id="everything">','<div id="background"/>','<div id="masthead"/>','<div id="messagebox"/>','<div id="inactivebox" class="panel-warning-message" />',this.left?'<div id="left" />':"",this.center?'<div id="center" class="inbound" />':"",this.right?'<div id="right" />':"","</div>",'<div id="dd-helper" />'].join("")},hideSidePanels:function(){this.left&&this.left.hide(),this.right&&this.right.hide()},toString:function(){return"PageLayoutView"},_checkCommunicationServerOnline:function(){var a=window.Galaxy.config.communication_server_host,b=window.Galaxy.config.communication_server_port,c=$("#show-chat-online");void 0!==window.Galaxy.user.attributes.preferences&&"1"===window.Galaxy.user.attributes.preferences.communication_server?$.ajax({url:a+":"+b}).success(function(){null!==window.Galaxy.user.id&&"hidden"===c.css("visibility")&&c.css("visibility","visible")}).error(function(){c.css("visibility","hidden")}):c.css("visibility","hidden")}});return{PageLayoutView:e}});
define(["layout/masthead","layout/panel","mvc/ui/ui-modal","mvc/base-mvc"],function(a,b,c,d){var e=Backbone.View.extend(d.LoggableMixin).extend({_logNamespace:"layout",el:"body",className:"full-content",_panelIds:["left","center","right"],defaultOptions:{message_box_visible:!1,message_box_content:"",message_box_class:"info",show_inactivity_warning:!1,inactivity_box_content:""},initialize:function(b){this.log(this+".initialize:",b),_.extend(this,_.pick(b,this._panelIds)),this.options=_.defaults(_.omit(b.config,this._panelIds),this.defaultOptions),Galaxy.modal=this.modal=new c.View,this.masthead=new a.View(this.options),this.$el.attr("scroll","no"),this.$el.html(this._template()),this.$el.append(this.masthead.frame.$el),this.$("#masthead").replaceWith(this.masthead.$el),this.$el.append(this.modal.$el),this.$messagebox=this.$("#messagebox"),this.$inactivebox=this.$("#inactivebox")},render:function(){return $(".select2-hidden-accessible").remove(),this.log(this+".render:"),this.masthead.render(),this.renderMessageBox(),this.renderInactivityBox(),this.renderPanels(),this._checkCommunicationServerOnline(),this},renderMessageBox:function(){if(this.options.message_box_visible){var a=this.options.message_box_content||"",b=this.options.message_box_class||"info";this.$el.addClass("has-message-box"),this.$messagebox.attr("class","panel-"+b+"-message").html(a).toggle(!!a).show()}else this.$el.removeClass("has-message-box"),this.$messagebox.hide();return this},renderInactivityBox:function(){if(this.options.show_inactivity_warning){var a=this.options.inactivity_box_content||"",b=$("<a/>").attr("href",Galaxy.root+"user/resend_verification").text("Resend verification");this.$el.addClass("has-inactivity-box"),this.$inactivebox.html(a+" ").append(b).toggle(!!a).show()}else this.$el.removeClass("has-inactivity-box"),this.$inactivebox.hide();return this},renderPanels:function(){var a=this;return this._panelIds.forEach(function(b){_.has(a,b)&&(a[b].setElement("#"+b),a[b].render())}),this.left||this.center.$el.css("left",0),this.right||this.center.$el.css("right",0),this},_template:function(){return['<div id="everything">','<div id="background"/>','<div id="masthead"/>','<div id="messagebox"/>','<div id="inactivebox" class="panel-warning-message" />',this.left?'<div id="left" />':"",this.center?'<div id="center" class="inbound" />':"",this.right?'<div id="right" />':"","</div>",'<div id="dd-helper" />'].join("")},hideSidePanels:function(){this.left&&this.left.hide(),this.right&&this.right.hide()},toString:function(){return"PageLayoutView"},_checkCommunicationServerOnline:function(){var a=window.Galaxy.config.communication_server_host,b=window.Galaxy.config.communication_server_port,c=window.Galaxy.user.attributes.preferences,d=$("#show-chat-online");c&&-1!=["1","true"].indexOf(c.communication_server)?$.ajax({url:a+":"+b}).success(function(){null!==window.Galaxy.user.id&&"hidden"===d.css("visibility")&&d.css("visibility","visible")}).error(function(){d.css("visibility","hidden")}):d.css("visibility","hidden")}});return{PageLayoutView:e}});
//# sourceMappingURL=../../maps/layout/page.js.map
+1 -1
View File
@@ -1,2 +1,2 @@
define(["utils/utils","mvc/ui/ui-misc","mvc/ui/ui-select-content","mvc/ui/ui-select-library","mvc/ui/ui-select-ftp","mvc/ui/ui-color-picker"],function(a,b,c,d,e,f){return Backbone.Model.extend({types:{text:"_fieldText",select:"_fieldSelect",data_column:"_fieldSelect",genomebuild:"_fieldSelect",data:"_fieldData",data_collection:"_fieldData",integer:"_fieldSlider","float":"_fieldSlider","boolean":"_fieldBoolean",drill_down:"_fieldDrilldown",color:"_fieldColor",hidden:"_fieldHidden",hidden_data:"_fieldHidden",baseurl:"_fieldHidden",library_data:"_fieldLibrary",ftpfile:"_fieldFtp"},create:function(a){var b=this.types[a.type],c="function"==typeof this[b]?this[b].call(this,a):null;return c||(c=a.options?this._fieldSelect(a):this._fieldText(a),Galaxy.emit.debug("form-parameters::_addRow()","Auto matched field type ("+a.type+").")),void 0===a.value&&(a.value=null),c.value(a.value),c},_fieldData:function(a){return new c.View({id:"field-"+a.id,extensions:a.extensions,optional:a.optional,multiple:a.multiple,type:a.type,flavor:a.flavor,data:a.options,onchange:a.onchange})},_fieldSelect:function(a){if(a.is_workflow)return this._fieldText(a);"data_column"==a.type&&(a.error_text="Missing columns in referenced dataset.");var c=a.data;c||(c=[],_.each(a.options,function(a){c.push({label:a[0],value:a[1]})}));var d=b.Select;switch(a.display){case"checkboxes":d=b.Checkbox;break;case"radio":d=b.Radio;break;case"radiobutton":d=b.RadioButton}return new d.View({id:"field-"+a.id,data:c,error_text:a.error_text||"No options available",multiple:a.multiple,optional:a.optional,onchange:a.onchange,searchable:"workflow"!==a.flavor})},_fieldDrilldown:function(a){return a.is_workflow?this._fieldText(a):new b.Drilldown.View({id:"field-"+a.id,data:a.options,display:a.display,optional:a.optional,onchange:a.onchange})},_fieldText:function(c){if(c.options&&c.data)if(c.area=c.multiple,a.isEmpty(c.value))c.value=null;else if($.isArray(c.value)){var d="";for(var e in c.value){if(d+=String(c.value[e]),!c.multiple)break;d+="\n"}c.value=d}return new b.Input({id:"field-"+c.id,area:c.area,placeholder:c.placeholder,onchange:c.onchange})},_fieldSlider:function(a){return new b.Slider.View({id:"field-"+a.id,precise:"float"==a.type,is_workflow:a.is_workflow,min:a.min,max:a.max,onchange:a.onchange})},_fieldHidden:function(a){return new b.Hidden({id:"field-"+a.id,info:a.info})},_fieldBoolean:function(a){return new b.RadioButton.View({id:"field-"+a.id,data:[{label:"Yes",value:"true"},{label:"No",value:"false"}],onchange:a.onchange})},_fieldColor:function(a){return new f({id:"field-"+a.id,onchange:a.onchange})},_fieldLibrary:function(a){return new d.View({id:"field-"+a.id,optional:a.optional,multiple:a.multiple,onchange:a.onchange})},_fieldFtp:function(a){return new e.View({id:"field-"+a.id,optional:a.optional,multiple:a.multiple,onchange:a.onchange})}})});
define(["utils/utils","mvc/ui/ui-misc","mvc/ui/ui-select-content","mvc/ui/ui-select-library","mvc/ui/ui-select-ftp","mvc/ui/ui-color-picker"],function(a,b,c,d,e,f){return Backbone.Model.extend({types:{text:"_fieldText",password:"_fieldText",select:"_fieldSelect",data_column:"_fieldSelect",genomebuild:"_fieldSelect",data:"_fieldData",data_collection:"_fieldData",integer:"_fieldSlider","float":"_fieldSlider","boolean":"_fieldBoolean",drill_down:"_fieldDrilldown",color:"_fieldColor",hidden:"_fieldHidden",hidden_data:"_fieldHidden",baseurl:"_fieldHidden",library_data:"_fieldLibrary",ftpfile:"_fieldFtp"},create:function(a){var b=this.types[a.type],c="function"==typeof this[b]?this[b].call(this,a):null;return c||(c=a.options?this._fieldSelect(a):this._fieldText(a),Galaxy.emit.debug("form-parameters::_addRow()","Auto matched field type ("+a.type+").")),void 0===a.value&&(a.value=null),c.value(a.value),c},_fieldData:function(a){return new c.View({id:"field-"+a.id,extensions:a.extensions,optional:a.optional,multiple:a.multiple,type:a.type,flavor:a.flavor,data:a.options,onchange:a.onchange})},_fieldSelect:function(a){if(a.is_workflow)return this._fieldText(a);"data_column"==a.type&&(a.error_text="Missing columns in referenced dataset.");var c=a.data;c||(c=[],_.each(a.options,function(a){c.push({label:a[0],value:a[1]})}));var d=b.Select;switch(a.display){case"checkboxes":d=b.Checkbox;break;case"radio":d=b.Radio;break;case"radiobutton":d=b.RadioButton}return new d.View({id:"field-"+a.id,data:c,error_text:a.error_text||"No options available",multiple:a.multiple,optional:a.optional,onchange:a.onchange,searchable:"workflow"!==a.flavor})},_fieldDrilldown:function(a){return a.is_workflow?this._fieldText(a):new b.Drilldown.View({id:"field-"+a.id,data:a.options,display:a.display,optional:a.optional,onchange:a.onchange})},_fieldText:function(c){if(c.options&&c.data)if(c.area=c.multiple,a.isEmpty(c.value))c.value=null;else if($.isArray(c.value)){var d="";for(var e in c.value){if(d+=String(c.value[e]),!c.multiple)break;d+="\n"}c.value=d}return new b.Input({id:"field-"+c.id,type:c.type,area:c.area,readonly:c.readonly,placeholder:c.placeholder,onchange:c.onchange})},_fieldSlider:function(a){return new b.Slider.View({id:"field-"+a.id,precise:"float"==a.type,is_workflow:a.is_workflow,min:a.min,max:a.max,onchange:a.onchange})},_fieldHidden:function(a){return new b.Hidden({id:"field-"+a.id,info:a.info})},_fieldBoolean:function(a){return new b.RadioButton.View({id:"field-"+a.id,data:[{label:"Yes",value:"true"},{label:"No",value:"false"}],onchange:a.onchange})},_fieldColor:function(a){return new f({id:"field-"+a.id,onchange:a.onchange})},_fieldLibrary:function(a){return new d.View({id:"field-"+a.id,optional:a.optional,multiple:a.multiple,onchange:a.onchange})},_fieldFtp:function(a){return new e.View({id:"field-"+a.id,optional:a.optional,multiple:a.multiple,onchange:a.onchange})}})});
//# sourceMappingURL=../../../maps/mvc/form/form-parameters.js.map
+1 -1
View File
@@ -1,2 +1,2 @@
define(["utils/utils","mvc/ui/ui-misc","mvc/ui/ui-portlet","mvc/form/form-repeat","mvc/form/form-input","mvc/form/form-parameters"],function(a,b,c,d,e,f){var g=Backbone.View.extend({initialize:function(a,b){this.app=a,this.inputs=b.inputs,this.parameters=new f,this.setElement($("<div/>")),this.render()},render:function(){var a=this;this.$el.empty(),_.each(this.inputs,function(b){a.add(b)})},add:function(b){var c=jQuery.extend(!0,{},b);switch(c.id=b.id=a.uid(),this.app.input_list[c.id]=c,c.type){case"conditional":this._addConditional(c);break;case"repeat":this._addRepeat(c);break;case"section":this._addSection(c);break;default:this._addRow(c)}},_addConditional:function(a){var b=this;a.test_param.id=a.id,this.app.options.sustain_conditionals&&(a.test_param.disabled=!0);var c=this._addRow(a.test_param);c.model&&c.model.set("onchange",function(c){var d=b.app.data.matchCase(a,c);for(var e in a.cases){var f=a.cases[e],g=b.$("#"+a.id+"-section-"+e),h=!1;for(var i in f.inputs)if(!f.inputs[i].hidden){h=!0;break}e==d&&h?g.fadeIn("fast"):g.hide()}b.app.trigger("change")});for(var d in a.cases){var e=new g(this.app,{inputs:a.cases[d].inputs});this._append(e.$el.addClass("ui-form-section"),a.id+"-section-"+d)}c.trigger("change")},_addRepeat:function(a){function b(b){var d=a.id+"-section-"+f++,e=new g(c.app,{inputs:b});h.add({id:d,$el:e.$el,ondel:function(){h.del(d),c.app.trigger("change")}})}for(var c=this,f=0,h=new d.View({title:a.title||"Repeat",min:a.min,max:a.max,onnew:function(){b(a.inputs),c.app.trigger("change")}}),i=_.size(a.cache),j=0;j<Math.max(Math.max(i,a.min),a.default||0);j++)b(i>j?a.cache[j]:a.inputs);this.app.options.sustain_repeats&&h.hideOptions();var k=new e(this.app,{label:a.title||a.name,help:a.help,field:h});this._append(k.$el,a.id)},_addSection:function(a){var b=new c.View({title:a.title||a.name,cls:"ui-portlet-section",collapsible:!0,collapsible_button:!0,collapsed:!a.expanded});b.append(new g(this.app,{inputs:a.inputs}).$el),b.append($("<div/>").addClass("ui-form-info").html(a.help)),this.app.on("expand",function(a){b.$("#"+a).length>0&&b.expand()}),this._append(b.$el,a.id)},_addRow:function(a){var b=this,c=a.id;a.onchange=function(){b.app.trigger("change",c)};var d=this.parameters.create(a);this.app.field_list[c]=d;var f=new e(this.app,{name:a.name,label:a.label||a.name,value:a.value,text_value:a.text_value,collapsible_value:a.collapsible_value,collapsible_preview:a.collapsible_preview,help:a.help,argument:a.argument,disabled:a.disabled,color:a.color,style:a.style,backdrop:a.backdrop,hidden:a.hidden,field:d});return this.app.element_list[c]=f,this._append(f.$el,a.id),d},_append:function(a,b){this.$el.append(a.addClass("section-row").attr("id",b))}});return{View:g}});
define(["utils/utils","mvc/ui/ui-misc","mvc/ui/ui-portlet","mvc/form/form-repeat","mvc/form/form-input","mvc/form/form-parameters"],function(a,b,c,d,e,f){var g=Backbone.View.extend({initialize:function(a,b){this.app=a,this.inputs=b.inputs,this.parameters=new f,this.setElement($("<div/>")),this.render()},render:function(){var a=this;this.$el.empty(),_.each(this.inputs,function(b){a.add(b)})},add:function(b){var c=jQuery.extend(!0,{},b);switch(c.id=b.id=a.uid(),this.app.input_list[c.id]=c,c.type){case"conditional":this._addConditional(c);break;case"repeat":this._addRepeat(c);break;case"section":this._addSection(c);break;default:this._addRow(c)}},_addConditional:function(a){var b=this;a.test_param.id=a.id,this.app.options.sustain_conditionals&&(a.test_param.disabled=!0);var c=this._addRow(a.test_param);c.model&&c.model.set("onchange",function(c){var d=b.app.data.matchCase(a,c);for(var e in a.cases){var f=a.cases[e],g=b.$("#"+a.id+"-section-"+e),h=!1;for(var i in f.inputs)if(!f.inputs[i].hidden){h=!0;break}e==d&&h?g.fadeIn("fast"):g.hide()}b.app.trigger("change")});for(var d in a.cases){var e=new g(this.app,{inputs:a.cases[d].inputs});this._append(e.$el.addClass("ui-form-section"),a.id+"-section-"+d)}c.trigger("change")},_addRepeat:function(a){function b(b){var d=a.id+"-section-"+f++,e=new g(c.app,{inputs:b});h.add({id:d,$el:e.$el,ondel:function(){h.del(d),c.app.trigger("change")}})}for(var c=this,f=0,h=new d.View({title:a.title||"Repeat",min:a.min,max:a.max,onnew:function(){b(a.inputs),c.app.trigger("change")}}),i=_.size(a.cache),j=0;j<Math.max(Math.max(i,a.min||0),a.default||0);j++)b(i>j?a.cache[j]:a.inputs);this.app.options.sustain_repeats&&h.hideOptions();var k=new e(this.app,{label:a.title||a.name,help:a.help,field:h});this._append(k.$el,a.id)},_addSection:function(a){var b=new c.View({title:a.title||a.name,cls:"ui-portlet-section",collapsible:!0,collapsible_button:!0,collapsed:!a.expanded});b.append(new g(this.app,{inputs:a.inputs}).$el),b.append($("<div/>").addClass("ui-form-info").html(a.help)),this.app.on("expand",function(a){b.$("#"+a).length>0&&b.expand()}),this._append(b.$el,a.id)},_addRow:function(a){var b=this,c=a.id;a.onchange=function(){b.app.trigger("change",c)};var d=this.parameters.create(a);this.app.field_list[c]=d;var f=new e(this.app,{name:a.name,label:a.label||a.name,value:a.value,text_value:a.text_value,collapsible_value:a.collapsible_value,collapsible_preview:a.collapsible_preview,help:a.help,argument:a.argument,disabled:a.disabled,color:a.color,style:a.style,backdrop:a.backdrop,hidden:a.hidden,field:d});return this.app.element_list[c]=f,this._append(f.$el,a.id),d},_append:function(a,b){this.$el.append(a.addClass("section-row").attr("id",b))}});return{View:g}});
//# sourceMappingURL=../../../maps/mvc/form/form-section.js.map
+1 -1
View File
@@ -1,2 +1,2 @@
define(["utils/utils","mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/form/form-section","mvc/form/form-data"],function(a,b,c,d,e){return Backbone.View.extend({initialize:function(b){this.options=a.merge(b,{initial_errors:!1,cls:"ui-portlet-limited",icon:null,always_refresh:!0}),this.setElement("<div/>"),this.render()},update:function(a){var b=this;this.data.matchModel(a,function(a,c){var d=b.input_list[c];if(d&&d.options&&!_.isEqual(d.options,a.options)){d.options=a.options;var e=b.field_list[c];if(e.update){var f=[];if(-1!=["data","data_collection","drill_down"].indexOf(d.type))f=d.options;else for(var g in a.options){var h=a.options[g];h.length>2&&f.push({label:h[0],value:h[1]})}e.update(f),e.trigger("change"),Galaxy.emit.debug("form-view::update()","Updating options for "+c)}}})},wait:function(a){for(var b in this.input_list){var c=this.field_list[b],d=this.input_list[b];d.is_dynamic&&c.wait&&c.unwait&&c[a?"wait":"unwait"]()}},highlight:function(a,b,c){var d=this.element_list[a];if(d&&(d.error(b||"Please verify this parameter."),this.portlet.expand(),this.trigger("expand",a),!c)){var e=this.$el.parents().filter(function(){return-1!=["auto","scroll"].indexOf($(this).css("overflow"))}).first();e.animate({scrollTop:e.scrollTop()+d.$el.offset().top-120},500)}},errors:function(a){if(this.trigger("reset"),a&&a.errors){var b=this.data.matchResponse(a.errors);for(var c in this.element_list){{this.element_list[c]}b[c]&&this.highlight(c,b[c],!0)}}},render:function(){var a=this;this.off("change"),this.off("reset"),this.field_list={},this.input_list={},this.element_list={},this.data=new e.Manager(this),this._renderForm(),this.data.create(),this.options.initial_errors&&this.errors(this.options);var b=this.data.checksum();return this.on("change",function(c){var d=a.input_list[c];if(!d||d.refresh_on_change||a.options.always_refresh){var e=a.data.checksum();e!=b&&(b=e,a.options.onchange&&a.options.onchange())}}),this.on("reset",function(){_.each(a.element_list,function(a){a.reset()})}),this},_renderForm:function(){$(".tooltip").remove(),this.message=new c.Message,this.section=new d.View(this,{inputs:this.options.inputs}),this.portlet=new b.View({icon:this.options.icon,title:this.options.title,cls:this.options.cls,operations:this.options.operations,buttons:this.options.buttons,collapsible:this.options.collapsible,collapsed:this.options.collapsed}),this.portlet.append(this.message.$el),this.portlet.append(this.section.$el),this.$el.empty(),this.options.inputs&&this.$el.append(this.portlet.$el),this.options.message&&this.message.update({persistent:!0,status:"warning",message:this.options.message}),Galaxy.emit.debug("form-view::initialize()","Completed")}})});
define(["utils/utils","mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/form/form-section","mvc/form/form-data"],function(a,b,c,d,e){return Backbone.View.extend({initialize:function(b){this.options=a.merge(b,{initial_errors:!1,cls:"ui-portlet-limited",icon:null,always_refresh:!0}),this.setElement("<div/>"),this.render()},update:function(a){var b=this;this.data.matchModel(a,function(a,c){var d=b.input_list[c];if(d&&d.options&&!_.isEqual(d.options,a.options)){d.options=a.options;var e=b.field_list[c];if(e.update){var f=[];if(["data","data_collection","drill_down"].indexOf(d.type)!=-1)f=d.options;else for(var g in a.options){var h=a.options[g];h.length>2&&f.push({label:h[0],value:h[1]})}e.update(f),e.trigger("change"),Galaxy.emit.debug("form-view::update()","Updating options for "+c)}}})},wait:function(a){for(var b in this.input_list){var c=this.field_list[b],d=this.input_list[b];d.is_dynamic&&c.wait&&c.unwait&&c[a?"wait":"unwait"]()}},highlight:function(a,b,c){var d=this.element_list[a];if(d&&(d.error(b||"Please verify this parameter."),this.portlet.expand(),this.trigger("expand",a),!c)){var e=this.$el.parents().filter(function(){return["auto","scroll"].indexOf($(this).css("overflow"))!=-1}).first();e.animate({scrollTop:e.scrollTop()+d.$el.offset().top-120},500)}},errors:function(a){if(this.trigger("reset"),a&&a.errors){var b=this.data.matchResponse(a.errors);for(var c in this.element_list){this.element_list[c];b[c]&&this.highlight(c,b[c],!0)}}},render:function(){var a=this;this.off("change"),this.off("reset"),this.field_list={},this.input_list={},this.element_list={},this.data=new e.Manager(this),this._renderForm(),this.data.create(),this.options.initial_errors&&this.errors(this.options);var b=this.data.checksum();return this.on("change",function(c){var d=a.input_list[c];if(!d||d.refresh_on_change||a.options.always_refresh){var e=a.data.checksum();e!=b&&(b=e,a.options.onchange&&a.options.onchange())}}),this.on("reset",function(){_.each(a.element_list,function(a){a.reset()})}),this},_renderForm:function(){$(".tooltip").remove(),this.message=new c.Message,this.section=new d.View(this,{inputs:this.options.inputs}),this.portlet=new b.View({icon:this.options.icon,title:this.options.title,cls:this.options.cls,operations:this.options.operations,buttons:this.options.buttons,collapsible:this.options.collapsible,collapsed:this.options.collapsed}),this.portlet.append(this.message.$el),this.portlet.append(this.section.$el),this.$el.empty(),this.options.inputs&&this.$el.append(this.portlet.$el),this.options.message&&this.message.update({persistent:!0,status:"warning",message:this.options.message}),Galaxy.emit.debug("form-view::initialize()","Completed")}})});
//# sourceMappingURL=../../../maps/mvc/form/form-view.js.map
+1 -1
View File
@@ -1,2 +1,2 @@
define(["utils/utils","mvc/ui/ui-select-default","mvc/ui/ui-slider","mvc/ui/ui-options","mvc/ui/ui-drilldown","mvc/ui/ui-buttons","mvc/ui/ui-modal"],function(a,b,c,d,e,f,g){var h=Backbone.View.extend({tagName:"label",initialize:function(a){this.model=a&&a.model||new Backbone.Model(a),this.tagName=a.tagName||this.tagName,this.setElement($("<"+this.tagName+"/>")),this.listenTo(this.model,"change",this.render,this),this.render()},title:function(a){this.model.set("title",a)},value:function(){return this.model.get("title")},render:function(){return this.$el.removeClass().addClass("ui-label").addClass(this.model.get("cls")).html(this.model.get("title")),this}}),i=Backbone.View.extend({initialize:function(a){this.model=a&&a.model||new Backbone.Model({message:null,status:"info",cls:"",persistent:!1,fade:!0}).set(a),this.listenTo(this.model,"change",this.render,this),this.render()},update:function(a){this.model.set(a)},render:function(){this.$el.removeClass().addClass("ui-message").addClass(this.model.get("cls"));var a=this.model.get("status");if(this.model.get("large")?this.$el.addClass(("success"==a&&"done"||"danger"==a&&"error"||a)+"messagelarge"):this.$el.addClass("alert").addClass("alert-"+a),this.model.get("message")){if(this.$el.html(this.model.get("message")),this.$el[this.model.get("fade")?"fadeIn":"show"](),this.timeout&&window.clearTimeout(this.timeout),!this.model.get("persistent")){var b=this;this.timeout=window.setTimeout(function(){b.model.set("message","")},3e3)}}else this.$el.fadeOut();return this}}),j=Backbone.View.extend({initialize:function(a){this.model=a&&a.model||new Backbone.Model({type:"text",placeholder:"",disabled:!1,visible:!0,cls:"",area:!1,color:null,style:null}).set(a),this.tagName=this.model.get("area")?"textarea":"input",this.setElement($("<"+this.tagName+"/>")),this.listenTo(this.model,"change",this.render,this),this.render()},events:{input:"_onchange"},value:function(a){return void 0!==a&&this.model.set("value","string"==typeof a?a:""),this.model.get("value")},render:function(){return this.$el.removeClass().addClass("ui-"+this.tagName).addClass(this.model.get("cls")).addClass(this.model.get("style")).attr("id",this.model.id).attr("type",this.model.get("type")).attr("placeholder",this.model.get("placeholder")).css("color",this.model.get("color")||"").css("border-color",this.model.get("color")||""),this.model.get("value")!==this.$el.val()&&this.$el.val(this.model.get("value")),this.model.get("disabled")?this.$el.attr("disabled",!0):this.$el.removeAttr("disabled"),this.$el[this.model.get("visible")?"show":"hide"](),this},_onchange:function(){this.value(this.$el.val()),this.model.get("onchange")&&this.model.get("onchange")(this.model.get("value"))}}),k=Backbone.View.extend({initialize:function(a){this.model=a&&a.model||new Backbone.Model(a),this.setElement($("<div/>").append(this.$info=$("<div/>")).append(this.$hidden=$("<div/>"))),this.listenTo(this.model,"change",this.render,this),this.render()},value:function(a){return void 0!==a&&this.model.set("value",a),this.model.get("value")},render:function(){return this.$el.attr("id",this.model.id),this.$hidden.val(this.model.get("value")),this.model.get("info")?this.$info.show().html(this.model.get("info")):this.$info.hide(),this}});return{Button:f.ButtonDefault,ButtonIcon:f.ButtonIcon,ButtonCheck:f.ButtonCheck,ButtonMenu:f.ButtonMenu,ButtonLink:f.ButtonLink,Input:j,Label:h,Message:i,Modal:g,RadioButton:d.RadioButton,Checkbox:d.Checkbox,Radio:d.Radio,Select:b,Hidden:k,Slider:c,Drilldown:e}});
define(["utils/utils","mvc/ui/ui-select-default","mvc/ui/ui-slider","mvc/ui/ui-options","mvc/ui/ui-drilldown","mvc/ui/ui-buttons","mvc/ui/ui-modal"],function(a,b,c,d,e,f,g){var h=Backbone.View.extend({tagName:"label",initialize:function(a){this.model=a&&a.model||new Backbone.Model(a),this.tagName=a.tagName||this.tagName,this.setElement($("<"+this.tagName+"/>")),this.listenTo(this.model,"change",this.render,this),this.render()},title:function(a){this.model.set("title",a)},value:function(){return this.model.get("title")},render:function(){return this.$el.removeClass().addClass("ui-label").addClass(this.model.get("cls")).html(this.model.get("title")),this}}),i=Backbone.View.extend({initialize:function(a){this.model=a&&a.model||new Backbone.Model({message:null,status:"info",cls:"",persistent:!1,fade:!0}).set(a),this.listenTo(this.model,"change",this.render,this),this.render()},update:function(a){this.model.set(a)},render:function(){this.$el.removeClass().addClass("ui-message").addClass(this.model.get("cls"));var a=this.model.get("status");if(this.model.get("large")?this.$el.addClass(("success"==a&&"done"||"danger"==a&&"error"||a)+"messagelarge"):this.$el.addClass("alert").addClass("alert-"+a),this.model.get("message")){if(this.$el.html(this.model.get("message")),this.$el[this.model.get("fade")?"fadeIn":"show"](),this.timeout&&window.clearTimeout(this.timeout),!this.model.get("persistent")){var b=this;this.timeout=window.setTimeout(function(){b.model.set("message","")},3e3)}}else this.$el.fadeOut();return this}}),j=Backbone.View.extend({initialize:function(a){this.model=a&&a.model||new Backbone.Model({type:"text",placeholder:"",disabled:!1,readonly:!1,visible:!0,cls:"",area:!1,color:null,style:null}).set(a),this.tagName=this.model.get("area")?"textarea":"input",this.setElement($("<"+this.tagName+"/>")),this.listenTo(this.model,"change",this.render,this),this.render()},events:{input:"_onchange"},value:function(a){return void 0!==a&&this.model.set("value","string"==typeof a?a:""),this.model.get("value")},render:function(){var a=this;return this.$el.removeClass().addClass("ui-"+this.tagName).addClass(this.model.get("cls")).addClass(this.model.get("style")).attr("id",this.model.id).attr("type",this.model.get("type")).attr("placeholder",this.model.get("placeholder")).css("color",this.model.get("color")||"").css("border-color",this.model.get("color")||""),this.model.get("value")!==this.$el.val()&&this.$el.val(this.model.get("value")),_.each(["readonly","disabled"],function(b){a.model.get(b)?a.$el.attr(b,!0):a.$el.removeAttr(b)}),this.$el[this.model.get("visible")?"show":"hide"](),this},_onchange:function(){this.value(this.$el.val()),this.model.get("onchange")&&this.model.get("onchange")(this.model.get("value"))}}),k=Backbone.View.extend({initialize:function(a){this.model=a&&a.model||new Backbone.Model(a),this.setElement($("<div/>").append(this.$info=$("<div/>")).append(this.$hidden=$("<div/>"))),this.listenTo(this.model,"change",this.render,this),this.render()},value:function(a){return void 0!==a&&this.model.set("value",a),this.model.get("value")},render:function(){return this.$el.attr("id",this.model.id),this.$hidden.val(this.model.get("value")),this.model.get("info")?this.$info.show().html(this.model.get("info")):this.$info.hide(),this}});return{Button:f.ButtonDefault,ButtonIcon:f.ButtonIcon,ButtonCheck:f.ButtonCheck,ButtonMenu:f.ButtonMenu,ButtonLink:f.ButtonLink,Input:j,Label:h,Message:i,Modal:g,RadioButton:d.RadioButton,Checkbox:d.Checkbox,Radio:d.Radio,Select:b,Hidden:k,Slider:c,Drilldown:e}});
//# sourceMappingURL=../../../maps/mvc/ui/ui-misc.js.map
@@ -0,0 +1,2 @@
define(["mvc/form/form-view","mvc/ui/ui-misc"],function(a,b){var c=Backbone.View.extend({initialize:function(){this.defs={information:{title:"Manage information",description:"Edit your email, addresses and custom parameters or change your username.",url:"api/users/"+Galaxy.user.id+"/information/inputs",icon:"fa-user"},password:{title:"Change password",description:"Allows you to change your login credentials.",icon:"fa-unlock-alt",url:"api/users/"+Galaxy.user.id+"/password/inputs",submit_title:"Save password"},communication:{title:"Change communication settings",description:"Enable or disable the communication feature to chat with other users.",url:"api/users/"+Galaxy.user.id+"/communication/inputs",icon:"fa-comments-o"},permissions:{title:"Set dataset permissions for new histories",description:"Grant others default access to newly created histories. Changes made here will only affect histories created after these settings have been stored.",url:"api/users/"+Galaxy.user.id+"/permissions/inputs",icon:"fa-users",submit_title:"Save permissions"},api_key:{title:"Manage API key",description:"Access your current API key or create a new one.",url:"api/users/"+Galaxy.user.id+"/api_key/inputs",icon:"fa-key",submit_title:"Create a new key",submit_icon:"fa-check"},toolbox_filters:{title:"Manage Toolbox filters",description:"Customize your Toolbox by displaying or omitting sets of Tools.",url:"api/users/"+Galaxy.user.id+"/toolbox_filters/inputs",icon:"fa-filter",submit_title:"Save filters"},openids:{title:"Manage OpenIDs",description:"Associate OpenIDs with your account.",icon:"fa-openid",onclick:function(){window.location.href=Galaxy.root+"user/openid_manage?cntrller=user&use_panels=True"}},logout:{title:"Sign out",description:"Click here to sign out of all sessions.",icon:"fa-sign-out",onclick:function(){Galaxy.modal.show({title:"Sign out",body:"Do you want to continue and sign out of all active sessions?",buttons:{Cancel:function(){Galaxy.modal.hide()},"Sign out":function(){window.location.href=Galaxy.root+"user/logout"}}})}}},this.message=new b.Message,this.setElement("<div/>"),this.render()},render:function(){var a=this,b=Galaxy.config;$.getJSON(Galaxy.root+"api/users/"+Galaxy.user.id,function(c){a.$preferences=$("<div/>").addClass("ui-panel").append(a.message.$el).append($("<h2/>").append("User preferences")).append($("<p/>").append("You are logged in as <strong>"+_.escape(c.email)+"</strong>.")).append(a.$table=$("<table/>").addClass("ui-panel-table")),b.use_remote_user||(a._link(a.defs.information),a._link(a.defs.password)),b.enable_communication_server&&a._link(a.defs.communication),a._link(a.defs.permissions),a._link(a.defs.api_key),b.has_user_tool_filters&&a._link(a.defs.toolbox_filters),b.enable_openid&&!b.use_remote_user&&a._link(a.defs.openids),a._link(a.defs.logout),a.$preferences.append(a._templateFooter(c)),a.$el.empty().append(a.$preferences)})},_link:function(c){var d=this,e=$(this._templateRow(c));this.$table.append(e),e.find("a").on("click",function(){c.url?$.ajax({url:Galaxy.root+c.url,type:"GET"}).done(function(e){var f=$.extend({},c,e),g=new a({title:f.title,icon:f.icon,inputs:f.inputs,operations:{submit:new b.ButtonIcon({tooltip:f.submit_tooltip,title:f.submit_title||"Save settings",icon:f.submit_icon||"fa-save",onclick:function(){d._submit(g,f)}}),back:new b.ButtonIcon({icon:"fa-caret-left",tooltip:"Return to user preferences",title:"Preferences",onclick:function(){g.remove(),d.$preferences.show()}})}});d.$preferences.hide(),d.$el.append(g.$el)}).fail(function(a){d.message.update({message:"Failed to load resource "+c.url+".",status:"danger"})}):c.onclick()})},_submit:function(a,b){var c=this;$.ajax({url:b.url,data:JSON.stringify(a.data.create()),type:"PUT",contentType:"application/json"}).done(function(b){var d=!1;a.data.matchModel(b,function(b,c){a.field_list[c].value(b.value),d=!0}),d?a.message.update({message:b.message,status:"success"}):(a.remove(),c.$preferences.show(),c.message.update({message:b.message,status:"success"}))}).fail(function(b){a.message.update({message:b.responseJSON.err_msg,status:"danger"})})},_templateRow:function(a){return'<tr><td><div class="ui-panel-icon fa '+a.icon+'"></td><td><a class="ui-panel-anchor" href="javascript:void(0)">'+a.title+'</a><div class="ui-form-info">'+a.description+"</div></td></tr>"},_templateFooter:function(a){return'<p class="ui-panel-footer">You are using <strong>'+a.nice_total_disk_usage+"</strong> of disk space in this Galaxy instance. "+(Galaxy.config.enable_quotas?"Your disk quota is: <strong>"+a.quota+"</strong>. ":"")+'Is your usage more than expected? See the <a href="https://wiki.galaxyproject.org/Learn/ManagingDatasets" target="_blank">documentation</a> for tips on how to find all of the data in your account.</p>'}});return{View:c}});
//# sourceMappingURL=../../../maps/mvc/user/user-preferences.js.map
File diff suppressed because one or more lines are too long
@@ -1,19 +0,0 @@
<%inherit file="/base.mako"/>
<%namespace file="/message.mako" import="render_msg" />
%if message:
${render_msg( message, status )}
%endif
<div class="toolForm">
<form name="change_communication" id="change_communication" action="${h.url_for( controller='user', action='change_communication', cntrller=cntrller )}" method="post" >
<div class="toolFormTitle">Change your communication settings</div>
<div class="form-row">
<label>Activate real-time communication with other Galaxy users.</label>
<input type="checkbox" name="enable_communication_server" ${activated} />
</div>
<div class="form-row">
<input type="submit" name="change_communication_button" value="Save"/>
</div>
</form>
</div>
-96
View File
@@ -1,96 +0,0 @@
<%inherit file="/base.mako"/>
<%namespace file="/message.mako" import="render_msg" />
%if message:
${render_msg( message, status )}
%endif
</br>
</br>
<h3>Edit address</h3>
<ul class="manage-table-actions">
<li>
<a class="action-button" href="${h.url_for( controller='user', action='manage_user_info', cntrller=cntrller, id=trans.security.encode_id( user.id) )}">Manage user information</a>
</li>
</ul>
<div class="toolForm">
<div class="toolFormTitle">Edit address</div>
<div class="toolFormBody">
<form name="login_info" id="login_info" action="${h.url_for( controller='user', action='edit_address', cntrller=cntrller, address_id=trans.security.encode_id( address_obj.id ), id=trans.security.encode_id( user.id ) )}" method="post" >
<div class="form-row">
<label>Short Description:</label>
<div style="float: left; width: 250px; margin-right: 10px;">
<input type="text" name="short_desc" value="${address_obj.desc | h}" size="40">
</div>
<div class="toolParamHelp" style="clear: both;">Required</div>
<div style="clear: both"></div>
</div>
<div class="form-row">
<label>Name:</label>
<div style="float: left; width: 250px; margin-right: 10px;">
<input type="text" name="name" value="${address_obj.name | h}" size="40">
</div>
<div class="toolParamHelp" style="clear: both;">Required</div>
<div style="clear: both"></div>
</div>
<div class="form-row">
<label>Institution:</label>
<div style="float: left; width: 250px; margin-right: 10px;">
<input type="text" name="institution" value="${address_obj.institution | h}" size="40">
</div>
<div class="toolParamHelp" style="clear: both;">Required</div>
<div style="clear: both"></div>
</div>
<div class="form-row">
<label>Address:</label>
<div style="float: left; width: 250px; margin-right: 10px;">
<input type="text" name="address" value="${address_obj.address | h}" size="40">
</div>
<div class="toolParamHelp" style="clear: both;">Required</div>
<div style="clear: both"></div>
</div>
<div class="form-row">
<label>City:</label>
<div style="float: left; width: 250px; margin-right: 10px;">
<input type="text" name="city" value="${address_obj.city | h}" size="40">
</div>
<div class="toolParamHelp" style="clear: both;">Required</div>
<div style="clear: both"></div>
</div>
<div class="form-row">
<label>State/Province/Region:</label>
<div style="float: left; width: 250px; margin-right: 10px;">
<input type="text" name="state" value="${address_obj.state | h}" size="40">
</div>
<div class="toolParamHelp" style="clear: both;">Required</div>
<div style="clear: both"></div>
</div>
<div class="form-row">
<label>Postal Code:</label>
<div style="float: left; width: 250px; margin-right: 10px;">
<input type="text" name="postal_code" value="${address_obj.postal_code | h}" size="40">
</div>
<div class="toolParamHelp" style="clear: both;">Required</div>
<div style="clear: both"></div>
</div>
<div class="form-row">
<label>Country:</label>
<div style="float: left; width: 250px; margin-right: 10px;">
<input type="text" name="country" value="${address_obj.country | h}" size="40">
</div>
<div class="toolParamHelp" style="clear: both;">Required</div>
<div style="clear: both"></div>
</div>
<div class="form-row">
<label>Phone:</label>
<div style="float: left; width: 250px; margin-right: 10px;">
<input type="text" name="phone" value="${address_obj.phone | h}" size="40">
</div>
<div style="clear: both"></div>
</div>
<div class="form-row">
<input type="submit" name="edit_address_button" value="Save changes">
</div>
</form>
</div>
</div>
-97
View File
@@ -1,97 +0,0 @@
<%inherit file="/base.mako"/>
<%namespace file="/message.mako" import="render_msg" />
%if message:
${render_msg( message, status )}
%endif
</br>
</br>
<h3>Add new address</h3>
<ul class="manage-table-actions">
<li>
<a class="action-button" href="${h.url_for( controller='user', action='manage_user_info', cntrller=cntrller, id=trans.security.encode_id( user.id) )}">
<span>Manage User Information</span></a>
</li>
</ul>
<div class="toolForm">
<div class="toolFormTitle">Add new address</div>
<div class="toolFormBody">
<form name="login_info" id="login_info" action="${h.url_for( controller='user', action='new_address', cntrller=cntrller, id=trans.security.encode_id( user.id ) )}" method="post" >
<div class="form-row">
<label>Short Description:</label>
<div style="float: left; width: 250px; margin-right: 10px;">
<input type="text" name="short_desc" value="${short_desc | h}" size="40">
</div>
<div class="toolParamHelp" style="clear: both;">Required</div>
<div style="clear: both"></div>
</div>
<div class="form-row">
<label>Name:</label>
<div style="float: left; width: 250px; margin-right: 10px;">
<input type="text" name="name" value="${name | h}" size="40">
</div>
<div class="toolParamHelp" style="clear: both;">Required</div>
<div style="clear: both"></div>
</div>
<div class="form-row">
<label>Institution:</label>
<div style="float: left; width: 250px; margin-right: 10px;">
<input type="text" name="institution" value="${institution | h}" size="40">
</div>
<div class="toolParamHelp" style="clear: both;">Required</div>
<div style="clear: both"></div>
</div>
<div class="form-row">
<label>Address:</label>
<div style="float: left; width: 250px; margin-right: 10px;">
<input type="text" name="address" value="${address | h}" size="40">
</div>
<div class="toolParamHelp" style="clear: both;">Required</div>
<div style="clear: both"></div>
</div>
<div class="form-row">
<label>City:</label>
<div style="float: left; width: 250px; margin-right: 10px;">
<input type="text" name="city" value="${city | h}" size="40">
</div>
<div class="toolParamHelp" style="clear: both;">Required</div>
<div style="clear: both"></div>
</div>
<div class="form-row">
<label>State/Province/Region:</label>
<div style="float: left; width: 250px; margin-right: 10px;">
<input type="text" name="state" value="${state | h}" size="40">
</div>
<div class="toolParamHelp" style="clear: both;">Required</div>
<div style="clear: both"></div>
</div>
<div class="form-row">
<label>Postal Code:</label>
<div style="float: left; width: 250px; margin-right: 10px;">
<input type="text" name="postal_code" value="${postal_code | h}" size="40">
</div>
<div class="toolParamHelp" style="clear: both;">Required</div>
<div style="clear: both"></div>
</div>
<div class="form-row">
<label>Country:</label>
<div style="float: left; width: 250px; margin-right: 10px;">
<input type="text" name="country" value="${country | h}" size="40">
</div>
<div class="toolParamHelp" style="clear: both;">Required</div>
<div style="clear: both"></div>
</div>
<div class="form-row">
<label>Phone:</label>
<div style="float: left; width: 250px; margin-right: 10px;">
<input type="text" name="phone" value="${phone | h}" size="40">
</div>
<div style="clear: both"></div>
</div>
<div class="form-row">
<input type="submit" name="new_address_button" value="Save">
</div>
</form>
</div>
</div>
-19
View File
@@ -1,19 +0,0 @@
<%inherit file="/base.mako"/>
<%namespace file="/message.mako" import="render_msg" />
<%namespace file="/dataset/security_common.mako" import="render_permission_form" />
<%def name="title()">Change Default Permissions on New Histories</%def>
%if message:
${render_msg( message, status )}
%endif
<br/><br/>
<ul class="manage-table-actions">
<li>
<a class="action-button" href="${h.url_for( controller='user', cntrller=cntrller, action='index')}">User preferences</a>
</li>
</ul>
%if trans.user:
${render_permission_form( trans.user, trans.user.email, h.url_for( controller='user', action='set_default_permissions', cntrller=cntrller ), trans.user.all_roles() )}
%endif
-21
View File
@@ -176,27 +176,6 @@ def inherit(context):
all Galaxy project mailing lists</a>.</p>
</div>
%endif
%if user_type_fd_id_select_field and len( user_type_fd_id_select_field.options ) >= 1:
<div class="form-row">
<label>User type</label>
${user_type_fd_id_select_field.get_html()}
</div>
%endif
%if user_type_form_definition:
%for field in widgets:
<div class="form-row">
<label>${field['label']}</label>
${field['widget'].get_html()}
<div class="toolParamHelp" style="clear: both;">
${field['helptext']}
</div>
<div style="clear: both"></div>
</div>
%endfor
%if not user_type_fd_id_select_field:
<input type="hidden" name="user_type_fd_id" value="${trans.security.encode_id( user_type_form_definition.id )}"/>
%endif
%endif
<div id="for_bears">
If you see this, please leave following field blank.
<input type="text" name="bear_field" size="1" value=""/>
-91
View File
@@ -1,91 +0,0 @@
<%inherit file="/base.mako"/>
<%namespace file="/message.mako" import="render_msg" />
%if message:
${render_msg( message, status )}
%endif
</br>
</br>
<ul class="manage-table-actions">
<li>
<a class="action-button" href="${h.url_for( controller='user', action='index', cntrller=cntrller )}">User preferences</a>
</li>
</ul>
%if tool_filters or section_filters or label_filters:
<div class="toolForm">
<form name="toolbox_filter" id="toolbox_filter" action="${h.url_for( controller='user', action='edit_toolbox_filters', cntrller=cntrller )}" method="post" >
% if tool_filters:
<div class="toolFormTitle">Edit ToolBox filters :: Tools</div>
<div class="toolFormBody">
% for filter in tool_filters:
<div class="form-row">
<div style="float: left; width: 40px; margin-right: 10px;">
% if filter['checked']:
<input type="checkbox" name="t_${filter['filterpath']}" checked="checked">
% else:
<input type="checkbox" name="t_${filter['filterpath']}">
% endif
</div>
<div style="float: left; margin-right: 10px;">
${filter['short_desc']}
<div class="toolParamHelp" style="clear: both;">${filter['desc']}</div>
</div>
<div style="clear: both"></div>
</div>
% endfor
</div>
% endif
% if section_filters:
<div class="toolFormTitle">Edit ToolBox filters :: Sections</div>
<div class="toolFormBody">
% for filter in section_filters:
<div class="form-row">
<div style="float: left; width: 40px; margin-right: 10px;">
% if filter['checked']:
<input type="checkbox" name="s_${filter['filterpath']}" checked="checked">
% else:
<input type="checkbox" name="s_${filter['filterpath']}">
% endif
</div>
<div style="float: left; margin-right: 10px;">
${filter['short_desc']}
<div class="toolParamHelp" style="clear: both;">${filter['desc']}</div>
</div>
<div style="clear: both"></div>
</div>
% endfor
</div>
% endif
% if label_filters:
<div class="toolFormTitle">Edit ToolBox filters :: Labels</div>
<div class="toolFormBody">
% for filter in label_filters:
<div class="form-row">
<div style="float: left; width: 40px; margin-right: 10px;">
% if filter['checked']:
<input type="checkbox" name="l_${filter['filterpath']}" checked="checked">
% else:
<input type="checkbox" name="l_${filter['filterpath']}">
% endif
</div>
<div style="float: left; margin-right: 10px;">
${filter['short_desc']}
<div class="toolParamHelp" style="clear: both;">${filter['desc']}</div>
</div>
<div style="clear: both"></div>
</div>
% endfor
</div>
% endif
<div class="form-row">
<input type="submit" name="edit_toolbox_filter_button" value="Save changes">
</div>
</form>
</div>
%else:
${render_msg( 'No filters available. Contact your system administrator or check your configuration file.', 'info' )}
%endif
@@ -1,95 +0,0 @@
<%inherit file="/base.mako"/>
<%namespace file="/user/info.mako" import="render_user_info" />
<%namespace file="/message.mako" import="render_msg" />
%if message:
${render_msg( message, status )}
%endif
${render_user_info()}
%if user.values or user_info_forms:
<p></p>
<div class="toolForm">
<form name="user_info" id="user_info" action="${h.url_for( controller='user', action='edit_info', cntrller=cntrller, user_id=trans.security.encode_id( user.id ) )}" method="post" >
<div class="toolFormTitle">User information</div>
%if user_type_fd_id_select_field and len( user_type_fd_id_select_field.options ) >= 1:
<div class="form-row">
<label>User type:</label>
${user_type_fd_id_select_field.get_html()}
</div>
%else:
<input type="hidden" name="user_type_fd_id" value="${trans.security.encode_id( user_type_fd_id )}"/>
%endif
%for field in widgets:
<div class="form-row">
<label>${field['label']}:</label>
${field['widget'].get_html()}
<div class="toolParamHelp" style="clear: both;">
${field['helptext']}
</div>
<div style="clear: both"></div>
</div>
%endfor
<div class="form-row">
<input type="submit" name="edit_user_info_button" value="Save"/>
</div>
</form>
</div>
<p></p>
%endif
<p/>
<div class="toolForm">
<form name="user_addresses" id="user_addresses" action="${h.url_for( controller='user', action='new_address', cntrller=cntrller, id=trans.security.encode_id( user.id ) )}" method="post" >
<div class="toolFormTitle">User Addresses</div>
<div class="toolFormBody">
%if user.addresses:
<div class="form-row">
<div class="grid-header">
%for i, filter in enumerate( ['Active', 'Deleted', 'All'] ):
%if i > 0:
<span>|</span>
%endif
%if show_filter == filter:
<span class="filter"><a href="${h.url_for( controller='user', action='manage_user_info', cntrller=cntrller, show_filter=filter, id=trans.security.encode_id( user.id ) )}"><b>${filter}</b></a></span>
%else:
<span class="filter"><a href="${h.url_for( controller='user', action='manage_user_info', cntrller=cntrller, show_filter=filter, id=trans.security.encode_id( user.id ) )}">${filter}</a></span>
%endif
%endfor
</div>
</div>
<table class="grid">
<tbody>
%for index, address in enumerate(addresses):
<tr class="libraryRow libraryOrFolderRow" id="libraryRow">
<td>
<div class="form-row">
<label>${address.desc | h}:</label>
${address.get_html()}
</div>
<div class="form-row">
<ul class="manage-table-actions">
<li>
%if not address.deleted:
<a class="action-button" href="${h.url_for( controller='user', action='edit_address', cntrller=cntrller, address_id=trans.security.encode_id( address.id ), id=trans.security.encode_id( user.id ) )}">Edit</a>
<a class="action-button" href="${h.url_for( controller='user', action='delete_address', cntrller=cntrller, address_id=trans.security.encode_id( address.id ), id=trans.security.encode_id( user.id ) )}">Delete</a>
%else:
<a class="action-button" href="${h.url_for( controller='user', action='undelete_address', cntrller=cntrller, address_id=trans.security.encode_id( address.id ), id=trans.security.encode_id( user.id ) )}">Undelete</a>
%endif
</li>
</ul>
</div>
</td>
</tr>
%endfor
</tbody>
</table>
%endif
<div class="form-row">
<input type="submit" value="Add a new address">
</div>
</div>
</form>
</div>
@@ -0,0 +1,21 @@
<%inherit file="/base.mako"/>
%if trans.user:
<h2>${_('User preferences')}</h2>
<p>You are currently logged in as ${trans.user.email|h}.</p>
<ul>
<li><a href="${h.url_for( controller='user', action='manage_user_info', cntrller=cntrller )}">${_('Manage your information')}</a></li>
<li><a href="${h.url_for( controller='user', action='change_password' )}">${_('Change your password')}</a></li>
<li><a href="${h.url_for( controller='user', action='api_keys', cntrller=cntrller )}">${_('Manage your API keys')}</a></li>
<li><a href="${h.url_for( controller='repository', action='manage_email_alerts', cntrller=cntrller )}">${_('Manage your email alerts')}</a></li>
<li><a href="${h.url_for( controller='user', action='logout', logout_all=True )}" target="_top">${_('Logout')}</a> ${_('of all user sessions')}</li>
</ul>
%else:
%if not message:
<p>${n_('You are currently not logged in.')}</p>
%endif
<ul>
<li><a href="${h.url_for( controller='user', action='login' )}">${_('Login')}</li>
<li><a href="${h.url_for( controller='user', action='create', cntrller='user' )}">${_('Register')}</a></li>
</ul>
%endif
+33 -2
View File
@@ -1,6 +1,6 @@
import json
from requests import put
from requests import put, get
from base import api
@@ -63,13 +63,44 @@ class UsersApiTestCase( api.ApiTestCase ):
def test_admin_update( self ):
new_name = 'flexo'
user = self._setup_user( TEST_USER_EMAIL )
update_url = self._api_url( "users/%s" % ( user[ "id" ] ), params=dict( key=self.master_api_key ) )
update_response = put( update_url, data=json.dumps( dict( username=new_name ) ) )
self._assert_status_code_is( update_response, 200 )
update_json = update_response.json()
self.assertEqual( update_json[ 'username' ], new_name )
def test_information( self ):
user = self._setup_user( TEST_USER_EMAIL )
url = self.__url( "information/inputs", user )
response = get( url ).json()
self.assertEqual( response[ "username" ], user[ "username" ] )
self.assertEqual( response[ "email" ], TEST_USER_EMAIL )
put( url, data=json.dumps( dict( username="newname", email="new@email.email" ) ) )
response = get( url ).json()
self.assertEqual( response[ "username" ], "newname" )
self.assertEqual( response[ "email" ], "new@email.email" )
put( url, data=json.dumps( dict( username=user[ "username" ], email=TEST_USER_EMAIL ) ) )
response = get( url ).json()
self.assertEqual( response[ "username" ], user[ "username" ] )
self.assertEqual( response[ "email" ], TEST_USER_EMAIL )
put( url, data=json.dumps( { "address_0|desc" : "_desc" } ) )
response = get( url ).json()
self.assertEqual( len( response[ "addresses" ] ), 1 )
self.assertEqual( response[ "addresses" ][ 0 ][ "desc" ], "_desc" )
def test_communication( self ):
user = self._setup_user( TEST_USER_EMAIL )
url = self.__url( "communication/inputs", user )
self.assertEqual( self.__filter( get( url ).json(), "enable", "value" ), "false" )
put( url, data=json.dumps( dict( enable="true" ) ) )
self.assertEqual( self.__filter( get( url ).json(), "enable", "value" ), "true" )
def __filter( self, response, name, attr ):
return [ r[ attr ] for r in response[ "inputs" ] if r[ "name" ] == name ][ 0 ]
def __url( self, action, user ):
return self._api_url( "users/%s/%s" % ( user[ "id" ], action ), params=dict( key=self.master_api_key ) )
def __show( self, user ):
return self._get( "users/%s" % ( user[ 'id' ] ) )