commit/galaxy-central: 2 new changesets
2 new commits in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/changeset/2ca0e99d6d6d/ changeset: 2ca0e99d6d6d user: james_taylor date: 2012-09-28 23:31:30 summary: Pull base Admin controller out into its own module, begin removing as much gratuitous passing around of the webapp parameter as possible affected #: 20 files diff -r 203e3e1592439dcb8c0eb890545ed38a66f08f2c -r 2ca0e99d6d6d940af0712e9c56b9f238fd59635c lib/galaxy/web/base/controller.py --- a/lib/galaxy/web/base/controller.py +++ b/lib/galaxy/web/base/controller.py @@ -1525,1191 +1525,8 @@ class ControllerUnavailable( Exception ): pass -class Admin( object ): - # Override these - user_list_grid = None - role_list_grid = None - group_list_grid = None - quota_list_grid = None - repository_list_grid = None - tool_version_list_grid = None - delete_operation = None - undelete_operation = None - purge_operation = None - - @web.expose - @web.require_admin - def index( self, trans, **kwd ): - webapp = get_webapp( trans, **kwd ) - message = kwd.get( 'message', '' ) - status = kwd.get( 'status', 'done' ) - if webapp == 'galaxy': - installed_repositories = trans.sa_session.query( trans.model.ToolShedRepository ).first() - installing_repository_ids = get_ids_of_tool_shed_repositories_being_installed( trans, as_string=True ) - return trans.fill_template( '/webapps/galaxy/admin/index.mako', - webapp=webapp, - installed_repositories=installed_repositories, - installing_repository_ids=installing_repository_ids, - message=message, - status=status ) - else: - return trans.fill_template( '/webapps/community/admin/index.mako', - webapp=webapp, - message=message, - status=status ) - @web.expose - @web.require_admin - def center( self, trans, **kwd ): - webapp = get_webapp( trans, **kwd ) - message = kwd.get( 'message', '' ) - status = kwd.get( 'status', 'done' ) - if webapp == 'galaxy': - return trans.fill_template( '/webapps/galaxy/admin/center.mako', - message=message, - status=status ) - else: - return trans.fill_template( '/webapps/community/admin/center.mako', - message=message, - status=status ) - @web.expose - @web.require_admin - def reload_tool( self, trans, **kwd ): - params = util.Params( kwd ) - message = util.restore_text( params.get( 'message', '' ) ) - status = params.get( 'status', 'done' ) - toolbox = self.app.toolbox - if params.get( 'reload_tool_button', False ): - tool_id = params.tool_id - message, status = toolbox.reload_tool_by_id( tool_id ) - return trans.fill_template( '/admin/reload_tool.mako', - toolbox=toolbox, - message=message, - status=status ) - @web.expose - @web.require_admin - def tool_versions( self, trans, **kwd ): - if 'message' not in kwd or not kwd[ 'message' ]: - kwd[ 'message' ] = 'Tool ids for tools that are currently loaded into the tool panel are highlighted in green (click to display).' - return self.tool_version_list_grid( trans, **kwd ) - # Galaxy Role Stuff - @web.expose - @web.require_admin - def roles( self, trans, **kwargs ): - if 'operation' in kwargs: - operation = kwargs['operation'].lower() - if operation == "roles": - return self.role( trans, **kwargs ) - if operation == "create": - return self.create_role( trans, **kwargs ) - if operation == "delete": - return self.mark_role_deleted( trans, **kwargs ) - if operation == "undelete": - return self.undelete_role( trans, **kwargs ) - if operation == "purge": - return self.purge_role( trans, **kwargs ) - if operation == "manage users and groups": - return self.manage_users_and_groups_for_role( trans, **kwargs ) - if operation == "rename": - return self.rename_role( trans, **kwargs ) - # Render the list view - return self.role_list_grid( trans, **kwargs ) - @web.expose - @web.require_admin - def create_role( self, trans, **kwd ): - params = util.Params( kwd ) - webapp = get_webapp( trans, **kwd ) - message = util.restore_text( params.get( 'message', '' ) ) - status = params.get( 'status', 'done' ) - name = util.restore_text( params.get( 'name', '' ) ) - description = util.restore_text( params.get( 'description', '' ) ) - in_users = util.listify( params.get( 'in_users', [] ) ) - out_users = util.listify( params.get( 'out_users', [] ) ) - in_groups = util.listify( params.get( 'in_groups', [] ) ) - out_groups = util.listify( params.get( 'out_groups', [] ) ) - create_group_for_role = params.get( 'create_group_for_role', '' ) - create_group_for_role_checked = CheckboxField.is_checked( create_group_for_role ) - ok = True - if params.get( 'create_role_button', False ): - if not name or not description: - message = "Enter a valid name and a description." - status = 'error' - ok = False - elif trans.sa_session.query( trans.app.model.Role ).filter( trans.app.model.Role.table.c.name==name ).first(): - message = "Role names must be unique and a role with that name already exists, so choose another name." - status = 'error' - ok = False - else: - # Create the role - role = trans.app.model.Role( name=name, description=description, type=trans.app.model.Role.types.ADMIN ) - trans.sa_session.add( role ) - # Create the UserRoleAssociations - for user in [ trans.sa_session.query( trans.app.model.User ).get( x ) for x in in_users ]: - ura = trans.app.model.UserRoleAssociation( user, role ) - trans.sa_session.add( ura ) - # Create the GroupRoleAssociations - for group in [ trans.sa_session.query( trans.app.model.Group ).get( x ) for x in in_groups ]: - gra = trans.app.model.GroupRoleAssociation( group, role ) - trans.sa_session.add( gra ) - if create_group_for_role_checked: - # Create the group - group = trans.app.model.Group( name=name ) - trans.sa_session.add( group ) - # Associate the group with the role - gra = trans.model.GroupRoleAssociation( group, role ) - trans.sa_session.add( gra ) - num_in_groups = len( in_groups ) + 1 - else: - num_in_groups = len( in_groups ) - trans.sa_session.flush() - message = "Role '%s' has been created with %d associated users and %d associated groups. " \ - % ( role.name, len( in_users ), num_in_groups ) - if create_group_for_role_checked: - message += 'One of the groups associated with this role is the newly created group with the same name.' - trans.response.send_redirect( web.url_for( controller='admin', - action='roles', - webapp=webapp, - message=util.sanitize_text( message ), - status='done' ) ) - if ok: - for user in trans.sa_session.query( trans.app.model.User ) \ - .filter( trans.app.model.User.table.c.deleted==False ) \ - .order_by( trans.app.model.User.table.c.email ): - out_users.append( ( user.id, user.email ) ) - for group in trans.sa_session.query( trans.app.model.Group ) \ - .filter( trans.app.model.Group.table.c.deleted==False ) \ - .order_by( trans.app.model.Group.table.c.name ): - out_groups.append( ( group.id, group.name ) ) - return trans.fill_template( '/admin/dataset_security/role/role_create.mako', - webapp=webapp, - name=name, - description=description, - in_users=in_users, - out_users=out_users, - in_groups=in_groups, - out_groups=out_groups, - create_group_for_role_checked=create_group_for_role_checked, - message=message, - status=status ) - @web.expose - @web.require_admin - def rename_role( self, trans, **kwd ): - params = util.Params( kwd ) - webapp = get_webapp( trans, **kwd ) - message = util.restore_text( params.get( 'message', '' ) ) - status = params.get( 'status', 'done' ) - id = params.get( 'id', None ) - if not id: - message = "No role ids received for renaming" - trans.response.send_redirect( web.url_for( controller='admin', - action='roles', - webapp=webapp, - message=message, - status='error' ) ) - role = get_role( trans, id ) - if params.get( 'rename_role_button', False ): - old_name = role.name - new_name = util.restore_text( params.name ) - new_description = util.restore_text( params.description ) - if not new_name: - message = 'Enter a valid name' - status='error' - else: - existing_role = trans.sa_session.query( trans.app.model.Role ).filter( trans.app.model.Role.table.c.name==new_name ).first() - if existing_role and existing_role.id != role.id: - message = 'A role with that name already exists' - status = 'error' - else: - if not ( role.name == new_name and role.description == new_description ): - role.name = new_name - role.description = new_description - trans.sa_session.add( role ) - trans.sa_session.flush() - message = "Role '%s' has been renamed to '%s'" % ( old_name, new_name ) - return trans.response.send_redirect( web.url_for( controller='admin', - action='roles', - webapp=webapp, - message=util.sanitize_text( message ), - status='done' ) ) - return trans.fill_template( '/admin/dataset_security/role/role_rename.mako', - role=role, - webapp=webapp, - message=message, - status=status ) - @web.expose - @web.require_admin - def manage_users_and_groups_for_role( self, trans, **kwd ): - params = util.Params( kwd ) - webapp = get_webapp( trans, **kwd ) - message = util.restore_text( params.get( 'message', '' ) ) - status = params.get( 'status', 'done' ) - id = params.get( 'id', None ) - if not id: - message = "No role ids received for managing users and groups" - trans.response.send_redirect( web.url_for( controller='admin', - action='roles', - webapp=webapp, - message=message, - status='error' ) ) - role = get_role( trans, id ) - if params.get( 'role_members_edit_button', False ): - in_users = [ trans.sa_session.query( trans.app.model.User ).get( x ) for x in util.listify( params.in_users ) ] - for ura in role.users: - user = trans.sa_session.query( trans.app.model.User ).get( ura.user_id ) - if user not in in_users: - # Delete DefaultUserPermissions for previously associated users that have been removed from the role - for dup in user.default_permissions: - if role == dup.role: - trans.sa_session.delete( dup ) - # Delete DefaultHistoryPermissions for previously associated users that have been removed from the role - for history in user.histories: - for dhp in history.default_permissions: - if role == dhp.role: - trans.sa_session.delete( dhp ) - trans.sa_session.flush() - in_groups = [ trans.sa_session.query( trans.app.model.Group ).get( x ) for x in util.listify( params.in_groups ) ] - trans.app.security_agent.set_entity_role_associations( roles=[ role ], users=in_users, groups=in_groups ) - trans.sa_session.refresh( role ) - message = "Role '%s' has been updated with %d associated users and %d associated groups" % ( role.name, len( in_users ), len( in_groups ) ) - trans.response.send_redirect( web.url_for( controller='admin', - action='roles', - webapp=webapp, - message=util.sanitize_text( message ), - status=status ) ) - in_users = [] - out_users = [] - in_groups = [] - out_groups = [] - for user in trans.sa_session.query( trans.app.model.User ) \ - .filter( trans.app.model.User.table.c.deleted==False ) \ - .order_by( trans.app.model.User.table.c.email ): - if user in [ x.user for x in role.users ]: - in_users.append( ( user.id, user.email ) ) - else: - out_users.append( ( user.id, user.email ) ) - for group in trans.sa_session.query( trans.app.model.Group ) \ - .filter( trans.app.model.Group.table.c.deleted==False ) \ - .order_by( trans.app.model.Group.table.c.name ): - if group in [ x.group for x in role.groups ]: - in_groups.append( ( group.id, group.name ) ) - else: - out_groups.append( ( group.id, group.name ) ) - library_dataset_actions = {} - if webapp == 'galaxy': - # Build a list of tuples that are LibraryDatasetDatasetAssociationss followed by a list of actions - # whose DatasetPermissions is associated with the Role - # [ ( LibraryDatasetDatasetAssociation [ action, action ] ) ] - for dp in role.dataset_actions: - for ldda in trans.sa_session.query( trans.app.model.LibraryDatasetDatasetAssociation ) \ - .filter( trans.app.model.LibraryDatasetDatasetAssociation.dataset_id==dp.dataset_id ): - root_found = False - folder_path = '' - folder = ldda.library_dataset.folder - while not root_found: - folder_path = '%s / %s' % ( folder.name, folder_path ) - if not folder.parent: - root_found = True - else: - folder = folder.parent - folder_path = '%s %s' % ( folder_path, ldda.name ) - library = trans.sa_session.query( trans.app.model.Library ) \ - .filter( trans.app.model.Library.table.c.root_folder_id == folder.id ) \ - .first() - if library not in library_dataset_actions: - library_dataset_actions[ library ] = {} - try: - library_dataset_actions[ library ][ folder_path ].append( dp.action ) - except: - library_dataset_actions[ library ][ folder_path ] = [ dp.action ] - return trans.fill_template( '/admin/dataset_security/role/role.mako', - role=role, - in_users=in_users, - out_users=out_users, - in_groups=in_groups, - out_groups=out_groups, - library_dataset_actions=library_dataset_actions, - webapp=webapp, - message=message, - status=status ) - @web.expose - @web.require_admin - def mark_role_deleted( self, trans, **kwd ): - params = util.Params( kwd ) - webapp = get_webapp( trans, **kwd ) - id = kwd.get( 'id', None ) - if not id: - message = "No role ids received for deleting" - trans.response.send_redirect( web.url_for( controller='admin', - action='roles', - webapp=webapp, - message=message, - status='error' ) ) - ids = util.listify( id ) - message = "Deleted %d roles: " % len( ids ) - for role_id in ids: - role = get_role( trans, role_id ) - role.deleted = True - trans.sa_session.add( role ) - trans.sa_session.flush() - message += " %s " % role.name - trans.response.send_redirect( web.url_for( controller='admin', - action='roles', - webapp=webapp, - message=util.sanitize_text( message ), - status='done' ) ) - @web.expose - @web.require_admin - def undelete_role( self, trans, **kwd ): - params = util.Params( kwd ) - webapp = get_webapp( trans, **kwd ) - id = kwd.get( 'id', None ) - if not id: - message = "No role ids received for undeleting" - trans.response.send_redirect( web.url_for( controller='admin', - action='roles', - webapp=webapp, - message=message, - status='error' ) ) - ids = util.listify( id ) - count = 0 - undeleted_roles = "" - for role_id in ids: - role = get_role( trans, role_id ) - if not role.deleted: - message = "Role '%s' has not been deleted, so it cannot be undeleted." % role.name - trans.response.send_redirect( web.url_for( controller='admin', - action='roles', - webapp=webapp, - message=util.sanitize_text( message ), - status='error' ) ) - role.deleted = False - trans.sa_session.add( role ) - trans.sa_session.flush() - count += 1 - undeleted_roles += " %s" % role.name - message = "Undeleted %d roles: %s" % ( count, undeleted_roles ) - trans.response.send_redirect( web.url_for( controller='admin', - action='roles', - webapp=webapp, - message=util.sanitize_text( message ), - status='done' ) ) - @web.expose - @web.require_admin - def purge_role( self, trans, **kwd ): - # This method should only be called for a Role that has previously been deleted. - # Purging a deleted Role deletes all of the following from the database: - # - UserRoleAssociations where role_id == Role.id - # - DefaultUserPermissions where role_id == Role.id - # - DefaultHistoryPermissions where role_id == Role.id - # - GroupRoleAssociations where role_id == Role.id - # - DatasetPermissionss where role_id == Role.id - params = util.Params( kwd ) - webapp = get_webapp( trans, **kwd ) - id = kwd.get( 'id', None ) - if not id: - message = "No role ids received for purging" - trans.response.send_redirect( web.url_for( controller='admin', - action='roles', - webapp=webapp, - message=util.sanitize_text( message ), - status='error' ) ) - ids = util.listify( id ) - message = "Purged %d roles: " % len( ids ) - for role_id in ids: - role = get_role( trans, role_id ) - if not role.deleted: - message = "Role '%s' has not been deleted, so it cannot be purged." % role.name - trans.response.send_redirect( web.url_for( controller='admin', - action='roles', - webapp=webapp, - message=util.sanitize_text( message ), - status='error' ) ) - # Delete UserRoleAssociations - for ura in role.users: - user = trans.sa_session.query( trans.app.model.User ).get( ura.user_id ) - # Delete DefaultUserPermissions for associated users - for dup in user.default_permissions: - if role == dup.role: - trans.sa_session.delete( dup ) - # Delete DefaultHistoryPermissions for associated users - for history in user.histories: - for dhp in history.default_permissions: - if role == dhp.role: - trans.sa_session.delete( dhp ) - trans.sa_session.delete( ura ) - # Delete GroupRoleAssociations - for gra in role.groups: - trans.sa_session.delete( gra ) - # Delete DatasetPermissionss - for dp in role.dataset_actions: - trans.sa_session.delete( dp ) - trans.sa_session.flush() - message += " %s " % role.name - trans.response.send_redirect( web.url_for( controller='admin', - action='roles', - webapp=webapp, - message=util.sanitize_text( message ), - status='done' ) ) - - # Galaxy Group Stuff - @web.expose - @web.require_admin - def groups( self, trans, **kwargs ): - if 'operation' in kwargs: - operation = kwargs['operation'].lower() - if operation == "groups": - return self.group( trans, **kwargs ) - if operation == "create": - return self.create_group( trans, **kwargs ) - if operation == "delete": - return self.mark_group_deleted( trans, **kwargs ) - if operation == "undelete": - return self.undelete_group( trans, **kwargs ) - if operation == "purge": - return self.purge_group( trans, **kwargs ) - if operation == "manage users and roles": - return self.manage_users_and_roles_for_group( trans, **kwargs ) - if operation == "rename": - return self.rename_group( trans, **kwargs ) - # Render the list view - return self.group_list_grid( trans, **kwargs ) - @web.expose - @web.require_admin - def rename_group( self, trans, **kwd ): - params = util.Params( kwd ) - webapp = get_webapp( trans, **kwd ) - message = util.restore_text( params.get( 'message', '' ) ) - status = params.get( 'status', 'done' ) - id = params.get( 'id', None ) - if not id: - message = "No group ids received for renaming" - trans.response.send_redirect( web.url_for( controller='admin', - action='groups', - webapp=webapp, - message=message, - status='error' ) ) - group = get_group( trans, id ) - if params.get( 'rename_group_button', False ): - old_name = group.name - new_name = util.restore_text( params.name ) - if not new_name: - message = 'Enter a valid name' - status = 'error' - else: - existing_group = trans.sa_session.query( trans.app.model.Group ).filter( trans.app.model.Group.table.c.name==new_name ).first() - if existing_group and existing_group.id != group.id: - message = 'A group with that name already exists' - status = 'error' - else: - if group.name != new_name: - group.name = new_name - trans.sa_session.add( group ) - trans.sa_session.flush() - message = "Group '%s' has been renamed to '%s'" % ( old_name, new_name ) - return trans.response.send_redirect( web.url_for( controller='admin', - action='groups', - webapp=webapp, - message=util.sanitize_text( message ), - status='done' ) ) - return trans.fill_template( '/admin/dataset_security/group/group_rename.mako', - group=group, - webapp=webapp, - message=message, - status=status ) - @web.expose - @web.require_admin - def manage_users_and_roles_for_group( self, trans, **kwd ): - params = util.Params( kwd ) - webapp = get_webapp( trans, **kwd ) - message = util.restore_text( params.get( 'message', '' ) ) - status = params.get( 'status', 'done' ) - group = get_group( trans, params.id ) - if params.get( 'group_roles_users_edit_button', False ): - in_roles = [ trans.sa_session.query( trans.app.model.Role ).get( x ) for x in util.listify( params.in_roles ) ] - in_users = [ trans.sa_session.query( trans.app.model.User ).get( x ) for x in util.listify( params.in_users ) ] - trans.app.security_agent.set_entity_group_associations( groups=[ group ], roles=in_roles, users=in_users ) - trans.sa_session.refresh( group ) - message += "Group '%s' has been updated with %d associated roles and %d associated users" % ( group.name, len( in_roles ), len( in_users ) ) - trans.response.send_redirect( web.url_for( controller='admin', - action='groups', - webapp=webapp, - message=util.sanitize_text( message ), - status=status ) ) - in_roles = [] - out_roles = [] - in_users = [] - out_users = [] - for role in trans.sa_session.query(trans.app.model.Role ) \ - .filter( trans.app.model.Role.table.c.deleted==False ) \ - .order_by( trans.app.model.Role.table.c.name ): - if role in [ x.role for x in group.roles ]: - in_roles.append( ( role.id, role.name ) ) - else: - out_roles.append( ( role.id, role.name ) ) - for user in trans.sa_session.query( trans.app.model.User ) \ - .filter( trans.app.model.User.table.c.deleted==False ) \ - .order_by( trans.app.model.User.table.c.email ): - if user in [ x.user for x in group.users ]: - in_users.append( ( user.id, user.email ) ) - else: - out_users.append( ( user.id, user.email ) ) - message += 'Group %s is currently associated with %d roles and %d users' % ( group.name, len( in_roles ), len( in_users ) ) - return trans.fill_template( '/admin/dataset_security/group/group.mako', - group=group, - in_roles=in_roles, - out_roles=out_roles, - in_users=in_users, - out_users=out_users, - webapp=webapp, - message=message, - status=status ) - @web.expose - @web.require_admin - def create_group( self, trans, **kwd ): - params = util.Params( kwd ) - webapp = get_webapp( trans, **kwd ) - message = util.restore_text( params.get( 'message', '' ) ) - status = params.get( 'status', 'done' ) - name = util.restore_text( params.get( 'name', '' ) ) - in_users = util.listify( params.get( 'in_users', [] ) ) - out_users = util.listify( params.get( 'out_users', [] ) ) - in_roles = util.listify( params.get( 'in_roles', [] ) ) - out_roles = util.listify( params.get( 'out_roles', [] ) ) - create_role_for_group = params.get( 'create_role_for_group', '' ) - create_role_for_group_checked = CheckboxField.is_checked( create_role_for_group ) - ok = True - if params.get( 'create_group_button', False ): - if not name: - message = "Enter a valid name." - status = 'error' - ok = False - elif trans.sa_session.query( trans.app.model.Group ).filter( trans.app.model.Group.table.c.name==name ).first(): - message = "Group names must be unique and a group with that name already exists, so choose another name." - status = 'error' - ok = False - else: - # Create the group - group = trans.app.model.Group( name=name ) - trans.sa_session.add( group ) - trans.sa_session.flush() - # Create the UserRoleAssociations - for user in [ trans.sa_session.query( trans.app.model.User ).get( x ) for x in in_users ]: - uga = trans.app.model.UserGroupAssociation( user, group ) - trans.sa_session.add( uga ) - # Create the GroupRoleAssociations - for role in [ trans.sa_session.query( trans.app.model.Role ).get( x ) for x in in_roles ]: - gra = trans.app.model.GroupRoleAssociation( group, role ) - trans.sa_session.add( gra ) - if create_role_for_group_checked: - # Create the role - role = trans.app.model.Role( name=name, description='Role for group %s' % name ) - trans.sa_session.add( role ) - # Associate the role with the group - gra = trans.model.GroupRoleAssociation( group, role ) - trans.sa_session.add( gra ) - num_in_roles = len( in_roles ) + 1 - else: - num_in_roles = len( in_roles ) - trans.sa_session.flush() - message = "Group '%s' has been created with %d associated users and %d associated roles. " \ - % ( group.name, len( in_users ), num_in_roles ) - if create_role_for_group_checked: - message += 'One of the roles associated with this group is the newly created role with the same name.' - trans.response.send_redirect( web.url_for( controller='admin', - action='groups', - webapp=webapp, - message=util.sanitize_text( message ), - status='done' ) ) - - - if ok: - for user in trans.sa_session.query( trans.app.model.User ) \ - .filter( trans.app.model.User.table.c.deleted==False ) \ - .order_by( trans.app.model.User.table.c.email ): - out_users.append( ( user.id, user.email ) ) - for role in trans.sa_session.query( trans.app.model.Role ) \ - .filter( trans.app.model.Role.table.c.deleted==False ) \ - .order_by( trans.app.model.Role.table.c.name ): - out_roles.append( ( role.id, role.name ) ) - return trans.fill_template( '/admin/dataset_security/group/group_create.mako', - webapp=webapp, - name=name, - in_users=in_users, - out_users=out_users, - in_roles=in_roles, - out_roles=out_roles, - create_role_for_group_checked=create_role_for_group_checked, - message=message, - status=status ) - @web.expose - @web.require_admin - def mark_group_deleted( self, trans, **kwd ): - params = util.Params( kwd ) - webapp = get_webapp( trans, **kwd ) - id = params.get( 'id', None ) - if not id: - message = "No group ids received for marking deleted" - trans.response.send_redirect( web.url_for( controller='admin', - action='groups', - webapp=webapp, - message=message, - status='error' ) ) - ids = util.listify( id ) - message = "Deleted %d groups: " % len( ids ) - for group_id in ids: - group = get_group( trans, group_id ) - group.deleted = True - trans.sa_session.add( group ) - trans.sa_session.flush() - message += " %s " % group.name - trans.response.send_redirect( web.url_for( controller='admin', - action='groups', - webapp=webapp, - message=util.sanitize_text( message ), - status='done' ) ) - @web.expose - @web.require_admin - def undelete_group( self, trans, **kwd ): - params = util.Params( kwd ) - webapp = get_webapp( trans, **kwd ) - id = kwd.get( 'id', None ) - if not id: - message = "No group ids received for undeleting" - trans.response.send_redirect( web.url_for( controller='admin', - action='groups', - webapp=webapp, - message=message, - status='error' ) ) - ids = util.listify( id ) - count = 0 - undeleted_groups = "" - for group_id in ids: - group = get_group( trans, group_id ) - if not group.deleted: - message = "Group '%s' has not been deleted, so it cannot be undeleted." % group.name - trans.response.send_redirect( web.url_for( controller='admin', - action='groups', - webapp=webapp, - message=util.sanitize_text( message ), - status='error' ) ) - group.deleted = False - trans.sa_session.add( group ) - trans.sa_session.flush() - count += 1 - undeleted_groups += " %s" % group.name - message = "Undeleted %d groups: %s" % ( count, undeleted_groups ) - trans.response.send_redirect( web.url_for( controller='admin', - action='groups', - webapp=webapp, - message=util.sanitize_text( message ), - status='done' ) ) - @web.expose - @web.require_admin - def purge_group( self, trans, **kwd ): - # This method should only be called for a Group that has previously been deleted. - # Purging a deleted Group simply deletes all UserGroupAssociations and GroupRoleAssociations. - params = util.Params( kwd ) - webapp = get_webapp( trans, **kwd ) - id = kwd.get( 'id', None ) - if not id: - message = "No group ids received for purging" - trans.response.send_redirect( web.url_for( controller='admin', - action='groups', - webapp=webapp, - message=util.sanitize_text( message ), - status='error' ) ) - ids = util.listify( id ) - message = "Purged %d groups: " % len( ids ) - for group_id in ids: - group = get_group( trans, group_id ) - if not group.deleted: - # We should never reach here, but just in case there is a bug somewhere... - message = "Group '%s' has not been deleted, so it cannot be purged." % group.name - trans.response.send_redirect( web.url_for( controller='admin', - action='groups', - webapp=webapp, - message=util.sanitize_text( message ), - status='error' ) ) - # Delete UserGroupAssociations - for uga in group.users: - trans.sa_session.delete( uga ) - # Delete GroupRoleAssociations - for gra in group.roles: - trans.sa_session.delete( gra ) - trans.sa_session.flush() - message += " %s " % group.name - trans.response.send_redirect( web.url_for( controller='admin', - action='groups', - webapp=webapp, - message=util.sanitize_text( message ), - status='done' ) ) - - # Galaxy User Stuff - @web.expose - @web.require_admin - def create_new_user( self, trans, **kwd ): - webapp = get_webapp( trans, **kwd ) - return trans.response.send_redirect( web.url_for( controller='user', - action='create', - cntrller='admin', - webapp=webapp ) ) - @web.expose - @web.require_admin - def reset_user_password( self, trans, **kwd ): - webapp = get_webapp( trans, **kwd ) - user_id = kwd.get( 'id', None ) - if not user_id: - message = "No users received for resetting passwords." - trans.response.send_redirect( web.url_for( controller='admin', - action='users', - webapp=webapp, - message=message, - status='error' ) ) - user_ids = util.listify( user_id ) - if 'reset_user_password_button' in kwd: - message = '' - status = '' - for user_id in user_ids: - user = get_user( trans, user_id ) - password = kwd.get( 'password', None ) - confirm = kwd.get( 'confirm' , None ) - if len( password ) < 6: - message = "Use a password of at least 6 characters." - status = 'error' - break - elif password != confirm: - message = "Passwords do not match." - status = 'error' - break - else: - user.set_password_cleartext( password ) - trans.sa_session.add( user ) - trans.sa_session.flush() - if not message and not status: - message = "Passwords reset for %d %s." % ( len( user_ids ), inflector.cond_plural( len( user_ids ), 'user' ) ) - status = 'done' - trans.response.send_redirect( web.url_for( controller='admin', - action='users', - webapp=webapp, - message=util.sanitize_text( message ), - status=status ) ) - users = [ get_user( trans, user_id ) for user_id in user_ids ] - if len( user_ids ) > 1: - user_id = ','.join( user_ids ) - return trans.fill_template( '/admin/user/reset_password.mako', - id=user_id, - users=users, - password='', - confirm='', - webapp=webapp ) - @web.expose - @web.require_admin - def mark_user_deleted( self, trans, **kwd ): - webapp = get_webapp( trans, **kwd ) - id = kwd.get( 'id', None ) - if not id: - message = "No user ids received for deleting" - trans.response.send_redirect( web.url_for( controller='admin', - action='users', - webapp=webapp, - message=message, - status='error' ) ) - ids = util.listify( id ) - message = "Deleted %d users: " % len( ids ) - for user_id in ids: - user = get_user( trans, user_id ) - user.deleted = True - trans.sa_session.add( user ) - trans.sa_session.flush() - message += " %s " % user.email - trans.response.send_redirect( web.url_for( controller='admin', - action='users', - webapp=webapp, - message=util.sanitize_text( message ), - status='done' ) ) - @web.expose - @web.require_admin - def undelete_user( self, trans, **kwd ): - webapp = get_webapp( trans, **kwd ) - id = kwd.get( 'id', None ) - if not id: - message = "No user ids received for undeleting" - trans.response.send_redirect( web.url_for( controller='admin', - action='users', - webapp=webapp, - message=message, - status='error' ) ) - ids = util.listify( id ) - count = 0 - undeleted_users = "" - for user_id in ids: - user = get_user( trans, user_id ) - if not user.deleted: - message = "User '%s' has not been deleted, so it cannot be undeleted." % user.email - trans.response.send_redirect( web.url_for( controller='admin', - action='users', - webapp=webapp, - message=util.sanitize_text( message ), - status='error' ) ) - user.deleted = False - trans.sa_session.add( user ) - trans.sa_session.flush() - count += 1 - undeleted_users += " %s" % user.email - message = "Undeleted %d users: %s" % ( count, undeleted_users ) - trans.response.send_redirect( web.url_for( controller='admin', - action='users', - webapp=webapp, - message=util.sanitize_text( message ), - status='done' ) ) - @web.expose - @web.require_admin - def purge_user( self, trans, **kwd ): - # This method should only be called for a User that has previously been deleted. - # We keep the User in the database ( marked as purged ), and stuff associated - # with the user's private role in case we want the ability to unpurge the user - # some time in the future. - # Purging a deleted User deletes all of the following: - # - History where user_id = User.id - # - HistoryDatasetAssociation where history_id = History.id - # - Dataset where HistoryDatasetAssociation.dataset_id = Dataset.id - # - UserGroupAssociation where user_id == User.id - # - UserRoleAssociation where user_id == User.id EXCEPT FOR THE PRIVATE ROLE - # - UserAddress where user_id == User.id - # Purging Histories and Datasets must be handled via the cleanup_datasets.py script - webapp = get_webapp( trans, **kwd ) - id = kwd.get( 'id', None ) - if not id: - message = "No user ids received for purging" - trans.response.send_redirect( web.url_for( controller='admin', - action='users', - webapp=webapp, - message=util.sanitize_text( message ), - status='error' ) ) - ids = util.listify( id ) - message = "Purged %d users: " % len( ids ) - for user_id in ids: - user = get_user( trans, user_id ) - if not user.deleted: - # We should never reach here, but just in case there is a bug somewhere... - message = "User '%s' has not been deleted, so it cannot be purged." % user.email - trans.response.send_redirect( web.url_for( controller='admin', - action='users', - webapp=webapp, - message=util.sanitize_text( message ), - status='error' ) ) - private_role = trans.app.security_agent.get_private_user_role( user ) - # Delete History - for h in user.active_histories: - trans.sa_session.refresh( h ) - for hda in h.active_datasets: - # Delete HistoryDatasetAssociation - d = trans.sa_session.query( trans.app.model.Dataset ).get( hda.dataset_id ) - # Delete Dataset - if not d.deleted: - d.deleted = True - trans.sa_session.add( d ) - hda.deleted = True - trans.sa_session.add( hda ) - h.deleted = True - trans.sa_session.add( h ) - # Delete UserGroupAssociations - for uga in user.groups: - trans.sa_session.delete( uga ) - # Delete UserRoleAssociations EXCEPT FOR THE PRIVATE ROLE - for ura in user.roles: - if ura.role_id != private_role.id: - trans.sa_session.delete( ura ) - # Delete UserAddresses - for address in user.addresses: - trans.sa_session.delete( address ) - # Purge the user - user.purged = True - trans.sa_session.add( user ) - trans.sa_session.flush() - message += "%s " % user.email - trans.response.send_redirect( web.url_for( controller='admin', - action='users', - webapp=webapp, - message=util.sanitize_text( message ), - status='done' ) ) - @web.expose - @web.require_admin - def users( self, trans, **kwd ): - if 'operation' in kwd: - operation = kwd['operation'].lower() - if operation == "roles": - return self.user( trans, **kwd ) - elif operation == "reset password": - return self.reset_user_password( trans, **kwd ) - elif operation == "delete": - return self.mark_user_deleted( trans, **kwd ) - elif operation == "undelete": - return self.undelete_user( trans, **kwd ) - elif operation == "purge": - return self.purge_user( trans, **kwd ) - elif operation == "create": - return self.create_new_user( trans, **kwd ) - elif operation == "information": - user_id = kwd.get( 'id', None ) - if not user_id: - kwd[ 'message' ] = util.sanitize_text( "Invalid user id (%s) received" % str( user_id ) ) - kwd[ 'status' ] = 'error' - else: - return trans.response.send_redirect( web.url_for( controller='user', - action='manage_user_info', - cntrller='admin', - **kwd ) ) - elif operation == "manage roles and groups": - return self.manage_roles_and_groups_for_user( trans, **kwd ) - if trans.app.config.allow_user_deletion: - if self.delete_operation not in self.user_list_grid.operations: - self.user_list_grid.operations.append( self.delete_operation ) - if self.undelete_operation not in self.user_list_grid.operations: - self.user_list_grid.operations.append( self.undelete_operation ) - if self.purge_operation not in self.user_list_grid.operations: - self.user_list_grid.operations.append( self.purge_operation ) - # Render the list view - return self.user_list_grid( trans, **kwd ) - @web.expose - @web.require_admin - def name_autocomplete_data( self, trans, q=None, limit=None, timestamp=None ): - """Return autocomplete data for user emails""" - ac_data = "" - for user in trans.sa_session.query( User ).filter_by( deleted=False ).filter( func.lower( User.email ).like( q.lower() + "%" ) ): - ac_data = ac_data + user.email + "\n" - return ac_data - @web.expose - @web.require_admin - def manage_roles_and_groups_for_user( self, trans, **kwd ): - webapp = get_webapp( trans, **kwd ) - user_id = kwd.get( 'id', None ) - message = '' - status = '' - if not user_id: - message += "Invalid user id (%s) received" % str( user_id ) - trans.response.send_redirect( web.url_for( controller='admin', - action='users', - webapp=webapp, - message=util.sanitize_text( message ), - status='error' ) ) - user = get_user( trans, user_id ) - private_role = trans.app.security_agent.get_private_user_role( user ) - if kwd.get( 'user_roles_groups_edit_button', False ): - # Make sure the user is not dis-associating himself from his private role - out_roles = kwd.get( 'out_roles', [] ) - if out_roles: - out_roles = [ trans.sa_session.query( trans.app.model.Role ).get( x ) for x in util.listify( out_roles ) ] - if private_role in out_roles: - message += "You cannot eliminate a user's private role association. " - status = 'error' - in_roles = kwd.get( 'in_roles', [] ) - if in_roles: - in_roles = [ trans.sa_session.query( trans.app.model.Role ).get( x ) for x in util.listify( in_roles ) ] - out_groups = kwd.get( 'out_groups', [] ) - if out_groups: - out_groups = [ trans.sa_session.query( trans.app.model.Group ).get( x ) for x in util.listify( out_groups ) ] - in_groups = kwd.get( 'in_groups', [] ) - if in_groups: - in_groups = [ trans.sa_session.query( trans.app.model.Group ).get( x ) for x in util.listify( in_groups ) ] - if in_roles: - trans.app.security_agent.set_entity_user_associations( users=[ user ], roles=in_roles, groups=in_groups ) - trans.sa_session.refresh( user ) - message += "User '%s' has been updated with %d associated roles and %d associated groups (private roles are not displayed)" % \ - ( user.email, len( in_roles ), len( in_groups ) ) - trans.response.send_redirect( web.url_for( controller='admin', - action='users', - webapp=webapp, - message=util.sanitize_text( message ), - status='done' ) ) - in_roles = [] - out_roles = [] - in_groups = [] - out_groups = [] - for role in trans.sa_session.query( trans.app.model.Role ).filter( trans.app.model.Role.table.c.deleted==False ) \ - .order_by( trans.app.model.Role.table.c.name ): - if role in [ x.role for x in user.roles ]: - in_roles.append( ( role.id, role.name ) ) - elif role.type != trans.app.model.Role.types.PRIVATE: - # There is a 1 to 1 mapping between a user and a PRIVATE role, so private roles should - # not be listed in the roles form fields, except for the currently selected user's private - # role, which should always be in in_roles. The check above is added as an additional - # precaution, since for a period of time we were including private roles in the form fields. - out_roles.append( ( role.id, role.name ) ) - for group in trans.sa_session.query( trans.app.model.Group ).filter( trans.app.model.Group.table.c.deleted==False ) \ - .order_by( trans.app.model.Group.table.c.name ): - if group in [ x.group for x in user.groups ]: - in_groups.append( ( group.id, group.name ) ) - else: - out_groups.append( ( group.id, group.name ) ) - message += "User '%s' is currently associated with %d roles and is a member of %d groups" % \ - ( user.email, len( in_roles ), len( in_groups ) ) - if not status: - status = 'done' - return trans.fill_template( '/admin/user/user.mako', - user=user, - in_roles=in_roles, - out_roles=out_roles, - in_groups=in_groups, - out_groups=out_groups, - webapp=webapp, - message=message, - status=status ) - @web.expose - @web.require_admin - def memdump( self, trans, ids = 'None', sorts = 'None', pages = 'None', new_id = None, new_sort = None, **kwd ): - if self.app.memdump is None: - return trans.show_error_message( "Memdump is not enabled (set <code>use_memdump = True</code> in universe_wsgi.ini)" ) - heap = self.app.memdump.get() - p = util.Params( kwd ) - msg = None - if p.dump: - heap = self.app.memdump.get( update = True ) - msg = "Heap dump complete" - elif p.setref: - self.app.memdump.setref() - msg = "Reference point set (dump to see delta from this point)" - ids = ids.split( ',' ) - sorts = sorts.split( ',' ) - if new_id is not None: - ids.append( new_id ) - sorts.append( 'None' ) - elif new_sort is not None: - sorts[-1] = new_sort - breadcrumb = "<a href='%s' class='breadcrumb'>heap</a>" % web.url_for() - # new lists so we can assemble breadcrumb links - new_ids = [] - new_sorts = [] - for id, sort in zip( ids, sorts ): - new_ids.append( id ) - if id != 'None': - breadcrumb += "<a href='%s' class='breadcrumb'>[%s]</a>" % ( web.url_for( ids=','.join( new_ids ), sorts=','.join( new_sorts ) ), id ) - heap = heap[int(id)] - new_sorts.append( sort ) - if sort != 'None': - breadcrumb += "<a href='%s' class='breadcrumb'>.by('%s')</a>" % ( web.url_for( ids=','.join( new_ids ), sorts=','.join( new_sorts ) ), sort ) - heap = heap.by( sort ) - ids = ','.join( new_ids ) - sorts = ','.join( new_sorts ) - if p.theone: - breadcrumb += ".theone" - heap = heap.theone - return trans.fill_template( '/admin/memdump.mako', heap = heap, ids = ids, sorts = sorts, breadcrumb = breadcrumb, msg = msg ) - - @web.expose - @web.require_admin - def jobs( self, trans, stop = [], stop_msg = None, cutoff = 180, job_lock = None, ajl_submit = None, **kwd ): - deleted = [] - msg = None - status = None - if self.app.config.job_manager != self.app.config.server_name: - return trans.show_error_message( 'This Galaxy instance (%s) is not the job manager (%s). If using multiple servers, please directly access the job manager instance to manage jobs.' % (self.app.config.server_name, self.app.config.job_manager) ) - job_ids = util.listify( stop ) - if job_ids and stop_msg in [ None, '' ]: - msg = 'Please enter an error message to display to the user describing why the job was terminated' - status = 'error' - elif job_ids: - if stop_msg[-1] not in string.punctuation: - stop_msg += '.' - for job_id in job_ids: - trans.app.job_manager.job_stop_queue.put( job_id, error_msg="This job was stopped by an administrator: %s For more information or help" % stop_msg ) - deleted.append( str( job_id ) ) - if deleted: - msg = 'Queued job' - if len( deleted ) > 1: - msg += 's' - msg += ' for deletion: ' - msg += ', '.join( deleted ) - status = 'done' - if ajl_submit: - if job_lock == 'on': - trans.app.job_manager.job_queue.job_lock = True - else: - trans.app.job_manager.job_queue.job_lock = False - cutoff_time = datetime.utcnow() - timedelta( seconds=int( cutoff ) ) - jobs = trans.sa_session.query( trans.app.model.Job ) \ - .filter( and_( trans.app.model.Job.table.c.update_time < cutoff_time, - or_( trans.app.model.Job.state == trans.app.model.Job.states.NEW, - trans.app.model.Job.state == trans.app.model.Job.states.QUEUED, - trans.app.model.Job.state == trans.app.model.Job.states.RUNNING, - trans.app.model.Job.state == trans.app.model.Job.states.UPLOAD ) ) ) \ - .order_by( trans.app.model.Job.table.c.update_time.desc() ) - last_updated = {} - for job in jobs: - delta = datetime.utcnow() - job.update_time - if delta > timedelta( minutes=60 ): - last_updated[job.id] = '%s hours' % int( delta.seconds / 60 / 60 ) - else: - last_updated[job.id] = '%s minutes' % int( delta.seconds / 60 ) - return trans.fill_template( '/admin/jobs.mako', - jobs = jobs, - last_updated = last_updated, - cutoff = cutoff, - msg = msg, - status = status, - job_lock = trans.app.job_manager.job_queue.job_lock ) - ## ---- Utility methods ------------------------------------------------------- -def get_ids_of_tool_shed_repositories_being_installed( trans, as_string=False ): - installing_repository_ids = [] - new_status = trans.model.ToolShedRepository.installation_status.NEW - cloning_status = trans.model.ToolShedRepository.installation_status.CLONING - setting_tool_versions_status = trans.model.ToolShedRepository.installation_status.SETTING_TOOL_VERSIONS - installing_dependencies_status = trans.model.ToolShedRepository.installation_status.INSTALLING_TOOL_DEPENDENCIES - loading_datatypes_status = trans.model.ToolShedRepository.installation_status.LOADING_PROPRIETARY_DATATYPES - for tool_shed_repository in trans.sa_session.query( trans.model.ToolShedRepository ) \ - .filter( or_( trans.model.ToolShedRepository.status == new_status, - trans.model.ToolShedRepository.status == cloning_status, - trans.model.ToolShedRepository.status == setting_tool_versions_status, - trans.model.ToolShedRepository.status == installing_dependencies_status, - trans.model.ToolShedRepository.status == loading_datatypes_status ) ): - installing_repository_ids.append( trans.security.encode_id( tool_shed_repository.id ) ) - if as_string: - return ','.join( installing_repository_ids ) - return installing_repository_ids - -def get_user( trans, user_id ): - """Get a User from the database by id.""" - user = trans.sa_session.query( trans.model.User ).get( trans.security.decode_id( user_id ) ) - if not user: - return trans.show_error_message( "User not found for id (%s)" % str( user_id ) ) - return user -def get_user_by_username( trans, username ): - """Get a user from the database by username""" - # TODO: Add exception handling here. - return trans.sa_session.query( trans.model.User ) \ - .filter( trans.model.User.table.c.username == username ) \ - .one() -def get_role( trans, id ): - """Get a Role from the database by id.""" - # Load user from database - id = trans.security.decode_id( id ) - role = trans.sa_session.query( trans.model.Role ).get( id ) - if not role: - return trans.show_error_message( "Role not found for id (%s)" % str( id ) ) - return role -def get_group( trans, id ): - """Get a Group from the database by id.""" - # Load user from database - id = trans.security.decode_id( id ) - group = trans.sa_session.query( trans.model.Group ).get( id ) - if not group: - return trans.show_error_message( "Group not found for id (%s)" % str( id ) ) - return group -def get_quota( trans, id ): - """Get a Quota from the database by id.""" - # Load user from database - id = trans.security.decode_id( id ) - quota = trans.sa_session.query( trans.model.Quota ).get( id ) - return quota -def get_webapp( trans, **kwd ): - """Get the value of the webapp, can be one of 'community', 'galaxy', 'reports', 'demo_sequencer'.""" - if 'webapp' in kwd: - return kwd[ 'webapp' ] - if 'webapp' in trans.environ: - return trans.environ[ 'webapp' ] - # The default is galaxy. - return 'galaxy' def sort_by_attr( seq, attr ): """ Sort the sequence of objects by object's attribute diff -r 203e3e1592439dcb8c0eb890545ed38a66f08f2c -r 2ca0e99d6d6d940af0712e9c56b9f238fd59635c lib/galaxy/web/base/controllers/admin.py --- /dev/null +++ b/lib/galaxy/web/base/controllers/admin.py @@ -0,0 +1,1114 @@ +from datetime import date, datetime, timedelta + +from galaxy import config, tools, web, util +from galaxy.model.orm import * + +class Admin( object ): + # Override these + user_list_grid = None + role_list_grid = None + group_list_grid = None + quota_list_grid = None + repository_list_grid = None + tool_version_list_grid = None + delete_operation = None + undelete_operation = None + purge_operation = None + + @web.expose + @web.require_admin + def index( self, trans, **kwd ): + message = kwd.get( 'message', '' ) + status = kwd.get( 'status', 'done' ) + if trans.webapp.name == 'galaxy': + installed_repositories = trans.sa_session.query( trans.model.ToolShedRepository ).first() + installing_repository_ids = get_ids_of_tool_shed_repositories_being_installed( trans, as_string=True ) + return trans.fill_template( '/webapps/galaxy/admin/index.mako', + installed_repositories=installed_repositories, + installing_repository_ids=installing_repository_ids, + message=message, + status=status ) + else: + return trans.fill_template( '/webapps/community/admin/index.mako', + message=message, + status=status ) + @web.expose + @web.require_admin + def center( self, trans, **kwd ): + message = kwd.get( 'message', '' ) + status = kwd.get( 'status', 'done' ) + if trans.webapp.name == 'galaxy': + return trans.fill_template( '/webapps/galaxy/admin/center.mako', + message=message, + status=status ) + else: + return trans.fill_template( '/webapps/community/admin/center.mako', + message=message, + status=status ) + @web.expose + @web.require_admin + def reload_tool( self, trans, **kwd ): + params = util.Params( kwd ) + message = util.restore_text( params.get( 'message', '' ) ) + status = params.get( 'status', 'done' ) + toolbox = self.app.toolbox + if params.get( 'reload_tool_button', False ): + tool_id = params.tool_id + message, status = toolbox.reload_tool_by_id( tool_id ) + return trans.fill_template( '/admin/reload_tool.mako', + toolbox=toolbox, + message=message, + status=status ) + @web.expose + @web.require_admin + def tool_versions( self, trans, **kwd ): + if 'message' not in kwd or not kwd[ 'message' ]: + kwd[ 'message' ] = 'Tool ids for tools that are currently loaded into the tool panel are highlighted in green (click to display).' + return self.tool_version_list_grid( trans, **kwd ) + # Galaxy Role Stuff + @web.expose + @web.require_admin + def roles( self, trans, **kwargs ): + if 'operation' in kwargs: + operation = kwargs['operation'].lower() + if operation == "roles": + return self.role( trans, **kwargs ) + if operation == "create": + return self.create_role( trans, **kwargs ) + if operation == "delete": + return self.mark_role_deleted( trans, **kwargs ) + if operation == "undelete": + return self.undelete_role( trans, **kwargs ) + if operation == "purge": + return self.purge_role( trans, **kwargs ) + if operation == "manage users and groups": + return self.manage_users_and_groups_for_role( trans, **kwargs ) + if operation == "rename": + return self.rename_role( trans, **kwargs ) + # Render the list view + return self.role_list_grid( trans, **kwargs ) + @web.expose + @web.require_admin + def create_role( self, trans, **kwd ): + params = util.Params( kwd ) + message = util.restore_text( params.get( 'message', '' ) ) + status = params.get( 'status', 'done' ) + name = util.restore_text( params.get( 'name', '' ) ) + description = util.restore_text( params.get( 'description', '' ) ) + in_users = util.listify( params.get( 'in_users', [] ) ) + out_users = util.listify( params.get( 'out_users', [] ) ) + in_groups = util.listify( params.get( 'in_groups', [] ) ) + out_groups = util.listify( params.get( 'out_groups', [] ) ) + create_group_for_role = params.get( 'create_group_for_role', '' ) + create_group_for_role_checked = CheckboxField.is_checked( create_group_for_role ) + ok = True + if params.get( 'create_role_button', False ): + if not name or not description: + message = "Enter a valid name and a description." + status = 'error' + ok = False + elif trans.sa_session.query( trans.app.model.Role ).filter( trans.app.model.Role.table.c.name==name ).first(): + message = "Role names must be unique and a role with that name already exists, so choose another name." + status = 'error' + ok = False + else: + # Create the role + role = trans.app.model.Role( name=name, description=description, type=trans.app.model.Role.types.ADMIN ) + trans.sa_session.add( role ) + # Create the UserRoleAssociations + for user in [ trans.sa_session.query( trans.app.model.User ).get( x ) for x in in_users ]: + ura = trans.app.model.UserRoleAssociation( user, role ) + trans.sa_session.add( ura ) + # Create the GroupRoleAssociations + for group in [ trans.sa_session.query( trans.app.model.Group ).get( x ) for x in in_groups ]: + gra = trans.app.model.GroupRoleAssociation( group, role ) + trans.sa_session.add( gra ) + if create_group_for_role_checked: + # Create the group + group = trans.app.model.Group( name=name ) + trans.sa_session.add( group ) + # Associate the group with the role + gra = trans.model.GroupRoleAssociation( group, role ) + trans.sa_session.add( gra ) + num_in_groups = len( in_groups ) + 1 + else: + num_in_groups = len( in_groups ) + trans.sa_session.flush() + message = "Role '%s' has been created with %d associated users and %d associated groups. " \ + % ( role.name, len( in_users ), num_in_groups ) + if create_group_for_role_checked: + message += 'One of the groups associated with this role is the newly created group with the same name.' + trans.response.send_redirect( web.url_for( controller='admin', + action='roles', + message=util.sanitize_text( message ), + status='done' ) ) + if ok: + for user in trans.sa_session.query( trans.app.model.User ) \ + .filter( trans.app.model.User.table.c.deleted==False ) \ + .order_by( trans.app.model.User.table.c.email ): + out_users.append( ( user.id, user.email ) ) + for group in trans.sa_session.query( trans.app.model.Group ) \ + .filter( trans.app.model.Group.table.c.deleted==False ) \ + .order_by( trans.app.model.Group.table.c.name ): + out_groups.append( ( group.id, group.name ) ) + return trans.fill_template( '/admin/dataset_security/role/role_create.mako', + name=name, + description=description, + in_users=in_users, + out_users=out_users, + in_groups=in_groups, + out_groups=out_groups, + create_group_for_role_checked=create_group_for_role_checked, + message=message, + status=status ) + @web.expose + @web.require_admin + def rename_role( self, trans, **kwd ): + params = util.Params( kwd ) + message = util.restore_text( params.get( 'message', '' ) ) + status = params.get( 'status', 'done' ) + id = params.get( 'id', None ) + if not id: + message = "No role ids received for renaming" + trans.response.send_redirect( web.url_for( controller='admin', + action='roles', + message=message, + status='error' ) ) + role = get_role( trans, id ) + if params.get( 'rename_role_button', False ): + old_name = role.name + new_name = util.restore_text( params.name ) + new_description = util.restore_text( params.description ) + if not new_name: + message = 'Enter a valid name' + status='error' + else: + existing_role = trans.sa_session.query( trans.app.model.Role ).filter( trans.app.model.Role.table.c.name==new_name ).first() + if existing_role and existing_role.id != role.id: + message = 'A role with that name already exists' + status = 'error' + else: + if not ( role.name == new_name and role.description == new_description ): + role.name = new_name + role.description = new_description + trans.sa_session.add( role ) + trans.sa_session.flush() + message = "Role '%s' has been renamed to '%s'" % ( old_name, new_name ) + return trans.response.send_redirect( web.url_for( controller='admin', + action='roles', + message=util.sanitize_text( message ), + status='done' ) ) + return trans.fill_template( '/admin/dataset_security/role/role_rename.mako', + role=role, + message=message, + status=status ) + @web.expose + @web.require_admin + def manage_users_and_groups_for_role( self, trans, **kwd ): + params = util.Params( kwd ) + message = util.restore_text( params.get( 'message', '' ) ) + status = params.get( 'status', 'done' ) + id = params.get( 'id', None ) + if not id: + message = "No role ids received for managing users and groups" + trans.response.send_redirect( web.url_for( controller='admin', + action='roles', + message=message, + status='error' ) ) + role = get_role( trans, id ) + if params.get( 'role_members_edit_button', False ): + in_users = [ trans.sa_session.query( trans.app.model.User ).get( x ) for x in util.listify( params.in_users ) ] + for ura in role.users: + user = trans.sa_session.query( trans.app.model.User ).get( ura.user_id ) + if user not in in_users: + # Delete DefaultUserPermissions for previously associated users that have been removed from the role + for dup in user.default_permissions: + if role == dup.role: + trans.sa_session.delete( dup ) + # Delete DefaultHistoryPermissions for previously associated users that have been removed from the role + for history in user.histories: + for dhp in history.default_permissions: + if role == dhp.role: + trans.sa_session.delete( dhp ) + trans.sa_session.flush() + in_groups = [ trans.sa_session.query( trans.app.model.Group ).get( x ) for x in util.listify( params.in_groups ) ] + trans.app.security_agent.set_entity_role_associations( roles=[ role ], users=in_users, groups=in_groups ) + trans.sa_session.refresh( role ) + message = "Role '%s' has been updated with %d associated users and %d associated groups" % ( role.name, len( in_users ), len( in_groups ) ) + trans.response.send_redirect( web.url_for( controller='admin', + action='roles', + message=util.sanitize_text( message ), + status=status ) ) + in_users = [] + out_users = [] + in_groups = [] + out_groups = [] + for user in trans.sa_session.query( trans.app.model.User ) \ + .filter( trans.app.model.User.table.c.deleted==False ) \ + .order_by( trans.app.model.User.table.c.email ): + if user in [ x.user for x in role.users ]: + in_users.append( ( user.id, user.email ) ) + else: + out_users.append( ( user.id, user.email ) ) + for group in trans.sa_session.query( trans.app.model.Group ) \ + .filter( trans.app.model.Group.table.c.deleted==False ) \ + .order_by( trans.app.model.Group.table.c.name ): + if group in [ x.group for x in role.groups ]: + in_groups.append( ( group.id, group.name ) ) + else: + out_groups.append( ( group.id, group.name ) ) + library_dataset_actions = {} + if trans.webapp.name == 'galaxy': + # Build a list of tuples that are LibraryDatasetDatasetAssociationss followed by a list of actions + # whose DatasetPermissions is associated with the Role + # [ ( LibraryDatasetDatasetAssociation [ action, action ] ) ] + for dp in role.dataset_actions: + for ldda in trans.sa_session.query( trans.app.model.LibraryDatasetDatasetAssociation ) \ + .filter( trans.app.model.LibraryDatasetDatasetAssociation.dataset_id==dp.dataset_id ): + root_found = False + folder_path = '' + folder = ldda.library_dataset.folder + while not root_found: + folder_path = '%s / %s' % ( folder.name, folder_path ) + if not folder.parent: + root_found = True + else: + folder = folder.parent + folder_path = '%s %s' % ( folder_path, ldda.name ) + library = trans.sa_session.query( trans.app.model.Library ) \ + .filter( trans.app.model.Library.table.c.root_folder_id == folder.id ) \ + .first() + if library not in library_dataset_actions: + library_dataset_actions[ library ] = {} + try: + library_dataset_actions[ library ][ folder_path ].append( dp.action ) + except: + library_dataset_actions[ library ][ folder_path ] = [ dp.action ] + return trans.fill_template( '/admin/dataset_security/role/role.mako', + role=role, + in_users=in_users, + out_users=out_users, + in_groups=in_groups, + out_groups=out_groups, + library_dataset_actions=library_dataset_actions, + message=message, + status=status ) + @web.expose + @web.require_admin + def mark_role_deleted( self, trans, **kwd ): + params = util.Params( kwd ) + id = kwd.get( 'id', None ) + if not id: + message = "No role ids received for deleting" + trans.response.send_redirect( web.url_for( controller='admin', + action='roles', + message=message, + status='error' ) ) + ids = util.listify( id ) + message = "Deleted %d roles: " % len( ids ) + for role_id in ids: + role = get_role( trans, role_id ) + role.deleted = True + trans.sa_session.add( role ) + trans.sa_session.flush() + message += " %s " % role.name + trans.response.send_redirect( web.url_for( controller='admin', + action='roles', + message=util.sanitize_text( message ), + status='done' ) ) + @web.expose + @web.require_admin + def undelete_role( self, trans, **kwd ): + params = util.Params( kwd ) + id = kwd.get( 'id', None ) + if not id: + message = "No role ids received for undeleting" + trans.response.send_redirect( web.url_for( controller='admin', + action='roles', + message=message, + status='error' ) ) + ids = util.listify( id ) + count = 0 + undeleted_roles = "" + for role_id in ids: + role = get_role( trans, role_id ) + if not role.deleted: + message = "Role '%s' has not been deleted, so it cannot be undeleted." % role.name + trans.response.send_redirect( web.url_for( controller='admin', + action='roles', + message=util.sanitize_text( message ), + status='error' ) ) + role.deleted = False + trans.sa_session.add( role ) + trans.sa_session.flush() + count += 1 + undeleted_roles += " %s" % role.name + message = "Undeleted %d roles: %s" % ( count, undeleted_roles ) + trans.response.send_redirect( web.url_for( controller='admin', + action='roles', + message=util.sanitize_text( message ), + status='done' ) ) + @web.expose + @web.require_admin + def purge_role( self, trans, **kwd ): + # This method should only be called for a Role that has previously been deleted. + # Purging a deleted Role deletes all of the following from the database: + # - UserRoleAssociations where role_id == Role.id + # - DefaultUserPermissions where role_id == Role.id + # - DefaultHistoryPermissions where role_id == Role.id + # - GroupRoleAssociations where role_id == Role.id + # - DatasetPermissionss where role_id == Role.id + params = util.Params( kwd ) + id = kwd.get( 'id', None ) + if not id: + message = "No role ids received for purging" + trans.response.send_redirect( web.url_for( controller='admin', + action='roles', + message=util.sanitize_text( message ), + status='error' ) ) + ids = util.listify( id ) + message = "Purged %d roles: " % len( ids ) + for role_id in ids: + role = get_role( trans, role_id ) + if not role.deleted: + message = "Role '%s' has not been deleted, so it cannot be purged." % role.name + trans.response.send_redirect( web.url_for( controller='admin', + action='roles', + message=util.sanitize_text( message ), + status='error' ) ) + # Delete UserRoleAssociations + for ura in role.users: + user = trans.sa_session.query( trans.app.model.User ).get( ura.user_id ) + # Delete DefaultUserPermissions for associated users + for dup in user.default_permissions: + if role == dup.role: + trans.sa_session.delete( dup ) + # Delete DefaultHistoryPermissions for associated users + for history in user.histories: + for dhp in history.default_permissions: + if role == dhp.role: + trans.sa_session.delete( dhp ) + trans.sa_session.delete( ura ) + # Delete GroupRoleAssociations + for gra in role.groups: + trans.sa_session.delete( gra ) + # Delete DatasetPermissionss + for dp in role.dataset_actions: + trans.sa_session.delete( dp ) + trans.sa_session.flush() + message += " %s " % role.name + trans.response.send_redirect( web.url_for( controller='admin', + action='roles', + message=util.sanitize_text( message ), + status='done' ) ) + + # Galaxy Group Stuff + @web.expose + @web.require_admin + def groups( self, trans, **kwargs ): + if 'operation' in kwargs: + operation = kwargs['operation'].lower() + if operation == "groups": + return self.group( trans, **kwargs ) + if operation == "create": + return self.create_group( trans, **kwargs ) + if operation == "delete": + return self.mark_group_deleted( trans, **kwargs ) + if operation == "undelete": + return self.undelete_group( trans, **kwargs ) + if operation == "purge": + return self.purge_group( trans, **kwargs ) + if operation == "manage users and roles": + return self.manage_users_and_roles_for_group( trans, **kwargs ) + if operation == "rename": + return self.rename_group( trans, **kwargs ) + # Render the list view + return self.group_list_grid( trans, **kwargs ) + @web.expose + @web.require_admin + def rename_group( self, trans, **kwd ): + params = util.Params( kwd ) + message = util.restore_text( params.get( 'message', '' ) ) + status = params.get( 'status', 'done' ) + id = params.get( 'id', None ) + if not id: + message = "No group ids received for renaming" + trans.response.send_redirect( web.url_for( controller='admin', + action='groups', + message=message, + status='error' ) ) + group = get_group( trans, id ) + if params.get( 'rename_group_button', False ): + old_name = group.name + new_name = util.restore_text( params.name ) + if not new_name: + message = 'Enter a valid name' + status = 'error' + else: + existing_group = trans.sa_session.query( trans.app.model.Group ).filter( trans.app.model.Group.table.c.name==new_name ).first() + if existing_group and existing_group.id != group.id: + message = 'A group with that name already exists' + status = 'error' + else: + if group.name != new_name: + group.name = new_name + trans.sa_session.add( group ) + trans.sa_session.flush() + message = "Group '%s' has been renamed to '%s'" % ( old_name, new_name ) + return trans.response.send_redirect( web.url_for( controller='admin', + action='groups', + message=util.sanitize_text( message ), + status='done' ) ) + return trans.fill_template( '/admin/dataset_security/group/group_rename.mako', + group=group, + message=message, + status=status ) + @web.expose + @web.require_admin + def manage_users_and_roles_for_group( self, trans, **kwd ): + params = util.Params( kwd ) + message = util.restore_text( params.get( 'message', '' ) ) + status = params.get( 'status', 'done' ) + group = get_group( trans, params.id ) + if params.get( 'group_roles_users_edit_button', False ): + in_roles = [ trans.sa_session.query( trans.app.model.Role ).get( x ) for x in util.listify( params.in_roles ) ] + in_users = [ trans.sa_session.query( trans.app.model.User ).get( x ) for x in util.listify( params.in_users ) ] + trans.app.security_agent.set_entity_group_associations( groups=[ group ], roles=in_roles, users=in_users ) + trans.sa_session.refresh( group ) + message += "Group '%s' has been updated with %d associated roles and %d associated users" % ( group.name, len( in_roles ), len( in_users ) ) + trans.response.send_redirect( web.url_for( controller='admin', + action='groups', + message=util.sanitize_text( message ), + status=status ) ) + in_roles = [] + out_roles = [] + in_users = [] + out_users = [] + for role in trans.sa_session.query(trans.app.model.Role ) \ + .filter( trans.app.model.Role.table.c.deleted==False ) \ + .order_by( trans.app.model.Role.table.c.name ): + if role in [ x.role for x in group.roles ]: + in_roles.append( ( role.id, role.name ) ) + else: + out_roles.append( ( role.id, role.name ) ) + for user in trans.sa_session.query( trans.app.model.User ) \ + .filter( trans.app.model.User.table.c.deleted==False ) \ + .order_by( trans.app.model.User.table.c.email ): + if user in [ x.user for x in group.users ]: + in_users.append( ( user.id, user.email ) ) + else: + out_users.append( ( user.id, user.email ) ) + message += 'Group %s is currently associated with %d roles and %d users' % ( group.name, len( in_roles ), len( in_users ) ) + return trans.fill_template( '/admin/dataset_security/group/group.mako', + group=group, + in_roles=in_roles, + out_roles=out_roles, + in_users=in_users, + out_users=out_users, + message=message, + status=status ) + @web.expose + @web.require_admin + def create_group( self, trans, **kwd ): + params = util.Params( kwd ) + message = util.restore_text( params.get( 'message', '' ) ) + status = params.get( 'status', 'done' ) + name = util.restore_text( params.get( 'name', '' ) ) + in_users = util.listify( params.get( 'in_users', [] ) ) + out_users = util.listify( params.get( 'out_users', [] ) ) + in_roles = util.listify( params.get( 'in_roles', [] ) ) + out_roles = util.listify( params.get( 'out_roles', [] ) ) + create_role_for_group = params.get( 'create_role_for_group', '' ) + create_role_for_group_checked = CheckboxField.is_checked( create_role_for_group ) + ok = True + if params.get( 'create_group_button', False ): + if not name: + message = "Enter a valid name." + status = 'error' + ok = False + elif trans.sa_session.query( trans.app.model.Group ).filter( trans.app.model.Group.table.c.name==name ).first(): + message = "Group names must be unique and a group with that name already exists, so choose another name." + status = 'error' + ok = False + else: + # Create the group + group = trans.app.model.Group( name=name ) + trans.sa_session.add( group ) + trans.sa_session.flush() + # Create the UserRoleAssociations + for user in [ trans.sa_session.query( trans.app.model.User ).get( x ) for x in in_users ]: + uga = trans.app.model.UserGroupAssociation( user, group ) + trans.sa_session.add( uga ) + # Create the GroupRoleAssociations + for role in [ trans.sa_session.query( trans.app.model.Role ).get( x ) for x in in_roles ]: + gra = trans.app.model.GroupRoleAssociation( group, role ) + trans.sa_session.add( gra ) + if create_role_for_group_checked: + # Create the role + role = trans.app.model.Role( name=name, description='Role for group %s' % name ) + trans.sa_session.add( role ) + # Associate the role with the group + gra = trans.model.GroupRoleAssociation( group, role ) + trans.sa_session.add( gra ) + num_in_roles = len( in_roles ) + 1 + else: + num_in_roles = len( in_roles ) + trans.sa_session.flush() + message = "Group '%s' has been created with %d associated users and %d associated roles. " \ + % ( group.name, len( in_users ), num_in_roles ) + if create_role_for_group_checked: + message += 'One of the roles associated with this group is the newly created role with the same name.' + trans.response.send_redirect( web.url_for( controller='admin', + action='groups', + message=util.sanitize_text( message ), + status='done' ) ) + + + if ok: + for user in trans.sa_session.query( trans.app.model.User ) \ + .filter( trans.app.model.User.table.c.deleted==False ) \ + .order_by( trans.app.model.User.table.c.email ): + out_users.append( ( user.id, user.email ) ) + for role in trans.sa_session.query( trans.app.model.Role ) \ + .filter( trans.app.model.Role.table.c.deleted==False ) \ + .order_by( trans.app.model.Role.table.c.name ): + out_roles.append( ( role.id, role.name ) ) + return trans.fill_template( '/admin/dataset_security/group/group_create.mako', + name=name, + in_users=in_users, + out_users=out_users, + in_roles=in_roles, + out_roles=out_roles, + create_role_for_group_checked=create_role_for_group_checked, + message=message, + status=status ) + @web.expose + @web.require_admin + def mark_group_deleted( self, trans, **kwd ): + params = util.Params( kwd ) + id = params.get( 'id', None ) + if not id: + message = "No group ids received for marking deleted" + trans.response.send_redirect( web.url_for( controller='admin', + action='groups', + message=message, + status='error' ) ) + ids = util.listify( id ) + message = "Deleted %d groups: " % len( ids ) + for group_id in ids: + group = get_group( trans, group_id ) + group.deleted = True + trans.sa_session.add( group ) + trans.sa_session.flush() + message += " %s " % group.name + trans.response.send_redirect( web.url_for( controller='admin', + action='groups', + message=util.sanitize_text( message ), + status='done' ) ) + @web.expose + @web.require_admin + def undelete_group( self, trans, **kwd ): + params = util.Params( kwd ) + id = kwd.get( 'id', None ) + if not id: + message = "No group ids received for undeleting" + trans.response.send_redirect( web.url_for( controller='admin', + action='groups', + message=message, + status='error' ) ) + ids = util.listify( id ) + count = 0 + undeleted_groups = "" + for group_id in ids: + group = get_group( trans, group_id ) + if not group.deleted: + message = "Group '%s' has not been deleted, so it cannot be undeleted." % group.name + trans.response.send_redirect( web.url_for( controller='admin', + action='groups', + message=util.sanitize_text( message ), + status='error' ) ) + group.deleted = False + trans.sa_session.add( group ) + trans.sa_session.flush() + count += 1 + undeleted_groups += " %s" % group.name + message = "Undeleted %d groups: %s" % ( count, undeleted_groups ) + trans.response.send_redirect( web.url_for( controller='admin', + action='groups', + message=util.sanitize_text( message ), + status='done' ) ) + @web.expose + @web.require_admin + def purge_group( self, trans, **kwd ): + # This method should only be called for a Group that has previously been deleted. + # Purging a deleted Group simply deletes all UserGroupAssociations and GroupRoleAssociations. + params = util.Params( kwd ) + id = kwd.get( 'id', None ) + if not id: + message = "No group ids received for purging" + trans.response.send_redirect( web.url_for( controller='admin', + action='groups', + message=util.sanitize_text( message ), + status='error' ) ) + ids = util.listify( id ) + message = "Purged %d groups: " % len( ids ) + for group_id in ids: + group = get_group( trans, group_id ) + if not group.deleted: + # We should never reach here, but just in case there is a bug somewhere... + message = "Group '%s' has not been deleted, so it cannot be purged." % group.name + trans.response.send_redirect( web.url_for( controller='admin', + action='groups', + message=util.sanitize_text( message ), + status='error' ) ) + # Delete UserGroupAssociations + for uga in group.users: + trans.sa_session.delete( uga ) + # Delete GroupRoleAssociations + for gra in group.roles: + trans.sa_session.delete( gra ) + trans.sa_session.flush() + message += " %s " % group.name + trans.response.send_redirect( web.url_for( controller='admin', + action='groups', + message=util.sanitize_text( message ), + status='done' ) ) + + # Galaxy User Stuff + @web.expose + @web.require_admin + def create_new_user( self, trans, **kwd ): + return trans.response.send_redirect( web.url_for( controller='user', + action='create', + cntrller='admin' ) ) + @web.expose + @web.require_admin + def reset_user_password( self, trans, **kwd ): + user_id = kwd.get( 'id', None ) + if not user_id: + message = "No users received for resetting passwords." + trans.response.send_redirect( web.url_for( controller='admin', + action='users', + message=message, + status='error' ) ) + user_ids = util.listify( user_id ) + if 'reset_user_password_button' in kwd: + message = '' + status = '' + for user_id in user_ids: + user = get_user( trans, user_id ) + password = kwd.get( 'password', None ) + confirm = kwd.get( 'confirm' , None ) + if len( password ) < 6: + message = "Use a password of at least 6 characters." + status = 'error' + break + elif password != confirm: + message = "Passwords do not match." + status = 'error' + break + else: + user.set_password_cleartext( password ) + trans.sa_session.add( user ) + trans.sa_session.flush() + if not message and not status: + message = "Passwords reset for %d %s." % ( len( user_ids ), inflector.cond_plural( len( user_ids ), 'user' ) ) + status = 'done' + trans.response.send_redirect( web.url_for( controller='admin', + action='users', + message=util.sanitize_text( message ), + status=status ) ) + users = [ get_user( trans, user_id ) for user_id in user_ids ] + if len( user_ids ) > 1: + user_id = ','.join( user_ids ) + return trans.fill_template( '/admin/user/reset_password.mako', + id=user_id, + users=users, + password='', + confirm='' ) + @web.expose + @web.require_admin + def mark_user_deleted( self, trans, **kwd ): + id = kwd.get( 'id', None ) + if not id: + message = "No user ids received for deleting" + trans.response.send_redirect( web.url_for( controller='admin', + action='users', + message=message, + status='error' ) ) + ids = util.listify( id ) + message = "Deleted %d users: " % len( ids ) + for user_id in ids: + user = get_user( trans, user_id ) + user.deleted = True + trans.sa_session.add( user ) + trans.sa_session.flush() + message += " %s " % user.email + trans.response.send_redirect( web.url_for( controller='admin', + action='users', + message=util.sanitize_text( message ), + status='done' ) ) + @web.expose + @web.require_admin + def undelete_user( self, trans, **kwd ): + id = kwd.get( 'id', None ) + if not id: + message = "No user ids received for undeleting" + trans.response.send_redirect( web.url_for( controller='admin', + action='users', + message=message, + status='error' ) ) + ids = util.listify( id ) + count = 0 + undeleted_users = "" + for user_id in ids: + user = get_user( trans, user_id ) + if not user.deleted: + message = "User '%s' has not been deleted, so it cannot be undeleted." % user.email + trans.response.send_redirect( web.url_for( controller='admin', + action='users', + message=util.sanitize_text( message ), + status='error' ) ) + user.deleted = False + trans.sa_session.add( user ) + trans.sa_session.flush() + count += 1 + undeleted_users += " %s" % user.email + message = "Undeleted %d users: %s" % ( count, undeleted_users ) + trans.response.send_redirect( web.url_for( controller='admin', + action='users', + message=util.sanitize_text( message ), + status='done' ) ) + @web.expose + @web.require_admin + def purge_user( self, trans, **kwd ): + # This method should only be called for a User that has previously been deleted. + # We keep the User in the database ( marked as purged ), and stuff associated + # with the user's private role in case we want the ability to unpurge the user + # some time in the future. + # Purging a deleted User deletes all of the following: + # - History where user_id = User.id + # - HistoryDatasetAssociation where history_id = History.id + # - Dataset where HistoryDatasetAssociation.dataset_id = Dataset.id + # - UserGroupAssociation where user_id == User.id + # - UserRoleAssociation where user_id == User.id EXCEPT FOR THE PRIVATE ROLE + # - UserAddress where user_id == User.id + # Purging Histories and Datasets must be handled via the cleanup_datasets.py script + id = kwd.get( 'id', None ) + if not id: + message = "No user ids received for purging" + trans.response.send_redirect( web.url_for( controller='admin', + action='users', + message=util.sanitize_text( message ), + status='error' ) ) + ids = util.listify( id ) + message = "Purged %d users: " % len( ids ) + for user_id in ids: + user = get_user( trans, user_id ) + if not user.deleted: + # We should never reach here, but just in case there is a bug somewhere... + message = "User '%s' has not been deleted, so it cannot be purged." % user.email + trans.response.send_redirect( web.url_for( controller='admin', + action='users', + message=util.sanitize_text( message ), + status='error' ) ) + private_role = trans.app.security_agent.get_private_user_role( user ) + # Delete History + for h in user.active_histories: + trans.sa_session.refresh( h ) + for hda in h.active_datasets: + # Delete HistoryDatasetAssociation + d = trans.sa_session.query( trans.app.model.Dataset ).get( hda.dataset_id ) + # Delete Dataset + if not d.deleted: + d.deleted = True + trans.sa_session.add( d ) + hda.deleted = True + trans.sa_session.add( hda ) + h.deleted = True + trans.sa_session.add( h ) + # Delete UserGroupAssociations + for uga in user.groups: + trans.sa_session.delete( uga ) + # Delete UserRoleAssociations EXCEPT FOR THE PRIVATE ROLE + for ura in user.roles: + if ura.role_id != private_role.id: + trans.sa_session.delete( ura ) + # Delete UserAddresses + for address in user.addresses: + trans.sa_session.delete( address ) + # Purge the user + user.purged = True + trans.sa_session.add( user ) + trans.sa_session.flush() + message += "%s " % user.email + trans.response.send_redirect( web.url_for( controller='admin', + action='users', + message=util.sanitize_text( message ), + status='done' ) ) + @web.expose + @web.require_admin + def users( self, trans, **kwd ): + if 'operation' in kwd: + operation = kwd['operation'].lower() + if operation == "roles": + return self.user( trans, **kwd ) + elif operation == "reset password": + return self.reset_user_password( trans, **kwd ) + elif operation == "delete": + return self.mark_user_deleted( trans, **kwd ) + elif operation == "undelete": + return self.undelete_user( trans, **kwd ) + elif operation == "purge": + return self.purge_user( trans, **kwd ) + elif operation == "create": + return self.create_new_user( trans, **kwd ) + elif operation == "information": + user_id = kwd.get( 'id', None ) + if not user_id: + kwd[ 'message' ] = util.sanitize_text( "Invalid user id (%s) received" % str( user_id ) ) + kwd[ 'status' ] = 'error' + else: + return trans.response.send_redirect( web.url_for( controller='user', + action='manage_user_info', + cntrller='admin', + **kwd ) ) + elif operation == "manage roles and groups": + return self.manage_roles_and_groups_for_user( trans, **kwd ) + if trans.app.config.allow_user_deletion: + if self.delete_operation not in self.user_list_grid.operations: + self.user_list_grid.operations.append( self.delete_operation ) + if self.undelete_operation not in self.user_list_grid.operations: + self.user_list_grid.operations.append( self.undelete_operation ) + if self.purge_operation not in self.user_list_grid.operations: + self.user_list_grid.operations.append( self.purge_operation ) + # Render the list view + return self.user_list_grid( trans, **kwd ) + @web.expose + @web.require_admin + def name_autocomplete_data( self, trans, q=None, limit=None, timestamp=None ): + """Return autocomplete data for user emails""" + ac_data = "" + for user in trans.sa_session.query( User ).filter_by( deleted=False ).filter( func.lower( User.email ).like( q.lower() + "%" ) ): + ac_data = ac_data + user.email + "\n" + return ac_data + @web.expose + @web.require_admin + def manage_roles_and_groups_for_user( self, trans, **kwd ): + user_id = kwd.get( 'id', None ) + message = '' + status = '' + if not user_id: + message += "Invalid user id (%s) received" % str( user_id ) + trans.response.send_redirect( web.url_for( controller='admin', + action='users', + message=util.sanitize_text( message ), + status='error' ) ) + user = get_user( trans, user_id ) + private_role = trans.app.security_agent.get_private_user_role( user ) + if kwd.get( 'user_roles_groups_edit_button', False ): + # Make sure the user is not dis-associating himself from his private role + out_roles = kwd.get( 'out_roles', [] ) + if out_roles: + out_roles = [ trans.sa_session.query( trans.app.model.Role ).get( x ) for x in util.listify( out_roles ) ] + if private_role in out_roles: + message += "You cannot eliminate a user's private role association. " + status = 'error' + in_roles = kwd.get( 'in_roles', [] ) + if in_roles: + in_roles = [ trans.sa_session.query( trans.app.model.Role ).get( x ) for x in util.listify( in_roles ) ] + out_groups = kwd.get( 'out_groups', [] ) + if out_groups: + out_groups = [ trans.sa_session.query( trans.app.model.Group ).get( x ) for x in util.listify( out_groups ) ] + in_groups = kwd.get( 'in_groups', [] ) + if in_groups: + in_groups = [ trans.sa_session.query( trans.app.model.Group ).get( x ) for x in util.listify( in_groups ) ] + if in_roles: + trans.app.security_agent.set_entity_user_associations( users=[ user ], roles=in_roles, groups=in_groups ) + trans.sa_session.refresh( user ) + message += "User '%s' has been updated with %d associated roles and %d associated groups (private roles are not displayed)" % \ + ( user.email, len( in_roles ), len( in_groups ) ) + trans.response.send_redirect( web.url_for( controller='admin', + action='users', + message=util.sanitize_text( message ), + status='done' ) ) + in_roles = [] + out_roles = [] + in_groups = [] + out_groups = [] + for role in trans.sa_session.query( trans.app.model.Role ).filter( trans.app.model.Role.table.c.deleted==False ) \ + .order_by( trans.app.model.Role.table.c.name ): + if role in [ x.role for x in user.roles ]: + in_roles.append( ( role.id, role.name ) ) + elif role.type != trans.app.model.Role.types.PRIVATE: + # There is a 1 to 1 mapping between a user and a PRIVATE role, so private roles should + # not be listed in the roles form fields, except for the currently selected user's private + # role, which should always be in in_roles. The check above is added as an additional + # precaution, since for a period of time we were including private roles in the form fields. + out_roles.append( ( role.id, role.name ) ) + for group in trans.sa_session.query( trans.app.model.Group ).filter( trans.app.model.Group.table.c.deleted==False ) \ + .order_by( trans.app.model.Group.table.c.name ): + if group in [ x.group for x in user.groups ]: + in_groups.append( ( group.id, group.name ) ) + else: + out_groups.append( ( group.id, group.name ) ) + message += "User '%s' is currently associated with %d roles and is a member of %d groups" % \ + ( user.email, len( in_roles ), len( in_groups ) ) + if not status: + status = 'done' + return trans.fill_template( '/admin/user/user.mako', + user=user, + in_roles=in_roles, + out_roles=out_roles, + in_groups=in_groups, + out_groups=out_groups, + message=message, + status=status ) + @web.expose + @web.require_admin + def memdump( self, trans, ids = 'None', sorts = 'None', pages = 'None', new_id = None, new_sort = None, **kwd ): + if self.app.memdump is None: + return trans.show_error_message( "Memdump is not enabled (set <code>use_memdump = True</code> in universe_wsgi.ini)" ) + heap = self.app.memdump.get() + p = util.Params( kwd ) + msg = None + if p.dump: + heap = self.app.memdump.get( update = True ) + msg = "Heap dump complete" + elif p.setref: + self.app.memdump.setref() + msg = "Reference point set (dump to see delta from this point)" + ids = ids.split( ',' ) + sorts = sorts.split( ',' ) + if new_id is not None: + ids.append( new_id ) + sorts.append( 'None' ) + elif new_sort is not None: + sorts[-1] = new_sort + breadcrumb = "<a href='%s' class='breadcrumb'>heap</a>" % web.url_for() + # new lists so we can assemble breadcrumb links + new_ids = [] + new_sorts = [] + for id, sort in zip( ids, sorts ): + new_ids.append( id ) + if id != 'None': + breadcrumb += "<a href='%s' class='breadcrumb'>[%s]</a>" % ( web.url_for( ids=','.join( new_ids ), sorts=','.join( new_sorts ) ), id ) + heap = heap[int(id)] + new_sorts.append( sort ) + if sort != 'None': + breadcrumb += "<a href='%s' class='breadcrumb'>.by('%s')</a>" % ( web.url_for( ids=','.join( new_ids ), sorts=','.join( new_sorts ) ), sort ) + heap = heap.by( sort ) + ids = ','.join( new_ids ) + sorts = ','.join( new_sorts ) + if p.theone: + breadcrumb += ".theone" + heap = heap.theone + return trans.fill_template( '/admin/memdump.mako', heap = heap, ids = ids, sorts = sorts, breadcrumb = breadcrumb, msg = msg ) + + @web.expose + @web.require_admin + def jobs( self, trans, stop = [], stop_msg = None, cutoff = 180, job_lock = None, ajl_submit = None, **kwd ): + deleted = [] + msg = None + status = None + if self.app.config.job_manager != self.app.config.server_name: + return trans.show_error_message( 'This Galaxy instance (%s) is not the job manager (%s). If using multiple servers, please directly access the job manager instance to manage jobs.' % (self.app.config.server_name, self.app.config.job_manager) ) + job_ids = util.listify( stop ) + if job_ids and stop_msg in [ None, '' ]: + msg = 'Please enter an error message to display to the user describing why the job was terminated' + status = 'error' + elif job_ids: + if stop_msg[-1] not in string.punctuation: + stop_msg += '.' + for job_id in job_ids: + trans.app.job_manager.job_stop_queue.put( job_id, error_msg="This job was stopped by an administrator: %s For more information or help" % stop_msg ) + deleted.append( str( job_id ) ) + if deleted: + msg = 'Queued job' + if len( deleted ) > 1: + msg += 's' + msg += ' for deletion: ' + msg += ', '.join( deleted ) + status = 'done' + if ajl_submit: + if job_lock == 'on': + trans.app.job_manager.job_queue.job_lock = True + else: + trans.app.job_manager.job_queue.job_lock = False + cutoff_time = datetime.utcnow() - timedelta( seconds=int( cutoff ) ) + jobs = trans.sa_session.query( trans.app.model.Job ) \ + .filter( and_( trans.app.model.Job.table.c.update_time < cutoff_time, + or_( trans.app.model.Job.state == trans.app.model.Job.states.NEW, + trans.app.model.Job.state == trans.app.model.Job.states.QUEUED, + trans.app.model.Job.state == trans.app.model.Job.states.RUNNING, + trans.app.model.Job.state == trans.app.model.Job.states.UPLOAD ) ) ) \ + .order_by( trans.app.model.Job.table.c.update_time.desc() ) + last_updated = {} + for job in jobs: + delta = datetime.utcnow() - job.update_time + if delta > timedelta( minutes=60 ): + last_updated[job.id] = '%s hours' % int( delta.seconds / 60 / 60 ) + else: + last_updated[job.id] = '%s minutes' % int( delta.seconds / 60 ) + return trans.fill_template( '/admin/jobs.mako', + jobs = jobs, + last_updated = last_updated, + cutoff = cutoff, + msg = msg, + status = status, + job_lock = trans.app.job_manager.job_queue.job_lock ) + +## ---- Utility methods ------------------------------------------------------- + +def get_ids_of_tool_shed_repositories_being_installed( trans, as_string=False ): + installing_repository_ids = [] + new_status = trans.model.ToolShedRepository.installation_status.NEW + cloning_status = trans.model.ToolShedRepository.installation_status.CLONING + setting_tool_versions_status = trans.model.ToolShedRepository.installation_status.SETTING_TOOL_VERSIONS + installing_dependencies_status = trans.model.ToolShedRepository.installation_status.INSTALLING_TOOL_DEPENDENCIES + loading_datatypes_status = trans.model.ToolShedRepository.installation_status.LOADING_PROPRIETARY_DATATYPES + for tool_shed_repository in trans.sa_session.query( trans.model.ToolShedRepository ) \ + .filter( or_( trans.model.ToolShedRepository.status == new_status, + trans.model.ToolShedRepository.status == cloning_status, + trans.model.ToolShedRepository.status == setting_tool_versions_status, + trans.model.ToolShedRepository.status == installing_dependencies_status, + trans.model.ToolShedRepository.status == loading_datatypes_status ) ): + installing_repository_ids.append( trans.security.encode_id( tool_shed_repository.id ) ) + if as_string: + return ','.join( installing_repository_ids ) + return installing_repository_ids + +def get_user( trans, user_id ): + """Get a User from the database by id.""" + user = trans.sa_session.query( trans.model.User ).get( trans.security.decode_id( user_id ) ) + if not user: + return trans.show_error_message( "User not found for id (%s)" % str( user_id ) ) + return user +def get_user_by_username( trans, username ): + """Get a user from the database by username""" + # TODO: Add exception handling here. + return trans.sa_session.query( trans.model.User ) \ + .filter( trans.model.User.table.c.username == username ) \ + .one() +def get_role( trans, id ): + """Get a Role from the database by id.""" + # Load user from database + id = trans.security.decode_id( id ) + role = trans.sa_session.query( trans.model.Role ).get( id ) + if not role: + return trans.show_error_message( "Role not found for id (%s)" % str( id ) ) + return role +def get_group( trans, id ): + """Get a Group from the database by id.""" + # Load user from database + id = trans.security.decode_id( id ) + group = trans.sa_session.query( trans.model.Group ).get( id ) + if not group: + return trans.show_error_message( "Group not found for id (%s)" % str( id ) ) + return group +def get_quota( trans, id ): + """Get a Quota from the database by id.""" + # Load user from database + id = trans.security.decode_id( id ) + quota = trans.sa_session.query( trans.model.Quota ).get( id ) + return quota \ No newline at end of file diff -r 203e3e1592439dcb8c0eb890545ed38a66f08f2c -r 2ca0e99d6d6d940af0712e9c56b9f238fd59635c lib/galaxy/web/framework/__init__.py --- a/lib/galaxy/web/framework/__init__.py +++ b/lib/galaxy/web/framework/__init__.py @@ -607,7 +607,7 @@ Update the session cookie to match the current session. """ self.set_cookie( self.security.encode_guid( self.galaxy_session.session_key ), name=name, path=self.app.config.cookie_path ) - def handle_user_login( self, user, webapp ): + def handle_user_login( self, user ): """ Login a new user (possibly newly created) - create a new session @@ -621,7 +621,7 @@ prev_galaxy_session.is_valid = False # Define a new current_session self.galaxy_session = self.__create_new_session( prev_galaxy_session, user ) - if webapp == 'galaxy': + if self.webapp.name == 'galaxy': cookie_name = 'galaxysession' # Associated the current user's last accessed history (if exists) with their new session history = None diff -r 203e3e1592439dcb8c0eb890545ed38a66f08f2c -r 2ca0e99d6d6d940af0712e9c56b9f238fd59635c lib/galaxy/web/framework/helpers/grids.py --- a/lib/galaxy/web/framework/helpers/grids.py +++ b/lib/galaxy/web/framework/helpers/grids.py @@ -53,7 +53,8 @@ def __call__( self, trans, **kwargs ): # Get basics. - webapp = get_webapp( trans, **kwargs ) + # FIXME: pretty sure this is only here to pass along, can likely be eliminated + webapp = trans.webapp.name status = kwargs.get( 'status', None ) message = kwargs.get( 'message', None ) # Build a base filter and sort key that is the combination of the saved state and defaults. diff -r 203e3e1592439dcb8c0eb890545ed38a66f08f2c -r 2ca0e99d6d6d940af0712e9c56b9f238fd59635c lib/galaxy/webapps/community/controllers/admin.py --- a/lib/galaxy/webapps/community/controllers/admin.py +++ b/lib/galaxy/webapps/community/controllers/admin.py @@ -1,4 +1,5 @@ from galaxy.web.base.controller import * +from galaxy.web.base.controllers.admin import Admin from galaxy.webapps.community import model from galaxy.model.orm import * from galaxy.web.framework.helpers import time_ago, iff, grids diff -r 203e3e1592439dcb8c0eb890545ed38a66f08f2c -r 2ca0e99d6d6d940af0712e9c56b9f238fd59635c lib/galaxy/webapps/galaxy/api/quotas.py --- a/lib/galaxy/webapps/galaxy/api/quotas.py +++ b/lib/galaxy/webapps/galaxy/api/quotas.py @@ -2,7 +2,8 @@ API operations on Quota objects. """ import logging -from galaxy.web.base.controller import BaseAPIController, Admin, UsesQuotaMixin, url_for +from galaxy.web.base.controller import BaseAPIController, UsesQuotaMixin, url_for +from galaxy.web.base.controllers.admin import Admin from galaxy import web, util from elementtree.ElementTree import XML diff -r 203e3e1592439dcb8c0eb890545ed38a66f08f2c -r 2ca0e99d6d6d940af0712e9c56b9f238fd59635c lib/galaxy/webapps/galaxy/controllers/admin.py --- a/lib/galaxy/webapps/galaxy/controllers/admin.py +++ b/lib/galaxy/webapps/galaxy/controllers/admin.py @@ -1,4 +1,5 @@ from galaxy.web.base.controller import * +from galaxy.web.base.controllers.admin import Admin from galaxy import model from galaxy.model.orm import * from galaxy.web.framework.helpers import time_ago, iff, grids diff -r 203e3e1592439dcb8c0eb890545ed38a66f08f2c -r 2ca0e99d6d6d940af0712e9c56b9f238fd59635c lib/galaxy/webapps/galaxy/controllers/user.py --- a/lib/galaxy/webapps/galaxy/controllers/user.py +++ b/lib/galaxy/webapps/galaxy/controllers/user.py @@ -14,7 +14,7 @@ from galaxy.security.validate_user_input import validate_email, validate_publicname, validate_password, transform_publicname from galaxy.util.json import from_json_string, to_json_string from galaxy.web import url_for -from galaxy.web.base.controller import BaseUIController, UsesFormDefinitionsMixin, get_webapp +from galaxy.web.base.controller import BaseUIController, UsesFormDefinitionsMixin from galaxy.web.form_builder import CheckboxField, build_select_field from galaxy.web.framework.helpers import time_ago, grids @@ -49,10 +49,10 @@ installed_len_files = None @web.expose - def index( self, trans, cntrller, webapp='galaxy', **kwd ): - return trans.fill_template( '/user/index.mako', cntrller=cntrller, webapp=webapp ) + def index( self, trans, cntrller, **kwd ): + return trans.fill_template( '/user/index.mako', cntrller=cntrller ) @web.expose - def openid_auth( self, trans, webapp='galaxy', **kwd ): + def openid_auth( self, trans, **kwd ): '''Handles user request to access an OpenID provider''' if not trans.app.config.enable_openid: return trans.show_error_message( 'OpenID authentication is not enabled in this instance of Galaxy' ) @@ -102,7 +102,7 @@ message=message, status='error' ) ) @web.expose - def openid_process( self, trans, webapp='galaxy', **kwd ): + def openid_process( self, trans, **kwd ): '''Handle's response from OpenID Providers''' if not trans.app.config.enable_openid: return trans.show_error_message( 'OpenID authentication is not enabled in this instance of Galaxy' ) @@ -178,7 +178,7 @@ message=message, status=status ) ) elif user_openid.user: - trans.handle_user_login( user_openid.user, webapp ) + trans.handle_user_login( user_openid.user ) trans.log_event( "User logged in via OpenID: %s" % display_identifier ) openid_provider_obj.post_authentication( trans, trans.app.openid_manager, info ) if not redirect: @@ -222,7 +222,7 @@ message=message, status=status ) ) @web.expose - def openid_associate( self, trans, cntrller='user', webapp='galaxy', **kwd ): + def openid_associate( self, trans, cntrller='user', **kwd ): '''Associates a user with an OpenID log in''' if not trans.app.config.enable_openid: return trans.show_error_message( 'OpenID authentication is not enabled in this instance of Galaxy' ) @@ -241,7 +241,7 @@ elif is_admin: return trans.show_error_message( 'Associating OpenIDs with accounts cannot be done by administrators.' ) if kwd.get( 'login_button', False ): - message, status, user, success = self.__validate_login( trans, webapp, **kwd ) + message, status, user, success = self.__validate_login( trans, **kwd ) if success: openid_objs = [] for openid in openids: @@ -285,7 +285,7 @@ error = 'User registration is disabled. Please contact your Galaxy administrator for an account.' else: # Check email and password validity - error = self.__validate( trans, params, email, password, confirm, username, webapp ) + error = self.__validate( trans, params, email, password, confirm, username ) if not error: # all the values are valid message, status, user, success = self.__register( trans, @@ -330,7 +330,7 @@ else: message = error status = 'error' - if webapp == 'galaxy': + 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: @@ -342,7 +342,6 @@ user_type_form_definition = None widgets = [] return trans.fill_template( '/user/openid_associate.mako', - webapp=webapp, cntrller=cntrller, email=email, password='', @@ -362,7 +361,7 @@ openids=openids ) @web.expose @web.require_login( 'manage OpenIDs' ) - def openid_disassociate( self, trans, webapp='galaxy', **kwd ): + def openid_disassociate( self, trans, **kwd ): '''Disassociates a user with an OpenID''' if not trans.app.config.enable_openid: return trans.show_error_message( 'OpenID authentication is not enabled in this instance of Galaxy' ) @@ -404,7 +403,7 @@ @web.expose @web.require_login( 'manage OpenIDs' ) - def openid_manage( self, trans, webapp='galaxy', **kwd ): + def openid_manage( self, trans, **kwd ): '''Manage OpenIDs for user''' if not trans.app.config.enable_openid: return trans.show_error_message( 'OpenID authentication is not enabled in this instance of Galaxy' ) @@ -421,7 +420,7 @@ return self.user_openid_grid( trans, **kwd ) @web.expose - def login( self, trans, webapp='galaxy', redirect_url='', refresh_frames=[], **kwd ): + def login( self, trans, redirect_url='', refresh_frames=[], **kwd ): '''Handle Galaxy Log in''' redirect = kwd.get( 'redirect', trans.request.referer ).strip() use_panels = util.string_as_bool( kwd.get( 'use_panels', False ) ) @@ -430,16 +429,13 @@ header = '' user = None email = kwd.get( 'email', '' ) - #Sanitize webapp login here, once, since it can be reflected to the user in messages/etc. - #Only text is valid. - webapp = util.sanitize_text(webapp) if kwd.get( 'login_button', False ): - if webapp == 'galaxy' and not refresh_frames: + if trans.webapp.name == 'galaxy' and not refresh_frames: if trans.app.config.require_login: refresh_frames = [ 'masthead', 'history', 'tools' ] else: refresh_frames = [ 'masthead', 'history' ] - message, status, user, success = self.__validate_login( trans, webapp, **kwd ) + message, status, user, success = self.__validate_login( trans, **kwd ) if success and redirect and not redirect.startswith( trans.request.base + url_for( controller='user', action='logout' ) ): redirect_url = redirect elif success: @@ -447,18 +443,17 @@ if not user and trans.app.config.require_login: if trans.app.config.allow_user_creation: create_account_str = " If you don't already have an account, <a href='%s'>you may create one</a>." % \ - web.url_for( action='create', cntrller='user', webapp=webapp ) - if webapp == 'galaxy': + web.url_for( action='create', cntrller='user' ) + if trans.webapp.name == 'galaxy': header = require_login_template % ( "Galaxy instance", create_account_str ) else: header = require_login_template % ( "Galaxy tool shed", create_account_str ) else: - if webapp == 'galaxy': + if trans.webapp.name == 'galaxy': header = require_login_template % ( "Galaxy instance", "" ) else: header = require_login_template % ( "Galaxy tool shed", "" ) return trans.fill_template( '/user/login.mako', - webapp=webapp, email=email, header=header, use_panels=use_panels, @@ -469,7 +464,7 @@ status=status, openid_providers=trans.app.openid_providers, active_view="user" ) - def __validate_login( self, trans, webapp='galaxy', **kwd ): + def __validate_login( self, trans, **kwd ): message = kwd.get( 'message', '' ) status = kwd.get( 'status', 'done' ) email = kwd.get( 'email', '' ) @@ -490,8 +485,8 @@ message = "Invalid password" status = 'error' else: - trans.handle_user_login( user, webapp ) - if webapp == 'galaxy': + trans.handle_user_login( user ) + if trans.webapp.name == 'galaxy': trans.log_event( "User logged in" ) message = 'You are now logged in as %s.<br>You can <a target="_top" href="%s">go back to the page you were visiting</a> or <a target="_top" href="%s">go to the home page</a>.' % \ ( user.email, redirect, url_for( '/' ) ) @@ -501,8 +496,8 @@ return ( message, status, user, success ) @web.expose - def logout( self, trans, webapp='galaxy', logout_all=False ): - if webapp == 'galaxy': + def logout( self, trans, logout_all=False ): + if trans.webapp.name == 'galaxy': if trans.app.config.require_login: refresh_frames = [ 'masthead', 'history', 'tools' ] else: @@ -515,7 +510,6 @@ message = 'You have been logged out.<br>You can log in again, <a target="_top" href="%s">go back to the page you were visiting</a> or <a target="_top" href="%s">go to the home page</a>.' % \ ( trans.request.referer, url_for( '/' ) ) return trans.fill_template( '/user/logout.mako', - webapp=webapp, refresh_frames=refresh_frames, message=message, status='done', @@ -526,7 +520,6 @@ params = util.Params( kwd ) message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) - webapp = get_webapp( trans, **kwd ) use_panels = util.string_as_bool( kwd.get( 'use_panels', True ) ) email = util.restore_text( params.get( 'email', '' ) ) # Do not sanitize passwords, so take from kwd @@ -543,7 +536,7 @@ status = 'error' else: if not refresh_frames: - if webapp == 'galaxy': + if trans.webapp.name == 'galaxy': if trans.app.config.require_login: refresh_frames = [ 'masthead', 'history', 'tools' ] else: @@ -553,19 +546,19 @@ # Create the user, save all the user info and login to Galaxy if params.get( 'create_user_button', False ): # Check email and password validity - message = self.__validate( trans, params, email, password, confirm, username, webapp ) + message = self.__validate( trans, params, email, password, confirm, username ) if not message: # All the values are valid message, status, user, success = self.__register( trans, cntrller, subscribe_checked, **kwd ) - if webapp == 'community': + if trans.webapp.name == 'community': redirect_url = url_for( '/' ) if success and not is_admin: # The handle_user_login() method has a call to the history_set_default_permissions() method # (needed when logging in with a history), user needs to have default permissions set before logging in - trans.handle_user_login( user, webapp ) + trans.handle_user_login( user ) trans.log_event( "User created a new account" ) trans.log_event( "User logged in" ) if success and is_admin: @@ -577,7 +570,7 @@ status=status ) ) else: status = 'error' - if webapp == 'galaxy': + 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: @@ -596,7 +589,6 @@ user_type_fd_id_select_field=user_type_fd_id_select_field, user_type_form_definition=user_type_form_definition, widgets=widgets, - webapp=webapp, use_panels=use_panels, redirect=redirect, redirect_url=redirect_url, @@ -608,7 +600,6 @@ email = util.restore_text( kwd.get( 'email', '' ) ) password = kwd.get( 'password', '' ) username = util.restore_text( kwd.get( 'username', '' ) ) - webapp = get_webapp( trans, **kwd ) status = kwd.get( 'status', 'done' ) is_admin = cntrller == 'admin' and trans.user_is_admin() user = trans.app.model.User( email=email ) @@ -618,7 +609,7 @@ trans.sa_session.flush() trans.app.security_agent.create_private_user_role( user ) error = '' - if webapp == 'galaxy': + if trans.webapp.name == 'galaxy': # We set default user permissions, before we log in and set the default history permissions trans.app.security_agent.user_set_default_permissions( user, default_access_private=trans.app.config.new_user_dataset_access_role_default_private ) @@ -654,7 +645,7 @@ if not error and not is_admin: # The handle_user_login() method has a call to the history_set_default_permissions() method # (needed when logging in with a history), user needs to have default permissions set before logging in - trans.handle_user_login( user, webapp ) + trans.handle_user_login( user ) trans.log_event( "User created a new account" ) trans.log_event( "User logged in" ) elif not error: @@ -706,14 +697,13 @@ user = trans.user if not user: raise AssertionError, "The user id (%s) is not valid" % str( user_id ) - webapp = get_webapp( trans, **kwd ) email = util.restore_text( params.get( 'email', user.email ) ) username = util.restore_text( params.get( 'username', '' ) ) if not username: username = user.username message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) - if webapp == 'galaxy': + 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: @@ -742,7 +732,6 @@ widgets=widgets, addresses=addresses, show_filter=show_filter, - webapp=webapp, message=message, status=status ) else: @@ -751,7 +740,6 @@ user=user, email=email, username=username, - webapp=webapp, message=message, status=status ) @@ -761,7 +749,6 @@ def edit_username( self, trans, cntrller, **kwd ): params = util.Params( kwd ) is_admin = cntrller == 'admin' and trans.user_is_admin() - webapp = get_webapp( trans, **kwd ) message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) user_id = params.get( 'user_id', None ) @@ -784,14 +771,12 @@ cntrller=cntrller, user=user, username=user.username, - webapp=webapp, message=message, status=status ) @web.expose def edit_info( self, trans, cntrller, **kwd ): params = util.Params( kwd ) is_admin = cntrller == 'admin' and trans.user_is_admin() - webapp = get_webapp( trans, **kwd ) message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) user_id = params.get( 'user_id', None ) @@ -885,7 +870,7 @@ trans.sa_session.add( user ) trans.sa_session.flush() message = "The user information has been updated with the changes." - if user and webapp == 'galaxy' and is_admin: + 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: @@ -897,7 +882,7 @@ cntrller=cntrller, **kwd ) ) @web.expose - def reset_password( self, trans, email=None, webapp='galaxy', **kwd ): + def reset_password( self, trans, email=None, **kwd ): if trans.app.config.smtp_server is None: return trans.show_error_message( "Mail is not configured for this Galaxy instance. Please contact an administrator." ) message = util.restore_text( kwd.get( 'message', '' ) ) @@ -941,12 +926,11 @@ elif email is None: email = "" return trans.fill_template( '/user/reset_password.mako', - webapp=webapp, message=message, status=status ) - def __validate( self, trans, params, email, password, confirm, username, webapp ): + def __validate( self, trans, params, email, password, confirm, username ): # If coming from the community webapp, we'll require a public user name - if webapp == 'community' and not username: + if trans.webapp.name == 'community' and not username: return "A public user name is required" message = validate_email( trans, email ) if not message: @@ -954,7 +938,7 @@ if not message and username: message = validate_publicname( trans, username ) if not message: - if webapp == 'galaxy': + if trans.webapp.name == 'galaxy': if self.get_all_forms( trans, filter=dict( deleted=False ), form_type=trans.app.model.FormDefinition.types.USER_INFO ): diff -r 203e3e1592439dcb8c0eb890545ed38a66f08f2c -r 2ca0e99d6d6d940af0712e9c56b9f238fd59635c templates/user/dbkeys.mako --- a/templates/user/dbkeys.mako +++ b/templates/user/dbkeys.mako @@ -1,11 +1,7 @@ <%! def inherit(context): if context.get('use_panels'): - if context.get('webapp'): - webapp = context.get('webapp') - else: - webapp = 'galaxy' - return '/webapps/%s/base_panels.mako' % webapp + return '/webapps/%s/base_panels.mako' % t.webapp.name else: return '/base.mako' %> diff -r 203e3e1592439dcb8c0eb890545ed38a66f08f2c -r 2ca0e99d6d6d940af0712e9c56b9f238fd59635c templates/user/index.mako --- a/templates/user/index.mako +++ b/templates/user/index.mako @@ -9,27 +9,27 @@ <h2>${_('User preferences')}</h2><p>You are currently logged in as ${trans.user.email}.</p><ul> - %if webapp == 'galaxy': - <li><a href="${h.url_for( controller='user', action='manage_user_info', cntrller=cntrller, webapp=webapp )}">${_('Manage your information')}</a></li> - <li><a href="${h.url_for( controller='user', action='set_default_permissions', cntrller=cntrller, webapp=webapp )}">${_('Change default permissions')}</a> for new histories</li> - <li><a href="${h.url_for( controller='user', action='api_keys', cntrller=cntrller, webapp=webapp )}">${_('Manage your API keys')}</a></li> + %if t.webapp.name == 'galaxy': + <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='set_default_permissions', cntrller=cntrller )}">${_('Change default permissions')}</a> for new histories</li> + <li><a href="${h.url_for( controller='user', action='api_keys', cntrller=cntrller )}">${_('Manage your API keys')}</a></li> %if trans.app.config.enable_openid: - <li><a href="${h.url_for( controller='user', action='openid_manage', cntrller=cntrller, webapp=webapp )}">${_('Manage OpenIDs')}</a> linked to your account</li> + <li><a href="${h.url_for( controller='user', action='openid_manage', cntrller=cntrller )}">${_('Manage OpenIDs')}</a> linked to your account</li> %endif %if trans.app.config.use_remote_user: %if trans.app.config.remote_user_logout_href: <li><a href="${trans.app.config.remote_user_logout_href}" target="_top">${_('Logout')}</a></li> %endif %else: - <li><a href="${h.url_for( controller='user', action='logout', webapp=webapp, logout_all=True )}" target="_top">${_('Logout')}</a> ${_('of all user sessions')}</li> + <li><a href="${h.url_for( controller='user', action='logout', logout_all=True )}" target="_top">${_('Logout')}</a> ${_('of all user sessions')}</li> %endif %else: - <li><a href="${h.url_for( controller='user', action='manage_user_info', cntrller=cntrller, webapp=webapp )}">${_('Manage your information')}</a></li> - <li><a href="${h.url_for( controller='repository', action='manage_email_alerts', cntrller=cntrller, webapp=webapp )}">${_('Manage your email alerts')}</a></li> - <li><a href="${h.url_for( controller='user', action='logout', webapp=webapp, logout_all=True )}" target="_top">${_('Logout')}</a> ${_('of all user sessions')}</li> + <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='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> %endif </ul> - %if webapp == 'galaxy': + %if t.webapp.name == 'galaxy': <p> You are using <strong>${trans.user.get_disk_usage( nice_size=True )}</strong> of disk space in this Galaxy instance. %if trans.app.config.enable_quotas: @@ -43,7 +43,7 @@ <p>${n_('You are currently not logged in.')}</p> %endif <ul> - <li><a href="${h.url_for( action='login', webapp=webapp )}">${_('Login')}</li> - <li><a href="${h.url_for( action='create', cntrller='user', webapp=webapp )}">${_('Register')}</a></li> + <li><a href="${h.url_for( action='login' )}">${_('Login')}</li> + <li><a href="${h.url_for( action='create', cntrller='user' )}">${_('Register')}</a></li></ul> %endif diff -r 203e3e1592439dcb8c0eb890545ed38a66f08f2c -r 2ca0e99d6d6d940af0712e9c56b9f238fd59635c templates/user/info.mako --- a/templates/user/info.mako +++ b/templates/user/info.mako @@ -7,13 +7,12 @@ %if not is_admin: <ul class="manage-table-actions"><li> - <a class="action-button" href="${h.url_for( controller='user', action='index', cntrller=cntrller, webapp=webapp )}">User preferences</a> + <a class="action-button" href="${h.url_for( controller='user', action='index', cntrller=cntrller )}">User preferences</a></li></ul> %endif <div class="toolForm"><form name="login_info" id="login_info" action="${h.url_for( controller='user', action='edit_info', cntrller=cntrller, user_id=trans.security.encode_id( user.id ) )}" method="post" > - <input type="hidden" name="webapp" value="${webapp}" size="40"/><div class="toolFormTitle">Login Information</div><div class="form-row"><label>Email address:</label> @@ -21,7 +20,7 @@ </div><div class="form-row"><label>Public name:</label> - %if webapp == 'community': + %if t.webapp.name == 'community': %if user.active_repositories: <input type="hidden" name="username" value="${username}"/> ${username} @@ -54,7 +53,6 @@ <p></p><div class="toolForm"><form name="change_password" id="change_password" action="${h.url_for( controller='user', action='edit_info', cntrller=cntrller, user_id=trans.security.encode_id( user.id ) )}" method="post" > - <input type="hidden" name="webapp" value="${webapp}" size="40"/><div class="toolFormTitle">Change Password</div> %if not is_admin: <div class="form-row"> diff -r 203e3e1592439dcb8c0eb890545ed38a66f08f2c -r 2ca0e99d6d6d940af0712e9c56b9f238fd59635c templates/user/login.mako --- a/templates/user/login.mako +++ b/templates/user/login.mako @@ -1,11 +1,7 @@ <%! def inherit(context): if context.get('use_panels'): - if context.get('webapp'): - webapp = context.get('webapp') - else: - webapp = 'galaxy' - return '/webapps/%s/base_panels.mako' % webapp + return '/webapps/%s/base_panels.mako' % context.get('t').webapp.name else: return '/base.mako' %> @@ -82,14 +78,13 @@ <div class="form-row"><label>Email address:</label><input type="text" name="email" value="${email | h}" size="40"/> - <input type="hidden" name="webapp" value="${webapp | h}" size="40"/><input type="hidden" name="redirect" value="${redirect | h}" size="40"/></div><div class="form-row"><label>Password:</label><input type="password" name="password" value="" size="40"/><div class="toolParamHelp" style="clear: both;"> - <a href="${h.url_for( controller='user', action='reset_password', webapp=webapp, use_panels=use_panels )}">Forgot password? Reset here</a> + <a href="${h.url_for( controller='user', action='reset_password', use_panels=use_panels )}">Forgot password? Reset here</a></div></div><div class="form-row"> @@ -107,7 +102,6 @@ <div class="form-row"><label>OpenID URL:</label><input type="text" name="openid_url" size="60" style="background-image:url('${h.url_for( '/static/images/openid-16x16.gif' )}' ); background-repeat: no-repeat; padding-right: 20px; background-position: 99% 50%;"/> - <input type="hidden" name="webapp" value="${webapp | h}" size="40"/><input type="hidden" name="redirect" value="${redirect | h}" size="40"/></div><div class="form-row"> diff -r 203e3e1592439dcb8c0eb890545ed38a66f08f2c -r 2ca0e99d6d6d940af0712e9c56b9f238fd59635c templates/user/logout.mako --- a/templates/user/logout.mako +++ b/templates/user/logout.mako @@ -1,10 +1,6 @@ <%! def inherit(context): - if context.get('webapp'): - webapp = context.get('webapp') - else: - webapp = 'galaxy' - return '/webapps/%s/base_panels.mako' % webapp + return '/webapps/%s/base_panels.mako' % context.get('t').webapp.name %><%inherit file="${inherit(context)}"/><%namespace file="/message.mako" import="render_msg" /> diff -r 203e3e1592439dcb8c0eb890545ed38a66f08f2c -r 2ca0e99d6d6d940af0712e9c56b9f238fd59635c templates/user/openid_associate.mako --- a/templates/user/openid_associate.mako +++ b/templates/user/openid_associate.mako @@ -1,11 +1,7 @@ <%! def inherit(context): if context.get('use_panels'): - if context.get('webapp'): - webapp = context.get('webapp') - else: - webapp = 'galaxy' - return '/webapps/%s/base_panels.mako' % webapp + return '/webapps/%s/base_panels.mako' % t.webapp.name else: return '/base.mako' %> diff -r 203e3e1592439dcb8c0eb890545ed38a66f08f2c -r 2ca0e99d6d6d940af0712e9c56b9f238fd59635c templates/user/register.mako --- a/templates/user/register.mako +++ b/templates/user/register.mako @@ -43,7 +43,6 @@ <div class="form-row"><label>Email address:</label><input type="text" name="email" value="${email | h}" size="40"/> - <input type="hidden" name="webapp" value="${webapp | h}" size="40"/><input type="hidden" name="redirect" value="${redirect | h}" size="40"/></div><div class="form-row"> @@ -57,7 +56,7 @@ <div class="form-row"><label>Public name:</label><input type="text" name="username" size="40" value="${username |h}"/> - %if webapp == 'galaxy': + %if t.webapp.name == 'galaxy': <div class="toolParamHelp" style="clear: both;"> Your public name is an identifier that will be used to generate addresses for information you share publicly. Public names must be at least four characters in length and contain only lower-case diff -r 203e3e1592439dcb8c0eb890545ed38a66f08f2c -r 2ca0e99d6d6d940af0712e9c56b9f238fd59635c templates/user/reset_password.mako --- a/templates/user/reset_password.mako +++ b/templates/user/reset_password.mako @@ -11,7 +11,6 @@ <div class="form-row"><label>Email:</label><input type="text" name="email" value="" size="40"/> - <input type="hidden" name="webapp" value="${webapp}" size="40"/></div><div style="clear: both"></div><div class="form-row"> diff -r 203e3e1592439dcb8c0eb890545ed38a66f08f2c -r 2ca0e99d6d6d940af0712e9c56b9f238fd59635c templates/user/username.mako --- a/templates/user/username.mako +++ b/templates/user/username.mako @@ -5,7 +5,6 @@ <h2>Manage Public Name</h2><div class="toolForm"><form name="username" id="username" action="${h.url_for( controller='user', action='edit_username', cntrller=cntrller, user_id=trans.security.encode_id( user.id ) )}" method="post" > - <input type="hidden" name="webapp" value="${webapp}" size="40"/><div class="toolFormTitle">Login Information</div><div class="form-row"><label>Public name:</label> diff -r 203e3e1592439dcb8c0eb890545ed38a66f08f2c -r 2ca0e99d6d6d940af0712e9c56b9f238fd59635c templates/webapps/galaxy/admin/index.mako --- a/templates/webapps/galaxy/admin/index.mako +++ b/templates/webapps/galaxy/admin/index.mako @@ -42,11 +42,11 @@ <div class="toolSectionTitle">Security</div><div class="toolSectionBody"><div class="toolSectionBg"> - <div class="toolTitle"><a href="${h.url_for( controller='admin', action='users', webapp=webapp )}" target="galaxy_main">Manage users</a></div> - <div class="toolTitle"><a href="${h.url_for( controller='admin', action='groups', webapp=webapp )}" target="galaxy_main">Manage groups</a></div> - <div class="toolTitle"><a href="${h.url_for( controller='admin', action='roles', webapp=webapp )}" target="galaxy_main">Manage roles</a></div> + <div class="toolTitle"><a href="${h.url_for( controller='admin', action='users' )}" target="galaxy_main">Manage users</a></div> + <div class="toolTitle"><a href="${h.url_for( controller='admin', action='groups' )}" target="galaxy_main">Manage groups</a></div> + <div class="toolTitle"><a href="${h.url_for( controller='admin', action='roles' )}" target="galaxy_main">Manage roles</a></div> %if trans.app.config.allow_user_impersonation: - <div class="toolTitle"><a href="${h.url_for( controller='admin', action='impersonate', webapp=webapp )}" target="galaxy_main">Impersonate a user</a></div> + <div class="toolTitle"><a href="${h.url_for( controller='admin', action='impersonate' )}" target="galaxy_main">Impersonate a user</a></div> %endif </div></div> @@ -54,7 +54,7 @@ <div class="toolSectionTitle">Data</div><div class="toolSectionBody"><div class="toolSectionBg"> - <div class="toolTitle"><a href="${h.url_for( controller='admin', action='quotas', webapp=webapp )}" target="galaxy_main">Manage quotas</a></div> + <div class="toolTitle"><a href="${h.url_for( controller='admin', action='quotas' )}" target="galaxy_main">Manage quotas</a></div><div class="toolTitle"><a href="${h.url_for( controller='library_admin', action='browse_libraries' )}" target="galaxy_main">Manage data libraries</a></div> %if trans.app.config.enable_beta_job_managers: <div class="toolTitle"><a href="${h.url_for( controller='data_admin', action='manage_data' )}" target="galaxy_main">Manage local data</a></div> @@ -111,6 +111,6 @@ </%def><%def name="center_panel()"> - <% center_url = h.url_for( controller='admin', action='center', webapp='galaxy', message=message, status=status ) %> + <% center_url = h.url_for( controller='admin', action='center', message=message, status=status ) %><iframe name="galaxy_main" id="galaxy_main" frameborder="0" style="position: absolute; width: 100%; height: 100%;" src="${center_url}"></iframe></%def> diff -r 203e3e1592439dcb8c0eb890545ed38a66f08f2c -r 2ca0e99d6d6d940af0712e9c56b9f238fd59635c templates/webapps/galaxy/base_panels.mako --- a/templates/webapps/galaxy/base_panels.mako +++ b/templates/webapps/galaxy/base_panels.mako @@ -136,7 +136,7 @@ # Menu for user who is not logged in. menu_options = [ [ _("Login"), h.url_for( controller='/user', action='login' ), "galaxy_main" ] ] if app.config.allow_user_creation: - menu_options.append( [ _("Register"), h.url_for( controller='/user', action='create', cntrller='user', webapp='galaxy' ), "galaxy_main" ] ) + menu_options.append( [ _("Register"), h.url_for( controller='/user', action='create', cntrller='user' ), "galaxy_main" ] ) extra_class = "loggedout-only" visible = ( trans.user == None ) tab( "user", _("User"), None, visible=visible, menu_options=menu_options ) @@ -151,20 +151,20 @@ if app.config.remote_user_logout_href: menu_options.append( [ _('Logout'), app.config.remote_user_logout_href, "_top" ] ) else: - menu_options.append( [ _('Preferences'), h.url_for( controller='/user', action='index', cntrller='user', webapp='galaxy' ), "galaxy_main" ] ) + menu_options.append( [ _('Preferences'), h.url_for( controller='/user', action='index', cntrller='user' ), "galaxy_main" ] ) menu_options.append( [ 'Custom Builds', h.url_for( controller='/user', action='dbkeys' ), "galaxy_main" ] ) if app.config.require_login: - logout_url = h.url_for( controller='/root', action='index', m_c='user', m_a='logout', webapp='galaxy' ) + logout_url = h.url_for( controller='/root', action='index', m_c='user', m_a='logout' ) else: - logout_url = h.url_for( controller='/user', action='logout', webapp='galaxy' ) + logout_url = h.url_for( controller='/user', action='logout' ) menu_options.append( [ 'Logout', logout_url, "_top" ] ) menu_options.append( None ) menu_options.append( [ _('Saved Histories'), h.url_for( controller='/history', action='list' ), "galaxy_main" ] ) menu_options.append( [ _('Saved Datasets'), h.url_for( controller='/dataset', action='list' ), "galaxy_main" ] ) menu_options.append( [ _('Saved Pages'), h.url_for( controller='/page', action='list' ), "_top" ] ) - menu_options.append( [ _('API Keys'), h.url_for( controller='/user', action='api_keys', cntrller='user', webapp='galaxy' ), "galaxy_main" ] ) + menu_options.append( [ _('API Keys'), h.url_for( controller='/user', action='api_keys', cntrller='user' ), "galaxy_main" ] ) if app.config.use_remote_user: - menu_options.append( [ _('Public Name'), h.url_for( controller='/user', action='edit_username', cntrller='user', webapp='galaxy' ), "galaxy_main" ] ) + menu_options.append( [ _('Public Name'), h.url_for( controller='/user', action='edit_username', cntrller='user' ), "galaxy_main" ] ) extra_class = "loggedin-only" visible = ( trans.user != None ) https://bitbucket.org/galaxy/galaxy-central/changeset/5b977db5fc50/ changeset: 5b977db5fc50 user: james_taylor date: 2012-09-28 23:37:31 summary: Automated merge with https://bitbucket.org/galaxy/galaxy-central affected #: 20 files diff -r ee2feed164a9efc9201409b3e6191e2707ec3e18 -r 5b977db5fc50b50caa5309838f37a77010f1e2b7 lib/galaxy/web/base/controller.py --- a/lib/galaxy/web/base/controller.py +++ b/lib/galaxy/web/base/controller.py @@ -1525,1191 +1525,8 @@ class ControllerUnavailable( Exception ): pass -class Admin( object ): - # Override these - user_list_grid = None - role_list_grid = None - group_list_grid = None - quota_list_grid = None - repository_list_grid = None - tool_version_list_grid = None - delete_operation = None - undelete_operation = None - purge_operation = None - - @web.expose - @web.require_admin - def index( self, trans, **kwd ): - webapp = get_webapp( trans, **kwd ) - message = kwd.get( 'message', '' ) - status = kwd.get( 'status', 'done' ) - if webapp == 'galaxy': - installed_repositories = trans.sa_session.query( trans.model.ToolShedRepository ).first() - installing_repository_ids = get_ids_of_tool_shed_repositories_being_installed( trans, as_string=True ) - return trans.fill_template( '/webapps/galaxy/admin/index.mako', - webapp=webapp, - installed_repositories=installed_repositories, - installing_repository_ids=installing_repository_ids, - message=message, - status=status ) - else: - return trans.fill_template( '/webapps/community/admin/index.mako', - webapp=webapp, - message=message, - status=status ) - @web.expose - @web.require_admin - def center( self, trans, **kwd ): - webapp = get_webapp( trans, **kwd ) - message = kwd.get( 'message', '' ) - status = kwd.get( 'status', 'done' ) - if webapp == 'galaxy': - return trans.fill_template( '/webapps/galaxy/admin/center.mako', - message=message, - status=status ) - else: - return trans.fill_template( '/webapps/community/admin/center.mako', - message=message, - status=status ) - @web.expose - @web.require_admin - def reload_tool( self, trans, **kwd ): - params = util.Params( kwd ) - message = util.restore_text( params.get( 'message', '' ) ) - status = params.get( 'status', 'done' ) - toolbox = self.app.toolbox - if params.get( 'reload_tool_button', False ): - tool_id = params.tool_id - message, status = toolbox.reload_tool_by_id( tool_id ) - return trans.fill_template( '/admin/reload_tool.mako', - toolbox=toolbox, - message=message, - status=status ) - @web.expose - @web.require_admin - def tool_versions( self, trans, **kwd ): - if 'message' not in kwd or not kwd[ 'message' ]: - kwd[ 'message' ] = 'Tool ids for tools that are currently loaded into the tool panel are highlighted in green (click to display).' - return self.tool_version_list_grid( trans, **kwd ) - # Galaxy Role Stuff - @web.expose - @web.require_admin - def roles( self, trans, **kwargs ): - if 'operation' in kwargs: - operation = kwargs['operation'].lower() - if operation == "roles": - return self.role( trans, **kwargs ) - if operation == "create": - return self.create_role( trans, **kwargs ) - if operation == "delete": - return self.mark_role_deleted( trans, **kwargs ) - if operation == "undelete": - return self.undelete_role( trans, **kwargs ) - if operation == "purge": - return self.purge_role( trans, **kwargs ) - if operation == "manage users and groups": - return self.manage_users_and_groups_for_role( trans, **kwargs ) - if operation == "rename": - return self.rename_role( trans, **kwargs ) - # Render the list view - return self.role_list_grid( trans, **kwargs ) - @web.expose - @web.require_admin - def create_role( self, trans, **kwd ): - params = util.Params( kwd ) - webapp = get_webapp( trans, **kwd ) - message = util.restore_text( params.get( 'message', '' ) ) - status = params.get( 'status', 'done' ) - name = util.restore_text( params.get( 'name', '' ) ) - description = util.restore_text( params.get( 'description', '' ) ) - in_users = util.listify( params.get( 'in_users', [] ) ) - out_users = util.listify( params.get( 'out_users', [] ) ) - in_groups = util.listify( params.get( 'in_groups', [] ) ) - out_groups = util.listify( params.get( 'out_groups', [] ) ) - create_group_for_role = params.get( 'create_group_for_role', '' ) - create_group_for_role_checked = CheckboxField.is_checked( create_group_for_role ) - ok = True - if params.get( 'create_role_button', False ): - if not name or not description: - message = "Enter a valid name and a description." - status = 'error' - ok = False - elif trans.sa_session.query( trans.app.model.Role ).filter( trans.app.model.Role.table.c.name==name ).first(): - message = "Role names must be unique and a role with that name already exists, so choose another name." - status = 'error' - ok = False - else: - # Create the role - role = trans.app.model.Role( name=name, description=description, type=trans.app.model.Role.types.ADMIN ) - trans.sa_session.add( role ) - # Create the UserRoleAssociations - for user in [ trans.sa_session.query( trans.app.model.User ).get( x ) for x in in_users ]: - ura = trans.app.model.UserRoleAssociation( user, role ) - trans.sa_session.add( ura ) - # Create the GroupRoleAssociations - for group in [ trans.sa_session.query( trans.app.model.Group ).get( x ) for x in in_groups ]: - gra = trans.app.model.GroupRoleAssociation( group, role ) - trans.sa_session.add( gra ) - if create_group_for_role_checked: - # Create the group - group = trans.app.model.Group( name=name ) - trans.sa_session.add( group ) - # Associate the group with the role - gra = trans.model.GroupRoleAssociation( group, role ) - trans.sa_session.add( gra ) - num_in_groups = len( in_groups ) + 1 - else: - num_in_groups = len( in_groups ) - trans.sa_session.flush() - message = "Role '%s' has been created with %d associated users and %d associated groups. " \ - % ( role.name, len( in_users ), num_in_groups ) - if create_group_for_role_checked: - message += 'One of the groups associated with this role is the newly created group with the same name.' - trans.response.send_redirect( web.url_for( controller='admin', - action='roles', - webapp=webapp, - message=util.sanitize_text( message ), - status='done' ) ) - if ok: - for user in trans.sa_session.query( trans.app.model.User ) \ - .filter( trans.app.model.User.table.c.deleted==False ) \ - .order_by( trans.app.model.User.table.c.email ): - out_users.append( ( user.id, user.email ) ) - for group in trans.sa_session.query( trans.app.model.Group ) \ - .filter( trans.app.model.Group.table.c.deleted==False ) \ - .order_by( trans.app.model.Group.table.c.name ): - out_groups.append( ( group.id, group.name ) ) - return trans.fill_template( '/admin/dataset_security/role/role_create.mako', - webapp=webapp, - name=name, - description=description, - in_users=in_users, - out_users=out_users, - in_groups=in_groups, - out_groups=out_groups, - create_group_for_role_checked=create_group_for_role_checked, - message=message, - status=status ) - @web.expose - @web.require_admin - def rename_role( self, trans, **kwd ): - params = util.Params( kwd ) - webapp = get_webapp( trans, **kwd ) - message = util.restore_text( params.get( 'message', '' ) ) - status = params.get( 'status', 'done' ) - id = params.get( 'id', None ) - if not id: - message = "No role ids received for renaming" - trans.response.send_redirect( web.url_for( controller='admin', - action='roles', - webapp=webapp, - message=message, - status='error' ) ) - role = get_role( trans, id ) - if params.get( 'rename_role_button', False ): - old_name = role.name - new_name = util.restore_text( params.name ) - new_description = util.restore_text( params.description ) - if not new_name: - message = 'Enter a valid name' - status='error' - else: - existing_role = trans.sa_session.query( trans.app.model.Role ).filter( trans.app.model.Role.table.c.name==new_name ).first() - if existing_role and existing_role.id != role.id: - message = 'A role with that name already exists' - status = 'error' - else: - if not ( role.name == new_name and role.description == new_description ): - role.name = new_name - role.description = new_description - trans.sa_session.add( role ) - trans.sa_session.flush() - message = "Role '%s' has been renamed to '%s'" % ( old_name, new_name ) - return trans.response.send_redirect( web.url_for( controller='admin', - action='roles', - webapp=webapp, - message=util.sanitize_text( message ), - status='done' ) ) - return trans.fill_template( '/admin/dataset_security/role/role_rename.mako', - role=role, - webapp=webapp, - message=message, - status=status ) - @web.expose - @web.require_admin - def manage_users_and_groups_for_role( self, trans, **kwd ): - params = util.Params( kwd ) - webapp = get_webapp( trans, **kwd ) - message = util.restore_text( params.get( 'message', '' ) ) - status = params.get( 'status', 'done' ) - id = params.get( 'id', None ) - if not id: - message = "No role ids received for managing users and groups" - trans.response.send_redirect( web.url_for( controller='admin', - action='roles', - webapp=webapp, - message=message, - status='error' ) ) - role = get_role( trans, id ) - if params.get( 'role_members_edit_button', False ): - in_users = [ trans.sa_session.query( trans.app.model.User ).get( x ) for x in util.listify( params.in_users ) ] - for ura in role.users: - user = trans.sa_session.query( trans.app.model.User ).get( ura.user_id ) - if user not in in_users: - # Delete DefaultUserPermissions for previously associated users that have been removed from the role - for dup in user.default_permissions: - if role == dup.role: - trans.sa_session.delete( dup ) - # Delete DefaultHistoryPermissions for previously associated users that have been removed from the role - for history in user.histories: - for dhp in history.default_permissions: - if role == dhp.role: - trans.sa_session.delete( dhp ) - trans.sa_session.flush() - in_groups = [ trans.sa_session.query( trans.app.model.Group ).get( x ) for x in util.listify( params.in_groups ) ] - trans.app.security_agent.set_entity_role_associations( roles=[ role ], users=in_users, groups=in_groups ) - trans.sa_session.refresh( role ) - message = "Role '%s' has been updated with %d associated users and %d associated groups" % ( role.name, len( in_users ), len( in_groups ) ) - trans.response.send_redirect( web.url_for( controller='admin', - action='roles', - webapp=webapp, - message=util.sanitize_text( message ), - status=status ) ) - in_users = [] - out_users = [] - in_groups = [] - out_groups = [] - for user in trans.sa_session.query( trans.app.model.User ) \ - .filter( trans.app.model.User.table.c.deleted==False ) \ - .order_by( trans.app.model.User.table.c.email ): - if user in [ x.user for x in role.users ]: - in_users.append( ( user.id, user.email ) ) - else: - out_users.append( ( user.id, user.email ) ) - for group in trans.sa_session.query( trans.app.model.Group ) \ - .filter( trans.app.model.Group.table.c.deleted==False ) \ - .order_by( trans.app.model.Group.table.c.name ): - if group in [ x.group for x in role.groups ]: - in_groups.append( ( group.id, group.name ) ) - else: - out_groups.append( ( group.id, group.name ) ) - library_dataset_actions = {} - if webapp == 'galaxy': - # Build a list of tuples that are LibraryDatasetDatasetAssociationss followed by a list of actions - # whose DatasetPermissions is associated with the Role - # [ ( LibraryDatasetDatasetAssociation [ action, action ] ) ] - for dp in role.dataset_actions: - for ldda in trans.sa_session.query( trans.app.model.LibraryDatasetDatasetAssociation ) \ - .filter( trans.app.model.LibraryDatasetDatasetAssociation.dataset_id==dp.dataset_id ): - root_found = False - folder_path = '' - folder = ldda.library_dataset.folder - while not root_found: - folder_path = '%s / %s' % ( folder.name, folder_path ) - if not folder.parent: - root_found = True - else: - folder = folder.parent - folder_path = '%s %s' % ( folder_path, ldda.name ) - library = trans.sa_session.query( trans.app.model.Library ) \ - .filter( trans.app.model.Library.table.c.root_folder_id == folder.id ) \ - .first() - if library not in library_dataset_actions: - library_dataset_actions[ library ] = {} - try: - library_dataset_actions[ library ][ folder_path ].append( dp.action ) - except: - library_dataset_actions[ library ][ folder_path ] = [ dp.action ] - return trans.fill_template( '/admin/dataset_security/role/role.mako', - role=role, - in_users=in_users, - out_users=out_users, - in_groups=in_groups, - out_groups=out_groups, - library_dataset_actions=library_dataset_actions, - webapp=webapp, - message=message, - status=status ) - @web.expose - @web.require_admin - def mark_role_deleted( self, trans, **kwd ): - params = util.Params( kwd ) - webapp = get_webapp( trans, **kwd ) - id = kwd.get( 'id', None ) - if not id: - message = "No role ids received for deleting" - trans.response.send_redirect( web.url_for( controller='admin', - action='roles', - webapp=webapp, - message=message, - status='error' ) ) - ids = util.listify( id ) - message = "Deleted %d roles: " % len( ids ) - for role_id in ids: - role = get_role( trans, role_id ) - role.deleted = True - trans.sa_session.add( role ) - trans.sa_session.flush() - message += " %s " % role.name - trans.response.send_redirect( web.url_for( controller='admin', - action='roles', - webapp=webapp, - message=util.sanitize_text( message ), - status='done' ) ) - @web.expose - @web.require_admin - def undelete_role( self, trans, **kwd ): - params = util.Params( kwd ) - webapp = get_webapp( trans, **kwd ) - id = kwd.get( 'id', None ) - if not id: - message = "No role ids received for undeleting" - trans.response.send_redirect( web.url_for( controller='admin', - action='roles', - webapp=webapp, - message=message, - status='error' ) ) - ids = util.listify( id ) - count = 0 - undeleted_roles = "" - for role_id in ids: - role = get_role( trans, role_id ) - if not role.deleted: - message = "Role '%s' has not been deleted, so it cannot be undeleted." % role.name - trans.response.send_redirect( web.url_for( controller='admin', - action='roles', - webapp=webapp, - message=util.sanitize_text( message ), - status='error' ) ) - role.deleted = False - trans.sa_session.add( role ) - trans.sa_session.flush() - count += 1 - undeleted_roles += " %s" % role.name - message = "Undeleted %d roles: %s" % ( count, undeleted_roles ) - trans.response.send_redirect( web.url_for( controller='admin', - action='roles', - webapp=webapp, - message=util.sanitize_text( message ), - status='done' ) ) - @web.expose - @web.require_admin - def purge_role( self, trans, **kwd ): - # This method should only be called for a Role that has previously been deleted. - # Purging a deleted Role deletes all of the following from the database: - # - UserRoleAssociations where role_id == Role.id - # - DefaultUserPermissions where role_id == Role.id - # - DefaultHistoryPermissions where role_id == Role.id - # - GroupRoleAssociations where role_id == Role.id - # - DatasetPermissionss where role_id == Role.id - params = util.Params( kwd ) - webapp = get_webapp( trans, **kwd ) - id = kwd.get( 'id', None ) - if not id: - message = "No role ids received for purging" - trans.response.send_redirect( web.url_for( controller='admin', - action='roles', - webapp=webapp, - message=util.sanitize_text( message ), - status='error' ) ) - ids = util.listify( id ) - message = "Purged %d roles: " % len( ids ) - for role_id in ids: - role = get_role( trans, role_id ) - if not role.deleted: - message = "Role '%s' has not been deleted, so it cannot be purged." % role.name - trans.response.send_redirect( web.url_for( controller='admin', - action='roles', - webapp=webapp, - message=util.sanitize_text( message ), - status='error' ) ) - # Delete UserRoleAssociations - for ura in role.users: - user = trans.sa_session.query( trans.app.model.User ).get( ura.user_id ) - # Delete DefaultUserPermissions for associated users - for dup in user.default_permissions: - if role == dup.role: - trans.sa_session.delete( dup ) - # Delete DefaultHistoryPermissions for associated users - for history in user.histories: - for dhp in history.default_permissions: - if role == dhp.role: - trans.sa_session.delete( dhp ) - trans.sa_session.delete( ura ) - # Delete GroupRoleAssociations - for gra in role.groups: - trans.sa_session.delete( gra ) - # Delete DatasetPermissionss - for dp in role.dataset_actions: - trans.sa_session.delete( dp ) - trans.sa_session.flush() - message += " %s " % role.name - trans.response.send_redirect( web.url_for( controller='admin', - action='roles', - webapp=webapp, - message=util.sanitize_text( message ), - status='done' ) ) - - # Galaxy Group Stuff - @web.expose - @web.require_admin - def groups( self, trans, **kwargs ): - if 'operation' in kwargs: - operation = kwargs['operation'].lower() - if operation == "groups": - return self.group( trans, **kwargs ) - if operation == "create": - return self.create_group( trans, **kwargs ) - if operation == "delete": - return self.mark_group_deleted( trans, **kwargs ) - if operation == "undelete": - return self.undelete_group( trans, **kwargs ) - if operation == "purge": - return self.purge_group( trans, **kwargs ) - if operation == "manage users and roles": - return self.manage_users_and_roles_for_group( trans, **kwargs ) - if operation == "rename": - return self.rename_group( trans, **kwargs ) - # Render the list view - return self.group_list_grid( trans, **kwargs ) - @web.expose - @web.require_admin - def rename_group( self, trans, **kwd ): - params = util.Params( kwd ) - webapp = get_webapp( trans, **kwd ) - message = util.restore_text( params.get( 'message', '' ) ) - status = params.get( 'status', 'done' ) - id = params.get( 'id', None ) - if not id: - message = "No group ids received for renaming" - trans.response.send_redirect( web.url_for( controller='admin', - action='groups', - webapp=webapp, - message=message, - status='error' ) ) - group = get_group( trans, id ) - if params.get( 'rename_group_button', False ): - old_name = group.name - new_name = util.restore_text( params.name ) - if not new_name: - message = 'Enter a valid name' - status = 'error' - else: - existing_group = trans.sa_session.query( trans.app.model.Group ).filter( trans.app.model.Group.table.c.name==new_name ).first() - if existing_group and existing_group.id != group.id: - message = 'A group with that name already exists' - status = 'error' - else: - if group.name != new_name: - group.name = new_name - trans.sa_session.add( group ) - trans.sa_session.flush() - message = "Group '%s' has been renamed to '%s'" % ( old_name, new_name ) - return trans.response.send_redirect( web.url_for( controller='admin', - action='groups', - webapp=webapp, - message=util.sanitize_text( message ), - status='done' ) ) - return trans.fill_template( '/admin/dataset_security/group/group_rename.mako', - group=group, - webapp=webapp, - message=message, - status=status ) - @web.expose - @web.require_admin - def manage_users_and_roles_for_group( self, trans, **kwd ): - params = util.Params( kwd ) - webapp = get_webapp( trans, **kwd ) - message = util.restore_text( params.get( 'message', '' ) ) - status = params.get( 'status', 'done' ) - group = get_group( trans, params.id ) - if params.get( 'group_roles_users_edit_button', False ): - in_roles = [ trans.sa_session.query( trans.app.model.Role ).get( x ) for x in util.listify( params.in_roles ) ] - in_users = [ trans.sa_session.query( trans.app.model.User ).get( x ) for x in util.listify( params.in_users ) ] - trans.app.security_agent.set_entity_group_associations( groups=[ group ], roles=in_roles, users=in_users ) - trans.sa_session.refresh( group ) - message += "Group '%s' has been updated with %d associated roles and %d associated users" % ( group.name, len( in_roles ), len( in_users ) ) - trans.response.send_redirect( web.url_for( controller='admin', - action='groups', - webapp=webapp, - message=util.sanitize_text( message ), - status=status ) ) - in_roles = [] - out_roles = [] - in_users = [] - out_users = [] - for role in trans.sa_session.query(trans.app.model.Role ) \ - .filter( trans.app.model.Role.table.c.deleted==False ) \ - .order_by( trans.app.model.Role.table.c.name ): - if role in [ x.role for x in group.roles ]: - in_roles.append( ( role.id, role.name ) ) - else: - out_roles.append( ( role.id, role.name ) ) - for user in trans.sa_session.query( trans.app.model.User ) \ - .filter( trans.app.model.User.table.c.deleted==False ) \ - .order_by( trans.app.model.User.table.c.email ): - if user in [ x.user for x in group.users ]: - in_users.append( ( user.id, user.email ) ) - else: - out_users.append( ( user.id, user.email ) ) - message += 'Group %s is currently associated with %d roles and %d users' % ( group.name, len( in_roles ), len( in_users ) ) - return trans.fill_template( '/admin/dataset_security/group/group.mako', - group=group, - in_roles=in_roles, - out_roles=out_roles, - in_users=in_users, - out_users=out_users, - webapp=webapp, - message=message, - status=status ) - @web.expose - @web.require_admin - def create_group( self, trans, **kwd ): - params = util.Params( kwd ) - webapp = get_webapp( trans, **kwd ) - message = util.restore_text( params.get( 'message', '' ) ) - status = params.get( 'status', 'done' ) - name = util.restore_text( params.get( 'name', '' ) ) - in_users = util.listify( params.get( 'in_users', [] ) ) - out_users = util.listify( params.get( 'out_users', [] ) ) - in_roles = util.listify( params.get( 'in_roles', [] ) ) - out_roles = util.listify( params.get( 'out_roles', [] ) ) - create_role_for_group = params.get( 'create_role_for_group', '' ) - create_role_for_group_checked = CheckboxField.is_checked( create_role_for_group ) - ok = True - if params.get( 'create_group_button', False ): - if not name: - message = "Enter a valid name." - status = 'error' - ok = False - elif trans.sa_session.query( trans.app.model.Group ).filter( trans.app.model.Group.table.c.name==name ).first(): - message = "Group names must be unique and a group with that name already exists, so choose another name." - status = 'error' - ok = False - else: - # Create the group - group = trans.app.model.Group( name=name ) - trans.sa_session.add( group ) - trans.sa_session.flush() - # Create the UserRoleAssociations - for user in [ trans.sa_session.query( trans.app.model.User ).get( x ) for x in in_users ]: - uga = trans.app.model.UserGroupAssociation( user, group ) - trans.sa_session.add( uga ) - # Create the GroupRoleAssociations - for role in [ trans.sa_session.query( trans.app.model.Role ).get( x ) for x in in_roles ]: - gra = trans.app.model.GroupRoleAssociation( group, role ) - trans.sa_session.add( gra ) - if create_role_for_group_checked: - # Create the role - role = trans.app.model.Role( name=name, description='Role for group %s' % name ) - trans.sa_session.add( role ) - # Associate the role with the group - gra = trans.model.GroupRoleAssociation( group, role ) - trans.sa_session.add( gra ) - num_in_roles = len( in_roles ) + 1 - else: - num_in_roles = len( in_roles ) - trans.sa_session.flush() - message = "Group '%s' has been created with %d associated users and %d associated roles. " \ - % ( group.name, len( in_users ), num_in_roles ) - if create_role_for_group_checked: - message += 'One of the roles associated with this group is the newly created role with the same name.' - trans.response.send_redirect( web.url_for( controller='admin', - action='groups', - webapp=webapp, - message=util.sanitize_text( message ), - status='done' ) ) - - - if ok: - for user in trans.sa_session.query( trans.app.model.User ) \ - .filter( trans.app.model.User.table.c.deleted==False ) \ - .order_by( trans.app.model.User.table.c.email ): - out_users.append( ( user.id, user.email ) ) - for role in trans.sa_session.query( trans.app.model.Role ) \ - .filter( trans.app.model.Role.table.c.deleted==False ) \ - .order_by( trans.app.model.Role.table.c.name ): - out_roles.append( ( role.id, role.name ) ) - return trans.fill_template( '/admin/dataset_security/group/group_create.mako', - webapp=webapp, - name=name, - in_users=in_users, - out_users=out_users, - in_roles=in_roles, - out_roles=out_roles, - create_role_for_group_checked=create_role_for_group_checked, - message=message, - status=status ) - @web.expose - @web.require_admin - def mark_group_deleted( self, trans, **kwd ): - params = util.Params( kwd ) - webapp = get_webapp( trans, **kwd ) - id = params.get( 'id', None ) - if not id: - message = "No group ids received for marking deleted" - trans.response.send_redirect( web.url_for( controller='admin', - action='groups', - webapp=webapp, - message=message, - status='error' ) ) - ids = util.listify( id ) - message = "Deleted %d groups: " % len( ids ) - for group_id in ids: - group = get_group( trans, group_id ) - group.deleted = True - trans.sa_session.add( group ) - trans.sa_session.flush() - message += " %s " % group.name - trans.response.send_redirect( web.url_for( controller='admin', - action='groups', - webapp=webapp, - message=util.sanitize_text( message ), - status='done' ) ) - @web.expose - @web.require_admin - def undelete_group( self, trans, **kwd ): - params = util.Params( kwd ) - webapp = get_webapp( trans, **kwd ) - id = kwd.get( 'id', None ) - if not id: - message = "No group ids received for undeleting" - trans.response.send_redirect( web.url_for( controller='admin', - action='groups', - webapp=webapp, - message=message, - status='error' ) ) - ids = util.listify( id ) - count = 0 - undeleted_groups = "" - for group_id in ids: - group = get_group( trans, group_id ) - if not group.deleted: - message = "Group '%s' has not been deleted, so it cannot be undeleted." % group.name - trans.response.send_redirect( web.url_for( controller='admin', - action='groups', - webapp=webapp, - message=util.sanitize_text( message ), - status='error' ) ) - group.deleted = False - trans.sa_session.add( group ) - trans.sa_session.flush() - count += 1 - undeleted_groups += " %s" % group.name - message = "Undeleted %d groups: %s" % ( count, undeleted_groups ) - trans.response.send_redirect( web.url_for( controller='admin', - action='groups', - webapp=webapp, - message=util.sanitize_text( message ), - status='done' ) ) - @web.expose - @web.require_admin - def purge_group( self, trans, **kwd ): - # This method should only be called for a Group that has previously been deleted. - # Purging a deleted Group simply deletes all UserGroupAssociations and GroupRoleAssociations. - params = util.Params( kwd ) - webapp = get_webapp( trans, **kwd ) - id = kwd.get( 'id', None ) - if not id: - message = "No group ids received for purging" - trans.response.send_redirect( web.url_for( controller='admin', - action='groups', - webapp=webapp, - message=util.sanitize_text( message ), - status='error' ) ) - ids = util.listify( id ) - message = "Purged %d groups: " % len( ids ) - for group_id in ids: - group = get_group( trans, group_id ) - if not group.deleted: - # We should never reach here, but just in case there is a bug somewhere... - message = "Group '%s' has not been deleted, so it cannot be purged." % group.name - trans.response.send_redirect( web.url_for( controller='admin', - action='groups', - webapp=webapp, - message=util.sanitize_text( message ), - status='error' ) ) - # Delete UserGroupAssociations - for uga in group.users: - trans.sa_session.delete( uga ) - # Delete GroupRoleAssociations - for gra in group.roles: - trans.sa_session.delete( gra ) - trans.sa_session.flush() - message += " %s " % group.name - trans.response.send_redirect( web.url_for( controller='admin', - action='groups', - webapp=webapp, - message=util.sanitize_text( message ), - status='done' ) ) - - # Galaxy User Stuff - @web.expose - @web.require_admin - def create_new_user( self, trans, **kwd ): - webapp = get_webapp( trans, **kwd ) - return trans.response.send_redirect( web.url_for( controller='user', - action='create', - cntrller='admin', - webapp=webapp ) ) - @web.expose - @web.require_admin - def reset_user_password( self, trans, **kwd ): - webapp = get_webapp( trans, **kwd ) - user_id = kwd.get( 'id', None ) - if not user_id: - message = "No users received for resetting passwords." - trans.response.send_redirect( web.url_for( controller='admin', - action='users', - webapp=webapp, - message=message, - status='error' ) ) - user_ids = util.listify( user_id ) - if 'reset_user_password_button' in kwd: - message = '' - status = '' - for user_id in user_ids: - user = get_user( trans, user_id ) - password = kwd.get( 'password', None ) - confirm = kwd.get( 'confirm' , None ) - if len( password ) < 6: - message = "Use a password of at least 6 characters." - status = 'error' - break - elif password != confirm: - message = "Passwords do not match." - status = 'error' - break - else: - user.set_password_cleartext( password ) - trans.sa_session.add( user ) - trans.sa_session.flush() - if not message and not status: - message = "Passwords reset for %d %s." % ( len( user_ids ), inflector.cond_plural( len( user_ids ), 'user' ) ) - status = 'done' - trans.response.send_redirect( web.url_for( controller='admin', - action='users', - webapp=webapp, - message=util.sanitize_text( message ), - status=status ) ) - users = [ get_user( trans, user_id ) for user_id in user_ids ] - if len( user_ids ) > 1: - user_id = ','.join( user_ids ) - return trans.fill_template( '/admin/user/reset_password.mako', - id=user_id, - users=users, - password='', - confirm='', - webapp=webapp ) - @web.expose - @web.require_admin - def mark_user_deleted( self, trans, **kwd ): - webapp = get_webapp( trans, **kwd ) - id = kwd.get( 'id', None ) - if not id: - message = "No user ids received for deleting" - trans.response.send_redirect( web.url_for( controller='admin', - action='users', - webapp=webapp, - message=message, - status='error' ) ) - ids = util.listify( id ) - message = "Deleted %d users: " % len( ids ) - for user_id in ids: - user = get_user( trans, user_id ) - user.deleted = True - trans.sa_session.add( user ) - trans.sa_session.flush() - message += " %s " % user.email - trans.response.send_redirect( web.url_for( controller='admin', - action='users', - webapp=webapp, - message=util.sanitize_text( message ), - status='done' ) ) - @web.expose - @web.require_admin - def undelete_user( self, trans, **kwd ): - webapp = get_webapp( trans, **kwd ) - id = kwd.get( 'id', None ) - if not id: - message = "No user ids received for undeleting" - trans.response.send_redirect( web.url_for( controller='admin', - action='users', - webapp=webapp, - message=message, - status='error' ) ) - ids = util.listify( id ) - count = 0 - undeleted_users = "" - for user_id in ids: - user = get_user( trans, user_id ) - if not user.deleted: - message = "User '%s' has not been deleted, so it cannot be undeleted." % user.email - trans.response.send_redirect( web.url_for( controller='admin', - action='users', - webapp=webapp, - message=util.sanitize_text( message ), - status='error' ) ) - user.deleted = False - trans.sa_session.add( user ) - trans.sa_session.flush() - count += 1 - undeleted_users += " %s" % user.email - message = "Undeleted %d users: %s" % ( count, undeleted_users ) - trans.response.send_redirect( web.url_for( controller='admin', - action='users', - webapp=webapp, - message=util.sanitize_text( message ), - status='done' ) ) - @web.expose - @web.require_admin - def purge_user( self, trans, **kwd ): - # This method should only be called for a User that has previously been deleted. - # We keep the User in the database ( marked as purged ), and stuff associated - # with the user's private role in case we want the ability to unpurge the user - # some time in the future. - # Purging a deleted User deletes all of the following: - # - History where user_id = User.id - # - HistoryDatasetAssociation where history_id = History.id - # - Dataset where HistoryDatasetAssociation.dataset_id = Dataset.id - # - UserGroupAssociation where user_id == User.id - # - UserRoleAssociation where user_id == User.id EXCEPT FOR THE PRIVATE ROLE - # - UserAddress where user_id == User.id - # Purging Histories and Datasets must be handled via the cleanup_datasets.py script - webapp = get_webapp( trans, **kwd ) - id = kwd.get( 'id', None ) - if not id: - message = "No user ids received for purging" - trans.response.send_redirect( web.url_for( controller='admin', - action='users', - webapp=webapp, - message=util.sanitize_text( message ), - status='error' ) ) - ids = util.listify( id ) - message = "Purged %d users: " % len( ids ) - for user_id in ids: - user = get_user( trans, user_id ) - if not user.deleted: - # We should never reach here, but just in case there is a bug somewhere... - message = "User '%s' has not been deleted, so it cannot be purged." % user.email - trans.response.send_redirect( web.url_for( controller='admin', - action='users', - webapp=webapp, - message=util.sanitize_text( message ), - status='error' ) ) - private_role = trans.app.security_agent.get_private_user_role( user ) - # Delete History - for h in user.active_histories: - trans.sa_session.refresh( h ) - for hda in h.active_datasets: - # Delete HistoryDatasetAssociation - d = trans.sa_session.query( trans.app.model.Dataset ).get( hda.dataset_id ) - # Delete Dataset - if not d.deleted: - d.deleted = True - trans.sa_session.add( d ) - hda.deleted = True - trans.sa_session.add( hda ) - h.deleted = True - trans.sa_session.add( h ) - # Delete UserGroupAssociations - for uga in user.groups: - trans.sa_session.delete( uga ) - # Delete UserRoleAssociations EXCEPT FOR THE PRIVATE ROLE - for ura in user.roles: - if ura.role_id != private_role.id: - trans.sa_session.delete( ura ) - # Delete UserAddresses - for address in user.addresses: - trans.sa_session.delete( address ) - # Purge the user - user.purged = True - trans.sa_session.add( user ) - trans.sa_session.flush() - message += "%s " % user.email - trans.response.send_redirect( web.url_for( controller='admin', - action='users', - webapp=webapp, - message=util.sanitize_text( message ), - status='done' ) ) - @web.expose - @web.require_admin - def users( self, trans, **kwd ): - if 'operation' in kwd: - operation = kwd['operation'].lower() - if operation == "roles": - return self.user( trans, **kwd ) - elif operation == "reset password": - return self.reset_user_password( trans, **kwd ) - elif operation == "delete": - return self.mark_user_deleted( trans, **kwd ) - elif operation == "undelete": - return self.undelete_user( trans, **kwd ) - elif operation == "purge": - return self.purge_user( trans, **kwd ) - elif operation == "create": - return self.create_new_user( trans, **kwd ) - elif operation == "information": - user_id = kwd.get( 'id', None ) - if not user_id: - kwd[ 'message' ] = util.sanitize_text( "Invalid user id (%s) received" % str( user_id ) ) - kwd[ 'status' ] = 'error' - else: - return trans.response.send_redirect( web.url_for( controller='user', - action='manage_user_info', - cntrller='admin', - **kwd ) ) - elif operation == "manage roles and groups": - return self.manage_roles_and_groups_for_user( trans, **kwd ) - if trans.app.config.allow_user_deletion: - if self.delete_operation not in self.user_list_grid.operations: - self.user_list_grid.operations.append( self.delete_operation ) - if self.undelete_operation not in self.user_list_grid.operations: - self.user_list_grid.operations.append( self.undelete_operation ) - if self.purge_operation not in self.user_list_grid.operations: - self.user_list_grid.operations.append( self.purge_operation ) - # Render the list view - return self.user_list_grid( trans, **kwd ) - @web.expose - @web.require_admin - def name_autocomplete_data( self, trans, q=None, limit=None, timestamp=None ): - """Return autocomplete data for user emails""" - ac_data = "" - for user in trans.sa_session.query( User ).filter_by( deleted=False ).filter( func.lower( User.email ).like( q.lower() + "%" ) ): - ac_data = ac_data + user.email + "\n" - return ac_data - @web.expose - @web.require_admin - def manage_roles_and_groups_for_user( self, trans, **kwd ): - webapp = get_webapp( trans, **kwd ) - user_id = kwd.get( 'id', None ) - message = '' - status = '' - if not user_id: - message += "Invalid user id (%s) received" % str( user_id ) - trans.response.send_redirect( web.url_for( controller='admin', - action='users', - webapp=webapp, - message=util.sanitize_text( message ), - status='error' ) ) - user = get_user( trans, user_id ) - private_role = trans.app.security_agent.get_private_user_role( user ) - if kwd.get( 'user_roles_groups_edit_button', False ): - # Make sure the user is not dis-associating himself from his private role - out_roles = kwd.get( 'out_roles', [] ) - if out_roles: - out_roles = [ trans.sa_session.query( trans.app.model.Role ).get( x ) for x in util.listify( out_roles ) ] - if private_role in out_roles: - message += "You cannot eliminate a user's private role association. " - status = 'error' - in_roles = kwd.get( 'in_roles', [] ) - if in_roles: - in_roles = [ trans.sa_session.query( trans.app.model.Role ).get( x ) for x in util.listify( in_roles ) ] - out_groups = kwd.get( 'out_groups', [] ) - if out_groups: - out_groups = [ trans.sa_session.query( trans.app.model.Group ).get( x ) for x in util.listify( out_groups ) ] - in_groups = kwd.get( 'in_groups', [] ) - if in_groups: - in_groups = [ trans.sa_session.query( trans.app.model.Group ).get( x ) for x in util.listify( in_groups ) ] - if in_roles: - trans.app.security_agent.set_entity_user_associations( users=[ user ], roles=in_roles, groups=in_groups ) - trans.sa_session.refresh( user ) - message += "User '%s' has been updated with %d associated roles and %d associated groups (private roles are not displayed)" % \ - ( user.email, len( in_roles ), len( in_groups ) ) - trans.response.send_redirect( web.url_for( controller='admin', - action='users', - webapp=webapp, - message=util.sanitize_text( message ), - status='done' ) ) - in_roles = [] - out_roles = [] - in_groups = [] - out_groups = [] - for role in trans.sa_session.query( trans.app.model.Role ).filter( trans.app.model.Role.table.c.deleted==False ) \ - .order_by( trans.app.model.Role.table.c.name ): - if role in [ x.role for x in user.roles ]: - in_roles.append( ( role.id, role.name ) ) - elif role.type != trans.app.model.Role.types.PRIVATE: - # There is a 1 to 1 mapping between a user and a PRIVATE role, so private roles should - # not be listed in the roles form fields, except for the currently selected user's private - # role, which should always be in in_roles. The check above is added as an additional - # precaution, since for a period of time we were including private roles in the form fields. - out_roles.append( ( role.id, role.name ) ) - for group in trans.sa_session.query( trans.app.model.Group ).filter( trans.app.model.Group.table.c.deleted==False ) \ - .order_by( trans.app.model.Group.table.c.name ): - if group in [ x.group for x in user.groups ]: - in_groups.append( ( group.id, group.name ) ) - else: - out_groups.append( ( group.id, group.name ) ) - message += "User '%s' is currently associated with %d roles and is a member of %d groups" % \ - ( user.email, len( in_roles ), len( in_groups ) ) - if not status: - status = 'done' - return trans.fill_template( '/admin/user/user.mako', - user=user, - in_roles=in_roles, - out_roles=out_roles, - in_groups=in_groups, - out_groups=out_groups, - webapp=webapp, - message=message, - status=status ) - @web.expose - @web.require_admin - def memdump( self, trans, ids = 'None', sorts = 'None', pages = 'None', new_id = None, new_sort = None, **kwd ): - if self.app.memdump is None: - return trans.show_error_message( "Memdump is not enabled (set <code>use_memdump = True</code> in universe_wsgi.ini)" ) - heap = self.app.memdump.get() - p = util.Params( kwd ) - msg = None - if p.dump: - heap = self.app.memdump.get( update = True ) - msg = "Heap dump complete" - elif p.setref: - self.app.memdump.setref() - msg = "Reference point set (dump to see delta from this point)" - ids = ids.split( ',' ) - sorts = sorts.split( ',' ) - if new_id is not None: - ids.append( new_id ) - sorts.append( 'None' ) - elif new_sort is not None: - sorts[-1] = new_sort - breadcrumb = "<a href='%s' class='breadcrumb'>heap</a>" % web.url_for() - # new lists so we can assemble breadcrumb links - new_ids = [] - new_sorts = [] - for id, sort in zip( ids, sorts ): - new_ids.append( id ) - if id != 'None': - breadcrumb += "<a href='%s' class='breadcrumb'>[%s]</a>" % ( web.url_for( ids=','.join( new_ids ), sorts=','.join( new_sorts ) ), id ) - heap = heap[int(id)] - new_sorts.append( sort ) - if sort != 'None': - breadcrumb += "<a href='%s' class='breadcrumb'>.by('%s')</a>" % ( web.url_for( ids=','.join( new_ids ), sorts=','.join( new_sorts ) ), sort ) - heap = heap.by( sort ) - ids = ','.join( new_ids ) - sorts = ','.join( new_sorts ) - if p.theone: - breadcrumb += ".theone" - heap = heap.theone - return trans.fill_template( '/admin/memdump.mako', heap = heap, ids = ids, sorts = sorts, breadcrumb = breadcrumb, msg = msg ) - - @web.expose - @web.require_admin - def jobs( self, trans, stop = [], stop_msg = None, cutoff = 180, job_lock = None, ajl_submit = None, **kwd ): - deleted = [] - msg = None - status = None - if self.app.config.job_manager != self.app.config.server_name: - return trans.show_error_message( 'This Galaxy instance (%s) is not the job manager (%s). If using multiple servers, please directly access the job manager instance to manage jobs.' % (self.app.config.server_name, self.app.config.job_manager) ) - job_ids = util.listify( stop ) - if job_ids and stop_msg in [ None, '' ]: - msg = 'Please enter an error message to display to the user describing why the job was terminated' - status = 'error' - elif job_ids: - if stop_msg[-1] not in string.punctuation: - stop_msg += '.' - for job_id in job_ids: - trans.app.job_manager.job_stop_queue.put( job_id, error_msg="This job was stopped by an administrator: %s For more information or help" % stop_msg ) - deleted.append( str( job_id ) ) - if deleted: - msg = 'Queued job' - if len( deleted ) > 1: - msg += 's' - msg += ' for deletion: ' - msg += ', '.join( deleted ) - status = 'done' - if ajl_submit: - if job_lock == 'on': - trans.app.job_manager.job_queue.job_lock = True - else: - trans.app.job_manager.job_queue.job_lock = False - cutoff_time = datetime.utcnow() - timedelta( seconds=int( cutoff ) ) - jobs = trans.sa_session.query( trans.app.model.Job ) \ - .filter( and_( trans.app.model.Job.table.c.update_time < cutoff_time, - or_( trans.app.model.Job.state == trans.app.model.Job.states.NEW, - trans.app.model.Job.state == trans.app.model.Job.states.QUEUED, - trans.app.model.Job.state == trans.app.model.Job.states.RUNNING, - trans.app.model.Job.state == trans.app.model.Job.states.UPLOAD ) ) ) \ - .order_by( trans.app.model.Job.table.c.update_time.desc() ) - last_updated = {} - for job in jobs: - delta = datetime.utcnow() - job.update_time - if delta > timedelta( minutes=60 ): - last_updated[job.id] = '%s hours' % int( delta.seconds / 60 / 60 ) - else: - last_updated[job.id] = '%s minutes' % int( delta.seconds / 60 ) - return trans.fill_template( '/admin/jobs.mako', - jobs = jobs, - last_updated = last_updated, - cutoff = cutoff, - msg = msg, - status = status, - job_lock = trans.app.job_manager.job_queue.job_lock ) - ## ---- Utility methods ------------------------------------------------------- -def get_ids_of_tool_shed_repositories_being_installed( trans, as_string=False ): - installing_repository_ids = [] - new_status = trans.model.ToolShedRepository.installation_status.NEW - cloning_status = trans.model.ToolShedRepository.installation_status.CLONING - setting_tool_versions_status = trans.model.ToolShedRepository.installation_status.SETTING_TOOL_VERSIONS - installing_dependencies_status = trans.model.ToolShedRepository.installation_status.INSTALLING_TOOL_DEPENDENCIES - loading_datatypes_status = trans.model.ToolShedRepository.installation_status.LOADING_PROPRIETARY_DATATYPES - for tool_shed_repository in trans.sa_session.query( trans.model.ToolShedRepository ) \ - .filter( or_( trans.model.ToolShedRepository.status == new_status, - trans.model.ToolShedRepository.status == cloning_status, - trans.model.ToolShedRepository.status == setting_tool_versions_status, - trans.model.ToolShedRepository.status == installing_dependencies_status, - trans.model.ToolShedRepository.status == loading_datatypes_status ) ): - installing_repository_ids.append( trans.security.encode_id( tool_shed_repository.id ) ) - if as_string: - return ','.join( installing_repository_ids ) - return installing_repository_ids - -def get_user( trans, user_id ): - """Get a User from the database by id.""" - user = trans.sa_session.query( trans.model.User ).get( trans.security.decode_id( user_id ) ) - if not user: - return trans.show_error_message( "User not found for id (%s)" % str( user_id ) ) - return user -def get_user_by_username( trans, username ): - """Get a user from the database by username""" - # TODO: Add exception handling here. - return trans.sa_session.query( trans.model.User ) \ - .filter( trans.model.User.table.c.username == username ) \ - .one() -def get_role( trans, id ): - """Get a Role from the database by id.""" - # Load user from database - id = trans.security.decode_id( id ) - role = trans.sa_session.query( trans.model.Role ).get( id ) - if not role: - return trans.show_error_message( "Role not found for id (%s)" % str( id ) ) - return role -def get_group( trans, id ): - """Get a Group from the database by id.""" - # Load user from database - id = trans.security.decode_id( id ) - group = trans.sa_session.query( trans.model.Group ).get( id ) - if not group: - return trans.show_error_message( "Group not found for id (%s)" % str( id ) ) - return group -def get_quota( trans, id ): - """Get a Quota from the database by id.""" - # Load user from database - id = trans.security.decode_id( id ) - quota = trans.sa_session.query( trans.model.Quota ).get( id ) - return quota -def get_webapp( trans, **kwd ): - """Get the value of the webapp, can be one of 'community', 'galaxy', 'reports', 'demo_sequencer'.""" - if 'webapp' in kwd: - return kwd[ 'webapp' ] - if 'webapp' in trans.environ: - return trans.environ[ 'webapp' ] - # The default is galaxy. - return 'galaxy' def sort_by_attr( seq, attr ): """ Sort the sequence of objects by object's attribute diff -r ee2feed164a9efc9201409b3e6191e2707ec3e18 -r 5b977db5fc50b50caa5309838f37a77010f1e2b7 lib/galaxy/web/base/controllers/admin.py --- /dev/null +++ b/lib/galaxy/web/base/controllers/admin.py @@ -0,0 +1,1114 @@ +from datetime import date, datetime, timedelta + +from galaxy import config, tools, web, util +from galaxy.model.orm import * + +class Admin( object ): + # Override these + user_list_grid = None + role_list_grid = None + group_list_grid = None + quota_list_grid = None + repository_list_grid = None + tool_version_list_grid = None + delete_operation = None + undelete_operation = None + purge_operation = None + + @web.expose + @web.require_admin + def index( self, trans, **kwd ): + message = kwd.get( 'message', '' ) + status = kwd.get( 'status', 'done' ) + if trans.webapp.name == 'galaxy': + installed_repositories = trans.sa_session.query( trans.model.ToolShedRepository ).first() + installing_repository_ids = get_ids_of_tool_shed_repositories_being_installed( trans, as_string=True ) + return trans.fill_template( '/webapps/galaxy/admin/index.mako', + installed_repositories=installed_repositories, + installing_repository_ids=installing_repository_ids, + message=message, + status=status ) + else: + return trans.fill_template( '/webapps/community/admin/index.mako', + message=message, + status=status ) + @web.expose + @web.require_admin + def center( self, trans, **kwd ): + message = kwd.get( 'message', '' ) + status = kwd.get( 'status', 'done' ) + if trans.webapp.name == 'galaxy': + return trans.fill_template( '/webapps/galaxy/admin/center.mako', + message=message, + status=status ) + else: + return trans.fill_template( '/webapps/community/admin/center.mako', + message=message, + status=status ) + @web.expose + @web.require_admin + def reload_tool( self, trans, **kwd ): + params = util.Params( kwd ) + message = util.restore_text( params.get( 'message', '' ) ) + status = params.get( 'status', 'done' ) + toolbox = self.app.toolbox + if params.get( 'reload_tool_button', False ): + tool_id = params.tool_id + message, status = toolbox.reload_tool_by_id( tool_id ) + return trans.fill_template( '/admin/reload_tool.mako', + toolbox=toolbox, + message=message, + status=status ) + @web.expose + @web.require_admin + def tool_versions( self, trans, **kwd ): + if 'message' not in kwd or not kwd[ 'message' ]: + kwd[ 'message' ] = 'Tool ids for tools that are currently loaded into the tool panel are highlighted in green (click to display).' + return self.tool_version_list_grid( trans, **kwd ) + # Galaxy Role Stuff + @web.expose + @web.require_admin + def roles( self, trans, **kwargs ): + if 'operation' in kwargs: + operation = kwargs['operation'].lower() + if operation == "roles": + return self.role( trans, **kwargs ) + if operation == "create": + return self.create_role( trans, **kwargs ) + if operation == "delete": + return self.mark_role_deleted( trans, **kwargs ) + if operation == "undelete": + return self.undelete_role( trans, **kwargs ) + if operation == "purge": + return self.purge_role( trans, **kwargs ) + if operation == "manage users and groups": + return self.manage_users_and_groups_for_role( trans, **kwargs ) + if operation == "rename": + return self.rename_role( trans, **kwargs ) + # Render the list view + return self.role_list_grid( trans, **kwargs ) + @web.expose + @web.require_admin + def create_role( self, trans, **kwd ): + params = util.Params( kwd ) + message = util.restore_text( params.get( 'message', '' ) ) + status = params.get( 'status', 'done' ) + name = util.restore_text( params.get( 'name', '' ) ) + description = util.restore_text( params.get( 'description', '' ) ) + in_users = util.listify( params.get( 'in_users', [] ) ) + out_users = util.listify( params.get( 'out_users', [] ) ) + in_groups = util.listify( params.get( 'in_groups', [] ) ) + out_groups = util.listify( params.get( 'out_groups', [] ) ) + create_group_for_role = params.get( 'create_group_for_role', '' ) + create_group_for_role_checked = CheckboxField.is_checked( create_group_for_role ) + ok = True + if params.get( 'create_role_button', False ): + if not name or not description: + message = "Enter a valid name and a description." + status = 'error' + ok = False + elif trans.sa_session.query( trans.app.model.Role ).filter( trans.app.model.Role.table.c.name==name ).first(): + message = "Role names must be unique and a role with that name already exists, so choose another name." + status = 'error' + ok = False + else: + # Create the role + role = trans.app.model.Role( name=name, description=description, type=trans.app.model.Role.types.ADMIN ) + trans.sa_session.add( role ) + # Create the UserRoleAssociations + for user in [ trans.sa_session.query( trans.app.model.User ).get( x ) for x in in_users ]: + ura = trans.app.model.UserRoleAssociation( user, role ) + trans.sa_session.add( ura ) + # Create the GroupRoleAssociations + for group in [ trans.sa_session.query( trans.app.model.Group ).get( x ) for x in in_groups ]: + gra = trans.app.model.GroupRoleAssociation( group, role ) + trans.sa_session.add( gra ) + if create_group_for_role_checked: + # Create the group + group = trans.app.model.Group( name=name ) + trans.sa_session.add( group ) + # Associate the group with the role + gra = trans.model.GroupRoleAssociation( group, role ) + trans.sa_session.add( gra ) + num_in_groups = len( in_groups ) + 1 + else: + num_in_groups = len( in_groups ) + trans.sa_session.flush() + message = "Role '%s' has been created with %d associated users and %d associated groups. " \ + % ( role.name, len( in_users ), num_in_groups ) + if create_group_for_role_checked: + message += 'One of the groups associated with this role is the newly created group with the same name.' + trans.response.send_redirect( web.url_for( controller='admin', + action='roles', + message=util.sanitize_text( message ), + status='done' ) ) + if ok: + for user in trans.sa_session.query( trans.app.model.User ) \ + .filter( trans.app.model.User.table.c.deleted==False ) \ + .order_by( trans.app.model.User.table.c.email ): + out_users.append( ( user.id, user.email ) ) + for group in trans.sa_session.query( trans.app.model.Group ) \ + .filter( trans.app.model.Group.table.c.deleted==False ) \ + .order_by( trans.app.model.Group.table.c.name ): + out_groups.append( ( group.id, group.name ) ) + return trans.fill_template( '/admin/dataset_security/role/role_create.mako', + name=name, + description=description, + in_users=in_users, + out_users=out_users, + in_groups=in_groups, + out_groups=out_groups, + create_group_for_role_checked=create_group_for_role_checked, + message=message, + status=status ) + @web.expose + @web.require_admin + def rename_role( self, trans, **kwd ): + params = util.Params( kwd ) + message = util.restore_text( params.get( 'message', '' ) ) + status = params.get( 'status', 'done' ) + id = params.get( 'id', None ) + if not id: + message = "No role ids received for renaming" + trans.response.send_redirect( web.url_for( controller='admin', + action='roles', + message=message, + status='error' ) ) + role = get_role( trans, id ) + if params.get( 'rename_role_button', False ): + old_name = role.name + new_name = util.restore_text( params.name ) + new_description = util.restore_text( params.description ) + if not new_name: + message = 'Enter a valid name' + status='error' + else: + existing_role = trans.sa_session.query( trans.app.model.Role ).filter( trans.app.model.Role.table.c.name==new_name ).first() + if existing_role and existing_role.id != role.id: + message = 'A role with that name already exists' + status = 'error' + else: + if not ( role.name == new_name and role.description == new_description ): + role.name = new_name + role.description = new_description + trans.sa_session.add( role ) + trans.sa_session.flush() + message = "Role '%s' has been renamed to '%s'" % ( old_name, new_name ) + return trans.response.send_redirect( web.url_for( controller='admin', + action='roles', + message=util.sanitize_text( message ), + status='done' ) ) + return trans.fill_template( '/admin/dataset_security/role/role_rename.mako', + role=role, + message=message, + status=status ) + @web.expose + @web.require_admin + def manage_users_and_groups_for_role( self, trans, **kwd ): + params = util.Params( kwd ) + message = util.restore_text( params.get( 'message', '' ) ) + status = params.get( 'status', 'done' ) + id = params.get( 'id', None ) + if not id: + message = "No role ids received for managing users and groups" + trans.response.send_redirect( web.url_for( controller='admin', + action='roles', + message=message, + status='error' ) ) + role = get_role( trans, id ) + if params.get( 'role_members_edit_button', False ): + in_users = [ trans.sa_session.query( trans.app.model.User ).get( x ) for x in util.listify( params.in_users ) ] + for ura in role.users: + user = trans.sa_session.query( trans.app.model.User ).get( ura.user_id ) + if user not in in_users: + # Delete DefaultUserPermissions for previously associated users that have been removed from the role + for dup in user.default_permissions: + if role == dup.role: + trans.sa_session.delete( dup ) + # Delete DefaultHistoryPermissions for previously associated users that have been removed from the role + for history in user.histories: + for dhp in history.default_permissions: + if role == dhp.role: + trans.sa_session.delete( dhp ) + trans.sa_session.flush() + in_groups = [ trans.sa_session.query( trans.app.model.Group ).get( x ) for x in util.listify( params.in_groups ) ] + trans.app.security_agent.set_entity_role_associations( roles=[ role ], users=in_users, groups=in_groups ) + trans.sa_session.refresh( role ) + message = "Role '%s' has been updated with %d associated users and %d associated groups" % ( role.name, len( in_users ), len( in_groups ) ) + trans.response.send_redirect( web.url_for( controller='admin', + action='roles', + message=util.sanitize_text( message ), + status=status ) ) + in_users = [] + out_users = [] + in_groups = [] + out_groups = [] + for user in trans.sa_session.query( trans.app.model.User ) \ + .filter( trans.app.model.User.table.c.deleted==False ) \ + .order_by( trans.app.model.User.table.c.email ): + if user in [ x.user for x in role.users ]: + in_users.append( ( user.id, user.email ) ) + else: + out_users.append( ( user.id, user.email ) ) + for group in trans.sa_session.query( trans.app.model.Group ) \ + .filter( trans.app.model.Group.table.c.deleted==False ) \ + .order_by( trans.app.model.Group.table.c.name ): + if group in [ x.group for x in role.groups ]: + in_groups.append( ( group.id, group.name ) ) + else: + out_groups.append( ( group.id, group.name ) ) + library_dataset_actions = {} + if trans.webapp.name == 'galaxy': + # Build a list of tuples that are LibraryDatasetDatasetAssociationss followed by a list of actions + # whose DatasetPermissions is associated with the Role + # [ ( LibraryDatasetDatasetAssociation [ action, action ] ) ] + for dp in role.dataset_actions: + for ldda in trans.sa_session.query( trans.app.model.LibraryDatasetDatasetAssociation ) \ + .filter( trans.app.model.LibraryDatasetDatasetAssociation.dataset_id==dp.dataset_id ): + root_found = False + folder_path = '' + folder = ldda.library_dataset.folder + while not root_found: + folder_path = '%s / %s' % ( folder.name, folder_path ) + if not folder.parent: + root_found = True + else: + folder = folder.parent + folder_path = '%s %s' % ( folder_path, ldda.name ) + library = trans.sa_session.query( trans.app.model.Library ) \ + .filter( trans.app.model.Library.table.c.root_folder_id == folder.id ) \ + .first() + if library not in library_dataset_actions: + library_dataset_actions[ library ] = {} + try: + library_dataset_actions[ library ][ folder_path ].append( dp.action ) + except: + library_dataset_actions[ library ][ folder_path ] = [ dp.action ] + return trans.fill_template( '/admin/dataset_security/role/role.mako', + role=role, + in_users=in_users, + out_users=out_users, + in_groups=in_groups, + out_groups=out_groups, + library_dataset_actions=library_dataset_actions, + message=message, + status=status ) + @web.expose + @web.require_admin + def mark_role_deleted( self, trans, **kwd ): + params = util.Params( kwd ) + id = kwd.get( 'id', None ) + if not id: + message = "No role ids received for deleting" + trans.response.send_redirect( web.url_for( controller='admin', + action='roles', + message=message, + status='error' ) ) + ids = util.listify( id ) + message = "Deleted %d roles: " % len( ids ) + for role_id in ids: + role = get_role( trans, role_id ) + role.deleted = True + trans.sa_session.add( role ) + trans.sa_session.flush() + message += " %s " % role.name + trans.response.send_redirect( web.url_for( controller='admin', + action='roles', + message=util.sanitize_text( message ), + status='done' ) ) + @web.expose + @web.require_admin + def undelete_role( self, trans, **kwd ): + params = util.Params( kwd ) + id = kwd.get( 'id', None ) + if not id: + message = "No role ids received for undeleting" + trans.response.send_redirect( web.url_for( controller='admin', + action='roles', + message=message, + status='error' ) ) + ids = util.listify( id ) + count = 0 + undeleted_roles = "" + for role_id in ids: + role = get_role( trans, role_id ) + if not role.deleted: + message = "Role '%s' has not been deleted, so it cannot be undeleted." % role.name + trans.response.send_redirect( web.url_for( controller='admin', + action='roles', + message=util.sanitize_text( message ), + status='error' ) ) + role.deleted = False + trans.sa_session.add( role ) + trans.sa_session.flush() + count += 1 + undeleted_roles += " %s" % role.name + message = "Undeleted %d roles: %s" % ( count, undeleted_roles ) + trans.response.send_redirect( web.url_for( controller='admin', + action='roles', + message=util.sanitize_text( message ), + status='done' ) ) + @web.expose + @web.require_admin + def purge_role( self, trans, **kwd ): + # This method should only be called for a Role that has previously been deleted. + # Purging a deleted Role deletes all of the following from the database: + # - UserRoleAssociations where role_id == Role.id + # - DefaultUserPermissions where role_id == Role.id + # - DefaultHistoryPermissions where role_id == Role.id + # - GroupRoleAssociations where role_id == Role.id + # - DatasetPermissionss where role_id == Role.id + params = util.Params( kwd ) + id = kwd.get( 'id', None ) + if not id: + message = "No role ids received for purging" + trans.response.send_redirect( web.url_for( controller='admin', + action='roles', + message=util.sanitize_text( message ), + status='error' ) ) + ids = util.listify( id ) + message = "Purged %d roles: " % len( ids ) + for role_id in ids: + role = get_role( trans, role_id ) + if not role.deleted: + message = "Role '%s' has not been deleted, so it cannot be purged." % role.name + trans.response.send_redirect( web.url_for( controller='admin', + action='roles', + message=util.sanitize_text( message ), + status='error' ) ) + # Delete UserRoleAssociations + for ura in role.users: + user = trans.sa_session.query( trans.app.model.User ).get( ura.user_id ) + # Delete DefaultUserPermissions for associated users + for dup in user.default_permissions: + if role == dup.role: + trans.sa_session.delete( dup ) + # Delete DefaultHistoryPermissions for associated users + for history in user.histories: + for dhp in history.default_permissions: + if role == dhp.role: + trans.sa_session.delete( dhp ) + trans.sa_session.delete( ura ) + # Delete GroupRoleAssociations + for gra in role.groups: + trans.sa_session.delete( gra ) + # Delete DatasetPermissionss + for dp in role.dataset_actions: + trans.sa_session.delete( dp ) + trans.sa_session.flush() + message += " %s " % role.name + trans.response.send_redirect( web.url_for( controller='admin', + action='roles', + message=util.sanitize_text( message ), + status='done' ) ) + + # Galaxy Group Stuff + @web.expose + @web.require_admin + def groups( self, trans, **kwargs ): + if 'operation' in kwargs: + operation = kwargs['operation'].lower() + if operation == "groups": + return self.group( trans, **kwargs ) + if operation == "create": + return self.create_group( trans, **kwargs ) + if operation == "delete": + return self.mark_group_deleted( trans, **kwargs ) + if operation == "undelete": + return self.undelete_group( trans, **kwargs ) + if operation == "purge": + return self.purge_group( trans, **kwargs ) + if operation == "manage users and roles": + return self.manage_users_and_roles_for_group( trans, **kwargs ) + if operation == "rename": + return self.rename_group( trans, **kwargs ) + # Render the list view + return self.group_list_grid( trans, **kwargs ) + @web.expose + @web.require_admin + def rename_group( self, trans, **kwd ): + params = util.Params( kwd ) + message = util.restore_text( params.get( 'message', '' ) ) + status = params.get( 'status', 'done' ) + id = params.get( 'id', None ) + if not id: + message = "No group ids received for renaming" + trans.response.send_redirect( web.url_for( controller='admin', + action='groups', + message=message, + status='error' ) ) + group = get_group( trans, id ) + if params.get( 'rename_group_button', False ): + old_name = group.name + new_name = util.restore_text( params.name ) + if not new_name: + message = 'Enter a valid name' + status = 'error' + else: + existing_group = trans.sa_session.query( trans.app.model.Group ).filter( trans.app.model.Group.table.c.name==new_name ).first() + if existing_group and existing_group.id != group.id: + message = 'A group with that name already exists' + status = 'error' + else: + if group.name != new_name: + group.name = new_name + trans.sa_session.add( group ) + trans.sa_session.flush() + message = "Group '%s' has been renamed to '%s'" % ( old_name, new_name ) + return trans.response.send_redirect( web.url_for( controller='admin', + action='groups', + message=util.sanitize_text( message ), + status='done' ) ) + return trans.fill_template( '/admin/dataset_security/group/group_rename.mako', + group=group, + message=message, + status=status ) + @web.expose + @web.require_admin + def manage_users_and_roles_for_group( self, trans, **kwd ): + params = util.Params( kwd ) + message = util.restore_text( params.get( 'message', '' ) ) + status = params.get( 'status', 'done' ) + group = get_group( trans, params.id ) + if params.get( 'group_roles_users_edit_button', False ): + in_roles = [ trans.sa_session.query( trans.app.model.Role ).get( x ) for x in util.listify( params.in_roles ) ] + in_users = [ trans.sa_session.query( trans.app.model.User ).get( x ) for x in util.listify( params.in_users ) ] + trans.app.security_agent.set_entity_group_associations( groups=[ group ], roles=in_roles, users=in_users ) + trans.sa_session.refresh( group ) + message += "Group '%s' has been updated with %d associated roles and %d associated users" % ( group.name, len( in_roles ), len( in_users ) ) + trans.response.send_redirect( web.url_for( controller='admin', + action='groups', + message=util.sanitize_text( message ), + status=status ) ) + in_roles = [] + out_roles = [] + in_users = [] + out_users = [] + for role in trans.sa_session.query(trans.app.model.Role ) \ + .filter( trans.app.model.Role.table.c.deleted==False ) \ + .order_by( trans.app.model.Role.table.c.name ): + if role in [ x.role for x in group.roles ]: + in_roles.append( ( role.id, role.name ) ) + else: + out_roles.append( ( role.id, role.name ) ) + for user in trans.sa_session.query( trans.app.model.User ) \ + .filter( trans.app.model.User.table.c.deleted==False ) \ + .order_by( trans.app.model.User.table.c.email ): + if user in [ x.user for x in group.users ]: + in_users.append( ( user.id, user.email ) ) + else: + out_users.append( ( user.id, user.email ) ) + message += 'Group %s is currently associated with %d roles and %d users' % ( group.name, len( in_roles ), len( in_users ) ) + return trans.fill_template( '/admin/dataset_security/group/group.mako', + group=group, + in_roles=in_roles, + out_roles=out_roles, + in_users=in_users, + out_users=out_users, + message=message, + status=status ) + @web.expose + @web.require_admin + def create_group( self, trans, **kwd ): + params = util.Params( kwd ) + message = util.restore_text( params.get( 'message', '' ) ) + status = params.get( 'status', 'done' ) + name = util.restore_text( params.get( 'name', '' ) ) + in_users = util.listify( params.get( 'in_users', [] ) ) + out_users = util.listify( params.get( 'out_users', [] ) ) + in_roles = util.listify( params.get( 'in_roles', [] ) ) + out_roles = util.listify( params.get( 'out_roles', [] ) ) + create_role_for_group = params.get( 'create_role_for_group', '' ) + create_role_for_group_checked = CheckboxField.is_checked( create_role_for_group ) + ok = True + if params.get( 'create_group_button', False ): + if not name: + message = "Enter a valid name." + status = 'error' + ok = False + elif trans.sa_session.query( trans.app.model.Group ).filter( trans.app.model.Group.table.c.name==name ).first(): + message = "Group names must be unique and a group with that name already exists, so choose another name." + status = 'error' + ok = False + else: + # Create the group + group = trans.app.model.Group( name=name ) + trans.sa_session.add( group ) + trans.sa_session.flush() + # Create the UserRoleAssociations + for user in [ trans.sa_session.query( trans.app.model.User ).get( x ) for x in in_users ]: + uga = trans.app.model.UserGroupAssociation( user, group ) + trans.sa_session.add( uga ) + # Create the GroupRoleAssociations + for role in [ trans.sa_session.query( trans.app.model.Role ).get( x ) for x in in_roles ]: + gra = trans.app.model.GroupRoleAssociation( group, role ) + trans.sa_session.add( gra ) + if create_role_for_group_checked: + # Create the role + role = trans.app.model.Role( name=name, description='Role for group %s' % name ) + trans.sa_session.add( role ) + # Associate the role with the group + gra = trans.model.GroupRoleAssociation( group, role ) + trans.sa_session.add( gra ) + num_in_roles = len( in_roles ) + 1 + else: + num_in_roles = len( in_roles ) + trans.sa_session.flush() + message = "Group '%s' has been created with %d associated users and %d associated roles. " \ + % ( group.name, len( in_users ), num_in_roles ) + if create_role_for_group_checked: + message += 'One of the roles associated with this group is the newly created role with the same name.' + trans.response.send_redirect( web.url_for( controller='admin', + action='groups', + message=util.sanitize_text( message ), + status='done' ) ) + + + if ok: + for user in trans.sa_session.query( trans.app.model.User ) \ + .filter( trans.app.model.User.table.c.deleted==False ) \ + .order_by( trans.app.model.User.table.c.email ): + out_users.append( ( user.id, user.email ) ) + for role in trans.sa_session.query( trans.app.model.Role ) \ + .filter( trans.app.model.Role.table.c.deleted==False ) \ + .order_by( trans.app.model.Role.table.c.name ): + out_roles.append( ( role.id, role.name ) ) + return trans.fill_template( '/admin/dataset_security/group/group_create.mako', + name=name, + in_users=in_users, + out_users=out_users, + in_roles=in_roles, + out_roles=out_roles, + create_role_for_group_checked=create_role_for_group_checked, + message=message, + status=status ) + @web.expose + @web.require_admin + def mark_group_deleted( self, trans, **kwd ): + params = util.Params( kwd ) + id = params.get( 'id', None ) + if not id: + message = "No group ids received for marking deleted" + trans.response.send_redirect( web.url_for( controller='admin', + action='groups', + message=message, + status='error' ) ) + ids = util.listify( id ) + message = "Deleted %d groups: " % len( ids ) + for group_id in ids: + group = get_group( trans, group_id ) + group.deleted = True + trans.sa_session.add( group ) + trans.sa_session.flush() + message += " %s " % group.name + trans.response.send_redirect( web.url_for( controller='admin', + action='groups', + message=util.sanitize_text( message ), + status='done' ) ) + @web.expose + @web.require_admin + def undelete_group( self, trans, **kwd ): + params = util.Params( kwd ) + id = kwd.get( 'id', None ) + if not id: + message = "No group ids received for undeleting" + trans.response.send_redirect( web.url_for( controller='admin', + action='groups', + message=message, + status='error' ) ) + ids = util.listify( id ) + count = 0 + undeleted_groups = "" + for group_id in ids: + group = get_group( trans, group_id ) + if not group.deleted: + message = "Group '%s' has not been deleted, so it cannot be undeleted." % group.name + trans.response.send_redirect( web.url_for( controller='admin', + action='groups', + message=util.sanitize_text( message ), + status='error' ) ) + group.deleted = False + trans.sa_session.add( group ) + trans.sa_session.flush() + count += 1 + undeleted_groups += " %s" % group.name + message = "Undeleted %d groups: %s" % ( count, undeleted_groups ) + trans.response.send_redirect( web.url_for( controller='admin', + action='groups', + message=util.sanitize_text( message ), + status='done' ) ) + @web.expose + @web.require_admin + def purge_group( self, trans, **kwd ): + # This method should only be called for a Group that has previously been deleted. + # Purging a deleted Group simply deletes all UserGroupAssociations and GroupRoleAssociations. + params = util.Params( kwd ) + id = kwd.get( 'id', None ) + if not id: + message = "No group ids received for purging" + trans.response.send_redirect( web.url_for( controller='admin', + action='groups', + message=util.sanitize_text( message ), + status='error' ) ) + ids = util.listify( id ) + message = "Purged %d groups: " % len( ids ) + for group_id in ids: + group = get_group( trans, group_id ) + if not group.deleted: + # We should never reach here, but just in case there is a bug somewhere... + message = "Group '%s' has not been deleted, so it cannot be purged." % group.name + trans.response.send_redirect( web.url_for( controller='admin', + action='groups', + message=util.sanitize_text( message ), + status='error' ) ) + # Delete UserGroupAssociations + for uga in group.users: + trans.sa_session.delete( uga ) + # Delete GroupRoleAssociations + for gra in group.roles: + trans.sa_session.delete( gra ) + trans.sa_session.flush() + message += " %s " % group.name + trans.response.send_redirect( web.url_for( controller='admin', + action='groups', + message=util.sanitize_text( message ), + status='done' ) ) + + # Galaxy User Stuff + @web.expose + @web.require_admin + def create_new_user( self, trans, **kwd ): + return trans.response.send_redirect( web.url_for( controller='user', + action='create', + cntrller='admin' ) ) + @web.expose + @web.require_admin + def reset_user_password( self, trans, **kwd ): + user_id = kwd.get( 'id', None ) + if not user_id: + message = "No users received for resetting passwords." + trans.response.send_redirect( web.url_for( controller='admin', + action='users', + message=message, + status='error' ) ) + user_ids = util.listify( user_id ) + if 'reset_user_password_button' in kwd: + message = '' + status = '' + for user_id in user_ids: + user = get_user( trans, user_id ) + password = kwd.get( 'password', None ) + confirm = kwd.get( 'confirm' , None ) + if len( password ) < 6: + message = "Use a password of at least 6 characters." + status = 'error' + break + elif password != confirm: + message = "Passwords do not match." + status = 'error' + break + else: + user.set_password_cleartext( password ) + trans.sa_session.add( user ) + trans.sa_session.flush() + if not message and not status: + message = "Passwords reset for %d %s." % ( len( user_ids ), inflector.cond_plural( len( user_ids ), 'user' ) ) + status = 'done' + trans.response.send_redirect( web.url_for( controller='admin', + action='users', + message=util.sanitize_text( message ), + status=status ) ) + users = [ get_user( trans, user_id ) for user_id in user_ids ] + if len( user_ids ) > 1: + user_id = ','.join( user_ids ) + return trans.fill_template( '/admin/user/reset_password.mako', + id=user_id, + users=users, + password='', + confirm='' ) + @web.expose + @web.require_admin + def mark_user_deleted( self, trans, **kwd ): + id = kwd.get( 'id', None ) + if not id: + message = "No user ids received for deleting" + trans.response.send_redirect( web.url_for( controller='admin', + action='users', + message=message, + status='error' ) ) + ids = util.listify( id ) + message = "Deleted %d users: " % len( ids ) + for user_id in ids: + user = get_user( trans, user_id ) + user.deleted = True + trans.sa_session.add( user ) + trans.sa_session.flush() + message += " %s " % user.email + trans.response.send_redirect( web.url_for( controller='admin', + action='users', + message=util.sanitize_text( message ), + status='done' ) ) + @web.expose + @web.require_admin + def undelete_user( self, trans, **kwd ): + id = kwd.get( 'id', None ) + if not id: + message = "No user ids received for undeleting" + trans.response.send_redirect( web.url_for( controller='admin', + action='users', + message=message, + status='error' ) ) + ids = util.listify( id ) + count = 0 + undeleted_users = "" + for user_id in ids: + user = get_user( trans, user_id ) + if not user.deleted: + message = "User '%s' has not been deleted, so it cannot be undeleted." % user.email + trans.response.send_redirect( web.url_for( controller='admin', + action='users', + message=util.sanitize_text( message ), + status='error' ) ) + user.deleted = False + trans.sa_session.add( user ) + trans.sa_session.flush() + count += 1 + undeleted_users += " %s" % user.email + message = "Undeleted %d users: %s" % ( count, undeleted_users ) + trans.response.send_redirect( web.url_for( controller='admin', + action='users', + message=util.sanitize_text( message ), + status='done' ) ) + @web.expose + @web.require_admin + def purge_user( self, trans, **kwd ): + # This method should only be called for a User that has previously been deleted. + # We keep the User in the database ( marked as purged ), and stuff associated + # with the user's private role in case we want the ability to unpurge the user + # some time in the future. + # Purging a deleted User deletes all of the following: + # - History where user_id = User.id + # - HistoryDatasetAssociation where history_id = History.id + # - Dataset where HistoryDatasetAssociation.dataset_id = Dataset.id + # - UserGroupAssociation where user_id == User.id + # - UserRoleAssociation where user_id == User.id EXCEPT FOR THE PRIVATE ROLE + # - UserAddress where user_id == User.id + # Purging Histories and Datasets must be handled via the cleanup_datasets.py script + id = kwd.get( 'id', None ) + if not id: + message = "No user ids received for purging" + trans.response.send_redirect( web.url_for( controller='admin', + action='users', + message=util.sanitize_text( message ), + status='error' ) ) + ids = util.listify( id ) + message = "Purged %d users: " % len( ids ) + for user_id in ids: + user = get_user( trans, user_id ) + if not user.deleted: + # We should never reach here, but just in case there is a bug somewhere... + message = "User '%s' has not been deleted, so it cannot be purged." % user.email + trans.response.send_redirect( web.url_for( controller='admin', + action='users', + message=util.sanitize_text( message ), + status='error' ) ) + private_role = trans.app.security_agent.get_private_user_role( user ) + # Delete History + for h in user.active_histories: + trans.sa_session.refresh( h ) + for hda in h.active_datasets: + # Delete HistoryDatasetAssociation + d = trans.sa_session.query( trans.app.model.Dataset ).get( hda.dataset_id ) + # Delete Dataset + if not d.deleted: + d.deleted = True + trans.sa_session.add( d ) + hda.deleted = True + trans.sa_session.add( hda ) + h.deleted = True + trans.sa_session.add( h ) + # Delete UserGroupAssociations + for uga in user.groups: + trans.sa_session.delete( uga ) + # Delete UserRoleAssociations EXCEPT FOR THE PRIVATE ROLE + for ura in user.roles: + if ura.role_id != private_role.id: + trans.sa_session.delete( ura ) + # Delete UserAddresses + for address in user.addresses: + trans.sa_session.delete( address ) + # Purge the user + user.purged = True + trans.sa_session.add( user ) + trans.sa_session.flush() + message += "%s " % user.email + trans.response.send_redirect( web.url_for( controller='admin', + action='users', + message=util.sanitize_text( message ), + status='done' ) ) + @web.expose + @web.require_admin + def users( self, trans, **kwd ): + if 'operation' in kwd: + operation = kwd['operation'].lower() + if operation == "roles": + return self.user( trans, **kwd ) + elif operation == "reset password": + return self.reset_user_password( trans, **kwd ) + elif operation == "delete": + return self.mark_user_deleted( trans, **kwd ) + elif operation == "undelete": + return self.undelete_user( trans, **kwd ) + elif operation == "purge": + return self.purge_user( trans, **kwd ) + elif operation == "create": + return self.create_new_user( trans, **kwd ) + elif operation == "information": + user_id = kwd.get( 'id', None ) + if not user_id: + kwd[ 'message' ] = util.sanitize_text( "Invalid user id (%s) received" % str( user_id ) ) + kwd[ 'status' ] = 'error' + else: + return trans.response.send_redirect( web.url_for( controller='user', + action='manage_user_info', + cntrller='admin', + **kwd ) ) + elif operation == "manage roles and groups": + return self.manage_roles_and_groups_for_user( trans, **kwd ) + if trans.app.config.allow_user_deletion: + if self.delete_operation not in self.user_list_grid.operations: + self.user_list_grid.operations.append( self.delete_operation ) + if self.undelete_operation not in self.user_list_grid.operations: + self.user_list_grid.operations.append( self.undelete_operation ) + if self.purge_operation not in self.user_list_grid.operations: + self.user_list_grid.operations.append( self.purge_operation ) + # Render the list view + return self.user_list_grid( trans, **kwd ) + @web.expose + @web.require_admin + def name_autocomplete_data( self, trans, q=None, limit=None, timestamp=None ): + """Return autocomplete data for user emails""" + ac_data = "" + for user in trans.sa_session.query( User ).filter_by( deleted=False ).filter( func.lower( User.email ).like( q.lower() + "%" ) ): + ac_data = ac_data + user.email + "\n" + return ac_data + @web.expose + @web.require_admin + def manage_roles_and_groups_for_user( self, trans, **kwd ): + user_id = kwd.get( 'id', None ) + message = '' + status = '' + if not user_id: + message += "Invalid user id (%s) received" % str( user_id ) + trans.response.send_redirect( web.url_for( controller='admin', + action='users', + message=util.sanitize_text( message ), + status='error' ) ) + user = get_user( trans, user_id ) + private_role = trans.app.security_agent.get_private_user_role( user ) + if kwd.get( 'user_roles_groups_edit_button', False ): + # Make sure the user is not dis-associating himself from his private role + out_roles = kwd.get( 'out_roles', [] ) + if out_roles: + out_roles = [ trans.sa_session.query( trans.app.model.Role ).get( x ) for x in util.listify( out_roles ) ] + if private_role in out_roles: + message += "You cannot eliminate a user's private role association. " + status = 'error' + in_roles = kwd.get( 'in_roles', [] ) + if in_roles: + in_roles = [ trans.sa_session.query( trans.app.model.Role ).get( x ) for x in util.listify( in_roles ) ] + out_groups = kwd.get( 'out_groups', [] ) + if out_groups: + out_groups = [ trans.sa_session.query( trans.app.model.Group ).get( x ) for x in util.listify( out_groups ) ] + in_groups = kwd.get( 'in_groups', [] ) + if in_groups: + in_groups = [ trans.sa_session.query( trans.app.model.Group ).get( x ) for x in util.listify( in_groups ) ] + if in_roles: + trans.app.security_agent.set_entity_user_associations( users=[ user ], roles=in_roles, groups=in_groups ) + trans.sa_session.refresh( user ) + message += "User '%s' has been updated with %d associated roles and %d associated groups (private roles are not displayed)" % \ + ( user.email, len( in_roles ), len( in_groups ) ) + trans.response.send_redirect( web.url_for( controller='admin', + action='users', + message=util.sanitize_text( message ), + status='done' ) ) + in_roles = [] + out_roles = [] + in_groups = [] + out_groups = [] + for role in trans.sa_session.query( trans.app.model.Role ).filter( trans.app.model.Role.table.c.deleted==False ) \ + .order_by( trans.app.model.Role.table.c.name ): + if role in [ x.role for x in user.roles ]: + in_roles.append( ( role.id, role.name ) ) + elif role.type != trans.app.model.Role.types.PRIVATE: + # There is a 1 to 1 mapping between a user and a PRIVATE role, so private roles should + # not be listed in the roles form fields, except for the currently selected user's private + # role, which should always be in in_roles. The check above is added as an additional + # precaution, since for a period of time we were including private roles in the form fields. + out_roles.append( ( role.id, role.name ) ) + for group in trans.sa_session.query( trans.app.model.Group ).filter( trans.app.model.Group.table.c.deleted==False ) \ + .order_by( trans.app.model.Group.table.c.name ): + if group in [ x.group for x in user.groups ]: + in_groups.append( ( group.id, group.name ) ) + else: + out_groups.append( ( group.id, group.name ) ) + message += "User '%s' is currently associated with %d roles and is a member of %d groups" % \ + ( user.email, len( in_roles ), len( in_groups ) ) + if not status: + status = 'done' + return trans.fill_template( '/admin/user/user.mako', + user=user, + in_roles=in_roles, + out_roles=out_roles, + in_groups=in_groups, + out_groups=out_groups, + message=message, + status=status ) + @web.expose + @web.require_admin + def memdump( self, trans, ids = 'None', sorts = 'None', pages = 'None', new_id = None, new_sort = None, **kwd ): + if self.app.memdump is None: + return trans.show_error_message( "Memdump is not enabled (set <code>use_memdump = True</code> in universe_wsgi.ini)" ) + heap = self.app.memdump.get() + p = util.Params( kwd ) + msg = None + if p.dump: + heap = self.app.memdump.get( update = True ) + msg = "Heap dump complete" + elif p.setref: + self.app.memdump.setref() + msg = "Reference point set (dump to see delta from this point)" + ids = ids.split( ',' ) + sorts = sorts.split( ',' ) + if new_id is not None: + ids.append( new_id ) + sorts.append( 'None' ) + elif new_sort is not None: + sorts[-1] = new_sort + breadcrumb = "<a href='%s' class='breadcrumb'>heap</a>" % web.url_for() + # new lists so we can assemble breadcrumb links + new_ids = [] + new_sorts = [] + for id, sort in zip( ids, sorts ): + new_ids.append( id ) + if id != 'None': + breadcrumb += "<a href='%s' class='breadcrumb'>[%s]</a>" % ( web.url_for( ids=','.join( new_ids ), sorts=','.join( new_sorts ) ), id ) + heap = heap[int(id)] + new_sorts.append( sort ) + if sort != 'None': + breadcrumb += "<a href='%s' class='breadcrumb'>.by('%s')</a>" % ( web.url_for( ids=','.join( new_ids ), sorts=','.join( new_sorts ) ), sort ) + heap = heap.by( sort ) + ids = ','.join( new_ids ) + sorts = ','.join( new_sorts ) + if p.theone: + breadcrumb += ".theone" + heap = heap.theone + return trans.fill_template( '/admin/memdump.mako', heap = heap, ids = ids, sorts = sorts, breadcrumb = breadcrumb, msg = msg ) + + @web.expose + @web.require_admin + def jobs( self, trans, stop = [], stop_msg = None, cutoff = 180, job_lock = None, ajl_submit = None, **kwd ): + deleted = [] + msg = None + status = None + if self.app.config.job_manager != self.app.config.server_name: + return trans.show_error_message( 'This Galaxy instance (%s) is not the job manager (%s). If using multiple servers, please directly access the job manager instance to manage jobs.' % (self.app.config.server_name, self.app.config.job_manager) ) + job_ids = util.listify( stop ) + if job_ids and stop_msg in [ None, '' ]: + msg = 'Please enter an error message to display to the user describing why the job was terminated' + status = 'error' + elif job_ids: + if stop_msg[-1] not in string.punctuation: + stop_msg += '.' + for job_id in job_ids: + trans.app.job_manager.job_stop_queue.put( job_id, error_msg="This job was stopped by an administrator: %s For more information or help" % stop_msg ) + deleted.append( str( job_id ) ) + if deleted: + msg = 'Queued job' + if len( deleted ) > 1: + msg += 's' + msg += ' for deletion: ' + msg += ', '.join( deleted ) + status = 'done' + if ajl_submit: + if job_lock == 'on': + trans.app.job_manager.job_queue.job_lock = True + else: + trans.app.job_manager.job_queue.job_lock = False + cutoff_time = datetime.utcnow() - timedelta( seconds=int( cutoff ) ) + jobs = trans.sa_session.query( trans.app.model.Job ) \ + .filter( and_( trans.app.model.Job.table.c.update_time < cutoff_time, + or_( trans.app.model.Job.state == trans.app.model.Job.states.NEW, + trans.app.model.Job.state == trans.app.model.Job.states.QUEUED, + trans.app.model.Job.state == trans.app.model.Job.states.RUNNING, + trans.app.model.Job.state == trans.app.model.Job.states.UPLOAD ) ) ) \ + .order_by( trans.app.model.Job.table.c.update_time.desc() ) + last_updated = {} + for job in jobs: + delta = datetime.utcnow() - job.update_time + if delta > timedelta( minutes=60 ): + last_updated[job.id] = '%s hours' % int( delta.seconds / 60 / 60 ) + else: + last_updated[job.id] = '%s minutes' % int( delta.seconds / 60 ) + return trans.fill_template( '/admin/jobs.mako', + jobs = jobs, + last_updated = last_updated, + cutoff = cutoff, + msg = msg, + status = status, + job_lock = trans.app.job_manager.job_queue.job_lock ) + +## ---- Utility methods ------------------------------------------------------- + +def get_ids_of_tool_shed_repositories_being_installed( trans, as_string=False ): + installing_repository_ids = [] + new_status = trans.model.ToolShedRepository.installation_status.NEW + cloning_status = trans.model.ToolShedRepository.installation_status.CLONING + setting_tool_versions_status = trans.model.ToolShedRepository.installation_status.SETTING_TOOL_VERSIONS + installing_dependencies_status = trans.model.ToolShedRepository.installation_status.INSTALLING_TOOL_DEPENDENCIES + loading_datatypes_status = trans.model.ToolShedRepository.installation_status.LOADING_PROPRIETARY_DATATYPES + for tool_shed_repository in trans.sa_session.query( trans.model.ToolShedRepository ) \ + .filter( or_( trans.model.ToolShedRepository.status == new_status, + trans.model.ToolShedRepository.status == cloning_status, + trans.model.ToolShedRepository.status == setting_tool_versions_status, + trans.model.ToolShedRepository.status == installing_dependencies_status, + trans.model.ToolShedRepository.status == loading_datatypes_status ) ): + installing_repository_ids.append( trans.security.encode_id( tool_shed_repository.id ) ) + if as_string: + return ','.join( installing_repository_ids ) + return installing_repository_ids + +def get_user( trans, user_id ): + """Get a User from the database by id.""" + user = trans.sa_session.query( trans.model.User ).get( trans.security.decode_id( user_id ) ) + if not user: + return trans.show_error_message( "User not found for id (%s)" % str( user_id ) ) + return user +def get_user_by_username( trans, username ): + """Get a user from the database by username""" + # TODO: Add exception handling here. + return trans.sa_session.query( trans.model.User ) \ + .filter( trans.model.User.table.c.username == username ) \ + .one() +def get_role( trans, id ): + """Get a Role from the database by id.""" + # Load user from database + id = trans.security.decode_id( id ) + role = trans.sa_session.query( trans.model.Role ).get( id ) + if not role: + return trans.show_error_message( "Role not found for id (%s)" % str( id ) ) + return role +def get_group( trans, id ): + """Get a Group from the database by id.""" + # Load user from database + id = trans.security.decode_id( id ) + group = trans.sa_session.query( trans.model.Group ).get( id ) + if not group: + return trans.show_error_message( "Group not found for id (%s)" % str( id ) ) + return group +def get_quota( trans, id ): + """Get a Quota from the database by id.""" + # Load user from database + id = trans.security.decode_id( id ) + quota = trans.sa_session.query( trans.model.Quota ).get( id ) + return quota \ No newline at end of file diff -r ee2feed164a9efc9201409b3e6191e2707ec3e18 -r 5b977db5fc50b50caa5309838f37a77010f1e2b7 lib/galaxy/web/framework/__init__.py --- a/lib/galaxy/web/framework/__init__.py +++ b/lib/galaxy/web/framework/__init__.py @@ -607,7 +607,7 @@ Update the session cookie to match the current session. """ self.set_cookie( self.security.encode_guid( self.galaxy_session.session_key ), name=name, path=self.app.config.cookie_path ) - def handle_user_login( self, user, webapp ): + def handle_user_login( self, user ): """ Login a new user (possibly newly created) - create a new session @@ -621,7 +621,7 @@ prev_galaxy_session.is_valid = False # Define a new current_session self.galaxy_session = self.__create_new_session( prev_galaxy_session, user ) - if webapp == 'galaxy': + if self.webapp.name == 'galaxy': cookie_name = 'galaxysession' # Associated the current user's last accessed history (if exists) with their new session history = None diff -r ee2feed164a9efc9201409b3e6191e2707ec3e18 -r 5b977db5fc50b50caa5309838f37a77010f1e2b7 lib/galaxy/web/framework/helpers/grids.py --- a/lib/galaxy/web/framework/helpers/grids.py +++ b/lib/galaxy/web/framework/helpers/grids.py @@ -53,7 +53,8 @@ def __call__( self, trans, **kwargs ): # Get basics. - webapp = get_webapp( trans, **kwargs ) + # FIXME: pretty sure this is only here to pass along, can likely be eliminated + webapp = trans.webapp.name status = kwargs.get( 'status', None ) message = kwargs.get( 'message', None ) # Build a base filter and sort key that is the combination of the saved state and defaults. diff -r ee2feed164a9efc9201409b3e6191e2707ec3e18 -r 5b977db5fc50b50caa5309838f37a77010f1e2b7 lib/galaxy/webapps/community/controllers/admin.py --- a/lib/galaxy/webapps/community/controllers/admin.py +++ b/lib/galaxy/webapps/community/controllers/admin.py @@ -1,4 +1,5 @@ from galaxy.web.base.controller import * +from galaxy.web.base.controllers.admin import Admin from galaxy.webapps.community import model from galaxy.model.orm import * from galaxy.web.framework.helpers import time_ago, iff, grids diff -r ee2feed164a9efc9201409b3e6191e2707ec3e18 -r 5b977db5fc50b50caa5309838f37a77010f1e2b7 lib/galaxy/webapps/galaxy/api/quotas.py --- a/lib/galaxy/webapps/galaxy/api/quotas.py +++ b/lib/galaxy/webapps/galaxy/api/quotas.py @@ -2,7 +2,8 @@ API operations on Quota objects. """ import logging -from galaxy.web.base.controller import BaseAPIController, Admin, UsesQuotaMixin, url_for +from galaxy.web.base.controller import BaseAPIController, UsesQuotaMixin, url_for +from galaxy.web.base.controllers.admin import Admin from galaxy import web, util from elementtree.ElementTree import XML diff -r ee2feed164a9efc9201409b3e6191e2707ec3e18 -r 5b977db5fc50b50caa5309838f37a77010f1e2b7 lib/galaxy/webapps/galaxy/controllers/admin.py --- a/lib/galaxy/webapps/galaxy/controllers/admin.py +++ b/lib/galaxy/webapps/galaxy/controllers/admin.py @@ -1,4 +1,5 @@ from galaxy.web.base.controller import * +from galaxy.web.base.controllers.admin import Admin from galaxy import model from galaxy.model.orm import * from galaxy.web.framework.helpers import time_ago, iff, grids diff -r ee2feed164a9efc9201409b3e6191e2707ec3e18 -r 5b977db5fc50b50caa5309838f37a77010f1e2b7 lib/galaxy/webapps/galaxy/controllers/user.py --- a/lib/galaxy/webapps/galaxy/controllers/user.py +++ b/lib/galaxy/webapps/galaxy/controllers/user.py @@ -14,7 +14,7 @@ from galaxy.security.validate_user_input import validate_email, validate_publicname, validate_password, transform_publicname from galaxy.util.json import from_json_string, to_json_string from galaxy.web import url_for -from galaxy.web.base.controller import BaseUIController, UsesFormDefinitionsMixin, get_webapp +from galaxy.web.base.controller import BaseUIController, UsesFormDefinitionsMixin from galaxy.web.form_builder import CheckboxField, build_select_field from galaxy.web.framework.helpers import time_ago, grids @@ -49,10 +49,10 @@ installed_len_files = None @web.expose - def index( self, trans, cntrller, webapp='galaxy', **kwd ): - return trans.fill_template( '/user/index.mako', cntrller=cntrller, webapp=webapp ) + def index( self, trans, cntrller, **kwd ): + return trans.fill_template( '/user/index.mako', cntrller=cntrller ) @web.expose - def openid_auth( self, trans, webapp='galaxy', **kwd ): + def openid_auth( self, trans, **kwd ): '''Handles user request to access an OpenID provider''' if not trans.app.config.enable_openid: return trans.show_error_message( 'OpenID authentication is not enabled in this instance of Galaxy' ) @@ -102,7 +102,7 @@ message=message, status='error' ) ) @web.expose - def openid_process( self, trans, webapp='galaxy', **kwd ): + def openid_process( self, trans, **kwd ): '''Handle's response from OpenID Providers''' if not trans.app.config.enable_openid: return trans.show_error_message( 'OpenID authentication is not enabled in this instance of Galaxy' ) @@ -178,7 +178,7 @@ message=message, status=status ) ) elif user_openid.user: - trans.handle_user_login( user_openid.user, webapp ) + trans.handle_user_login( user_openid.user ) trans.log_event( "User logged in via OpenID: %s" % display_identifier ) openid_provider_obj.post_authentication( trans, trans.app.openid_manager, info ) if not redirect: @@ -222,7 +222,7 @@ message=message, status=status ) ) @web.expose - def openid_associate( self, trans, cntrller='user', webapp='galaxy', **kwd ): + def openid_associate( self, trans, cntrller='user', **kwd ): '''Associates a user with an OpenID log in''' if not trans.app.config.enable_openid: return trans.show_error_message( 'OpenID authentication is not enabled in this instance of Galaxy' ) @@ -241,7 +241,7 @@ elif is_admin: return trans.show_error_message( 'Associating OpenIDs with accounts cannot be done by administrators.' ) if kwd.get( 'login_button', False ): - message, status, user, success = self.__validate_login( trans, webapp, **kwd ) + message, status, user, success = self.__validate_login( trans, **kwd ) if success: openid_objs = [] for openid in openids: @@ -285,7 +285,7 @@ error = 'User registration is disabled. Please contact your Galaxy administrator for an account.' else: # Check email and password validity - error = self.__validate( trans, params, email, password, confirm, username, webapp ) + error = self.__validate( trans, params, email, password, confirm, username ) if not error: # all the values are valid message, status, user, success = self.__register( trans, @@ -330,7 +330,7 @@ else: message = error status = 'error' - if webapp == 'galaxy': + 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: @@ -342,7 +342,6 @@ user_type_form_definition = None widgets = [] return trans.fill_template( '/user/openid_associate.mako', - webapp=webapp, cntrller=cntrller, email=email, password='', @@ -362,7 +361,7 @@ openids=openids ) @web.expose @web.require_login( 'manage OpenIDs' ) - def openid_disassociate( self, trans, webapp='galaxy', **kwd ): + def openid_disassociate( self, trans, **kwd ): '''Disassociates a user with an OpenID''' if not trans.app.config.enable_openid: return trans.show_error_message( 'OpenID authentication is not enabled in this instance of Galaxy' ) @@ -404,7 +403,7 @@ @web.expose @web.require_login( 'manage OpenIDs' ) - def openid_manage( self, trans, webapp='galaxy', **kwd ): + def openid_manage( self, trans, **kwd ): '''Manage OpenIDs for user''' if not trans.app.config.enable_openid: return trans.show_error_message( 'OpenID authentication is not enabled in this instance of Galaxy' ) @@ -421,7 +420,7 @@ return self.user_openid_grid( trans, **kwd ) @web.expose - def login( self, trans, webapp='galaxy', redirect_url='', refresh_frames=[], **kwd ): + def login( self, trans, redirect_url='', refresh_frames=[], **kwd ): '''Handle Galaxy Log in''' redirect = kwd.get( 'redirect', trans.request.referer ).strip() use_panels = util.string_as_bool( kwd.get( 'use_panels', False ) ) @@ -430,16 +429,13 @@ header = '' user = None email = kwd.get( 'email', '' ) - #Sanitize webapp login here, once, since it can be reflected to the user in messages/etc. - #Only text is valid. - webapp = util.sanitize_text(webapp) if kwd.get( 'login_button', False ): - if webapp == 'galaxy' and not refresh_frames: + if trans.webapp.name == 'galaxy' and not refresh_frames: if trans.app.config.require_login: refresh_frames = [ 'masthead', 'history', 'tools' ] else: refresh_frames = [ 'masthead', 'history' ] - message, status, user, success = self.__validate_login( trans, webapp, **kwd ) + message, status, user, success = self.__validate_login( trans, **kwd ) if success and redirect and not redirect.startswith( trans.request.base + url_for( controller='user', action='logout' ) ): redirect_url = redirect elif success: @@ -447,18 +443,17 @@ if not user and trans.app.config.require_login: if trans.app.config.allow_user_creation: create_account_str = " If you don't already have an account, <a href='%s'>you may create one</a>." % \ - web.url_for( action='create', cntrller='user', webapp=webapp ) - if webapp == 'galaxy': + web.url_for( action='create', cntrller='user' ) + if trans.webapp.name == 'galaxy': header = require_login_template % ( "Galaxy instance", create_account_str ) else: header = require_login_template % ( "Galaxy tool shed", create_account_str ) else: - if webapp == 'galaxy': + if trans.webapp.name == 'galaxy': header = require_login_template % ( "Galaxy instance", "" ) else: header = require_login_template % ( "Galaxy tool shed", "" ) return trans.fill_template( '/user/login.mako', - webapp=webapp, email=email, header=header, use_panels=use_panels, @@ -469,7 +464,7 @@ status=status, openid_providers=trans.app.openid_providers, active_view="user" ) - def __validate_login( self, trans, webapp='galaxy', **kwd ): + def __validate_login( self, trans, **kwd ): message = kwd.get( 'message', '' ) status = kwd.get( 'status', 'done' ) email = kwd.get( 'email', '' ) @@ -490,8 +485,8 @@ message = "Invalid password" status = 'error' else: - trans.handle_user_login( user, webapp ) - if webapp == 'galaxy': + trans.handle_user_login( user ) + if trans.webapp.name == 'galaxy': trans.log_event( "User logged in" ) message = 'You are now logged in as %s.<br>You can <a target="_top" href="%s">go back to the page you were visiting</a> or <a target="_top" href="%s">go to the home page</a>.' % \ ( user.email, redirect, url_for( '/' ) ) @@ -501,8 +496,8 @@ return ( message, status, user, success ) @web.expose - def logout( self, trans, webapp='galaxy', logout_all=False ): - if webapp == 'galaxy': + def logout( self, trans, logout_all=False ): + if trans.webapp.name == 'galaxy': if trans.app.config.require_login: refresh_frames = [ 'masthead', 'history', 'tools' ] else: @@ -515,7 +510,6 @@ message = 'You have been logged out.<br>You can log in again, <a target="_top" href="%s">go back to the page you were visiting</a> or <a target="_top" href="%s">go to the home page</a>.' % \ ( trans.request.referer, url_for( '/' ) ) return trans.fill_template( '/user/logout.mako', - webapp=webapp, refresh_frames=refresh_frames, message=message, status='done', @@ -526,7 +520,6 @@ params = util.Params( kwd ) message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) - webapp = get_webapp( trans, **kwd ) use_panels = util.string_as_bool( kwd.get( 'use_panels', True ) ) email = util.restore_text( params.get( 'email', '' ) ) # Do not sanitize passwords, so take from kwd @@ -543,7 +536,7 @@ status = 'error' else: if not refresh_frames: - if webapp == 'galaxy': + if trans.webapp.name == 'galaxy': if trans.app.config.require_login: refresh_frames = [ 'masthead', 'history', 'tools' ] else: @@ -553,19 +546,19 @@ # Create the user, save all the user info and login to Galaxy if params.get( 'create_user_button', False ): # Check email and password validity - message = self.__validate( trans, params, email, password, confirm, username, webapp ) + message = self.__validate( trans, params, email, password, confirm, username ) if not message: # All the values are valid message, status, user, success = self.__register( trans, cntrller, subscribe_checked, **kwd ) - if webapp == 'community': + if trans.webapp.name == 'community': redirect_url = url_for( '/' ) if success and not is_admin: # The handle_user_login() method has a call to the history_set_default_permissions() method # (needed when logging in with a history), user needs to have default permissions set before logging in - trans.handle_user_login( user, webapp ) + trans.handle_user_login( user ) trans.log_event( "User created a new account" ) trans.log_event( "User logged in" ) if success and is_admin: @@ -577,7 +570,7 @@ status=status ) ) else: status = 'error' - if webapp == 'galaxy': + 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: @@ -596,7 +589,6 @@ user_type_fd_id_select_field=user_type_fd_id_select_field, user_type_form_definition=user_type_form_definition, widgets=widgets, - webapp=webapp, use_panels=use_panels, redirect=redirect, redirect_url=redirect_url, @@ -608,7 +600,6 @@ email = util.restore_text( kwd.get( 'email', '' ) ) password = kwd.get( 'password', '' ) username = util.restore_text( kwd.get( 'username', '' ) ) - webapp = get_webapp( trans, **kwd ) status = kwd.get( 'status', 'done' ) is_admin = cntrller == 'admin' and trans.user_is_admin() user = trans.app.model.User( email=email ) @@ -618,7 +609,7 @@ trans.sa_session.flush() trans.app.security_agent.create_private_user_role( user ) error = '' - if webapp == 'galaxy': + if trans.webapp.name == 'galaxy': # We set default user permissions, before we log in and set the default history permissions trans.app.security_agent.user_set_default_permissions( user, default_access_private=trans.app.config.new_user_dataset_access_role_default_private ) @@ -654,7 +645,7 @@ if not error and not is_admin: # The handle_user_login() method has a call to the history_set_default_permissions() method # (needed when logging in with a history), user needs to have default permissions set before logging in - trans.handle_user_login( user, webapp ) + trans.handle_user_login( user ) trans.log_event( "User created a new account" ) trans.log_event( "User logged in" ) elif not error: @@ -706,14 +697,13 @@ user = trans.user if not user: raise AssertionError, "The user id (%s) is not valid" % str( user_id ) - webapp = get_webapp( trans, **kwd ) email = util.restore_text( params.get( 'email', user.email ) ) username = util.restore_text( params.get( 'username', '' ) ) if not username: username = user.username message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) - if webapp == 'galaxy': + 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: @@ -742,7 +732,6 @@ widgets=widgets, addresses=addresses, show_filter=show_filter, - webapp=webapp, message=message, status=status ) else: @@ -751,7 +740,6 @@ user=user, email=email, username=username, - webapp=webapp, message=message, status=status ) @@ -761,7 +749,6 @@ def edit_username( self, trans, cntrller, **kwd ): params = util.Params( kwd ) is_admin = cntrller == 'admin' and trans.user_is_admin() - webapp = get_webapp( trans, **kwd ) message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) user_id = params.get( 'user_id', None ) @@ -784,14 +771,12 @@ cntrller=cntrller, user=user, username=user.username, - webapp=webapp, message=message, status=status ) @web.expose def edit_info( self, trans, cntrller, **kwd ): params = util.Params( kwd ) is_admin = cntrller == 'admin' and trans.user_is_admin() - webapp = get_webapp( trans, **kwd ) message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) user_id = params.get( 'user_id', None ) @@ -885,7 +870,7 @@ trans.sa_session.add( user ) trans.sa_session.flush() message = "The user information has been updated with the changes." - if user and webapp == 'galaxy' and is_admin: + 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: @@ -897,7 +882,7 @@ cntrller=cntrller, **kwd ) ) @web.expose - def reset_password( self, trans, email=None, webapp='galaxy', **kwd ): + def reset_password( self, trans, email=None, **kwd ): if trans.app.config.smtp_server is None: return trans.show_error_message( "Mail is not configured for this Galaxy instance. Please contact an administrator." ) message = util.restore_text( kwd.get( 'message', '' ) ) @@ -941,12 +926,11 @@ elif email is None: email = "" return trans.fill_template( '/user/reset_password.mako', - webapp=webapp, message=message, status=status ) - def __validate( self, trans, params, email, password, confirm, username, webapp ): + def __validate( self, trans, params, email, password, confirm, username ): # If coming from the community webapp, we'll require a public user name - if webapp == 'community' and not username: + if trans.webapp.name == 'community' and not username: return "A public user name is required" message = validate_email( trans, email ) if not message: @@ -954,7 +938,7 @@ if not message and username: message = validate_publicname( trans, username ) if not message: - if webapp == 'galaxy': + if trans.webapp.name == 'galaxy': if self.get_all_forms( trans, filter=dict( deleted=False ), form_type=trans.app.model.FormDefinition.types.USER_INFO ): diff -r ee2feed164a9efc9201409b3e6191e2707ec3e18 -r 5b977db5fc50b50caa5309838f37a77010f1e2b7 templates/user/dbkeys.mako --- a/templates/user/dbkeys.mako +++ b/templates/user/dbkeys.mako @@ -1,11 +1,7 @@ <%! def inherit(context): if context.get('use_panels'): - if context.get('webapp'): - webapp = context.get('webapp') - else: - webapp = 'galaxy' - return '/webapps/%s/base_panels.mako' % webapp + return '/webapps/%s/base_panels.mako' % t.webapp.name else: return '/base.mako' %> diff -r ee2feed164a9efc9201409b3e6191e2707ec3e18 -r 5b977db5fc50b50caa5309838f37a77010f1e2b7 templates/user/index.mako --- a/templates/user/index.mako +++ b/templates/user/index.mako @@ -9,27 +9,27 @@ <h2>${_('User preferences')}</h2><p>You are currently logged in as ${trans.user.email}.</p><ul> - %if webapp == 'galaxy': - <li><a href="${h.url_for( controller='user', action='manage_user_info', cntrller=cntrller, webapp=webapp )}">${_('Manage your information')}</a></li> - <li><a href="${h.url_for( controller='user', action='set_default_permissions', cntrller=cntrller, webapp=webapp )}">${_('Change default permissions')}</a> for new histories</li> - <li><a href="${h.url_for( controller='user', action='api_keys', cntrller=cntrller, webapp=webapp )}">${_('Manage your API keys')}</a></li> + %if t.webapp.name == 'galaxy': + <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='set_default_permissions', cntrller=cntrller )}">${_('Change default permissions')}</a> for new histories</li> + <li><a href="${h.url_for( controller='user', action='api_keys', cntrller=cntrller )}">${_('Manage your API keys')}</a></li> %if trans.app.config.enable_openid: - <li><a href="${h.url_for( controller='user', action='openid_manage', cntrller=cntrller, webapp=webapp )}">${_('Manage OpenIDs')}</a> linked to your account</li> + <li><a href="${h.url_for( controller='user', action='openid_manage', cntrller=cntrller )}">${_('Manage OpenIDs')}</a> linked to your account</li> %endif %if trans.app.config.use_remote_user: %if trans.app.config.remote_user_logout_href: <li><a href="${trans.app.config.remote_user_logout_href}" target="_top">${_('Logout')}</a></li> %endif %else: - <li><a href="${h.url_for( controller='user', action='logout', webapp=webapp, logout_all=True )}" target="_top">${_('Logout')}</a> ${_('of all user sessions')}</li> + <li><a href="${h.url_for( controller='user', action='logout', logout_all=True )}" target="_top">${_('Logout')}</a> ${_('of all user sessions')}</li> %endif %else: - <li><a href="${h.url_for( controller='user', action='manage_user_info', cntrller=cntrller, webapp=webapp )}">${_('Manage your information')}</a></li> - <li><a href="${h.url_for( controller='repository', action='manage_email_alerts', cntrller=cntrller, webapp=webapp )}">${_('Manage your email alerts')}</a></li> - <li><a href="${h.url_for( controller='user', action='logout', webapp=webapp, logout_all=True )}" target="_top">${_('Logout')}</a> ${_('of all user sessions')}</li> + <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='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> %endif </ul> - %if webapp == 'galaxy': + %if t.webapp.name == 'galaxy': <p> You are using <strong>${trans.user.get_disk_usage( nice_size=True )}</strong> of disk space in this Galaxy instance. %if trans.app.config.enable_quotas: @@ -43,7 +43,7 @@ <p>${n_('You are currently not logged in.')}</p> %endif <ul> - <li><a href="${h.url_for( action='login', webapp=webapp )}">${_('Login')}</li> - <li><a href="${h.url_for( action='create', cntrller='user', webapp=webapp )}">${_('Register')}</a></li> + <li><a href="${h.url_for( action='login' )}">${_('Login')}</li> + <li><a href="${h.url_for( action='create', cntrller='user' )}">${_('Register')}</a></li></ul> %endif diff -r ee2feed164a9efc9201409b3e6191e2707ec3e18 -r 5b977db5fc50b50caa5309838f37a77010f1e2b7 templates/user/info.mako --- a/templates/user/info.mako +++ b/templates/user/info.mako @@ -7,13 +7,12 @@ %if not is_admin: <ul class="manage-table-actions"><li> - <a class="action-button" href="${h.url_for( controller='user', action='index', cntrller=cntrller, webapp=webapp )}">User preferences</a> + <a class="action-button" href="${h.url_for( controller='user', action='index', cntrller=cntrller )}">User preferences</a></li></ul> %endif <div class="toolForm"><form name="login_info" id="login_info" action="${h.url_for( controller='user', action='edit_info', cntrller=cntrller, user_id=trans.security.encode_id( user.id ) )}" method="post" > - <input type="hidden" name="webapp" value="${webapp}" size="40"/><div class="toolFormTitle">Login Information</div><div class="form-row"><label>Email address:</label> @@ -21,7 +20,7 @@ </div><div class="form-row"><label>Public name:</label> - %if webapp == 'community': + %if t.webapp.name == 'community': %if user.active_repositories: <input type="hidden" name="username" value="${username}"/> ${username} @@ -54,7 +53,6 @@ <p></p><div class="toolForm"><form name="change_password" id="change_password" action="${h.url_for( controller='user', action='edit_info', cntrller=cntrller, user_id=trans.security.encode_id( user.id ) )}" method="post" > - <input type="hidden" name="webapp" value="${webapp}" size="40"/><div class="toolFormTitle">Change Password</div> %if not is_admin: <div class="form-row"> diff -r ee2feed164a9efc9201409b3e6191e2707ec3e18 -r 5b977db5fc50b50caa5309838f37a77010f1e2b7 templates/user/login.mako --- a/templates/user/login.mako +++ b/templates/user/login.mako @@ -1,11 +1,7 @@ <%! def inherit(context): if context.get('use_panels'): - if context.get('webapp'): - webapp = context.get('webapp') - else: - webapp = 'galaxy' - return '/webapps/%s/base_panels.mako' % webapp + return '/webapps/%s/base_panels.mako' % context.get('t').webapp.name else: return '/base.mako' %> @@ -82,14 +78,13 @@ <div class="form-row"><label>Email address:</label><input type="text" name="email" value="${email | h}" size="40"/> - <input type="hidden" name="webapp" value="${webapp | h}" size="40"/><input type="hidden" name="redirect" value="${redirect | h}" size="40"/></div><div class="form-row"><label>Password:</label><input type="password" name="password" value="" size="40"/><div class="toolParamHelp" style="clear: both;"> - <a href="${h.url_for( controller='user', action='reset_password', webapp=webapp, use_panels=use_panels )}">Forgot password? Reset here</a> + <a href="${h.url_for( controller='user', action='reset_password', use_panels=use_panels )}">Forgot password? Reset here</a></div></div><div class="form-row"> @@ -107,7 +102,6 @@ <div class="form-row"><label>OpenID URL:</label><input type="text" name="openid_url" size="60" style="background-image:url('${h.url_for( '/static/images/openid-16x16.gif' )}' ); background-repeat: no-repeat; padding-right: 20px; background-position: 99% 50%;"/> - <input type="hidden" name="webapp" value="${webapp | h}" size="40"/><input type="hidden" name="redirect" value="${redirect | h}" size="40"/></div><div class="form-row"> diff -r ee2feed164a9efc9201409b3e6191e2707ec3e18 -r 5b977db5fc50b50caa5309838f37a77010f1e2b7 templates/user/logout.mako --- a/templates/user/logout.mako +++ b/templates/user/logout.mako @@ -1,10 +1,6 @@ <%! def inherit(context): - if context.get('webapp'): - webapp = context.get('webapp') - else: - webapp = 'galaxy' - return '/webapps/%s/base_panels.mako' % webapp + return '/webapps/%s/base_panels.mako' % context.get('t').webapp.name %><%inherit file="${inherit(context)}"/><%namespace file="/message.mako" import="render_msg" /> diff -r ee2feed164a9efc9201409b3e6191e2707ec3e18 -r 5b977db5fc50b50caa5309838f37a77010f1e2b7 templates/user/openid_associate.mako --- a/templates/user/openid_associate.mako +++ b/templates/user/openid_associate.mako @@ -1,11 +1,7 @@ <%! def inherit(context): if context.get('use_panels'): - if context.get('webapp'): - webapp = context.get('webapp') - else: - webapp = 'galaxy' - return '/webapps/%s/base_panels.mako' % webapp + return '/webapps/%s/base_panels.mako' % t.webapp.name else: return '/base.mako' %> diff -r ee2feed164a9efc9201409b3e6191e2707ec3e18 -r 5b977db5fc50b50caa5309838f37a77010f1e2b7 templates/user/register.mako --- a/templates/user/register.mako +++ b/templates/user/register.mako @@ -43,7 +43,6 @@ <div class="form-row"><label>Email address:</label><input type="text" name="email" value="${email | h}" size="40"/> - <input type="hidden" name="webapp" value="${webapp | h}" size="40"/><input type="hidden" name="redirect" value="${redirect | h}" size="40"/></div><div class="form-row"> @@ -57,7 +56,7 @@ <div class="form-row"><label>Public name:</label><input type="text" name="username" size="40" value="${username |h}"/> - %if webapp == 'galaxy': + %if t.webapp.name == 'galaxy': <div class="toolParamHelp" style="clear: both;"> Your public name is an identifier that will be used to generate addresses for information you share publicly. Public names must be at least four characters in length and contain only lower-case diff -r ee2feed164a9efc9201409b3e6191e2707ec3e18 -r 5b977db5fc50b50caa5309838f37a77010f1e2b7 templates/user/reset_password.mako --- a/templates/user/reset_password.mako +++ b/templates/user/reset_password.mako @@ -11,7 +11,6 @@ <div class="form-row"><label>Email:</label><input type="text" name="email" value="" size="40"/> - <input type="hidden" name="webapp" value="${webapp}" size="40"/></div><div style="clear: both"></div><div class="form-row"> diff -r ee2feed164a9efc9201409b3e6191e2707ec3e18 -r 5b977db5fc50b50caa5309838f37a77010f1e2b7 templates/user/username.mako --- a/templates/user/username.mako +++ b/templates/user/username.mako @@ -5,7 +5,6 @@ <h2>Manage Public Name</h2><div class="toolForm"><form name="username" id="username" action="${h.url_for( controller='user', action='edit_username', cntrller=cntrller, user_id=trans.security.encode_id( user.id ) )}" method="post" > - <input type="hidden" name="webapp" value="${webapp}" size="40"/><div class="toolFormTitle">Login Information</div><div class="form-row"><label>Public name:</label> diff -r ee2feed164a9efc9201409b3e6191e2707ec3e18 -r 5b977db5fc50b50caa5309838f37a77010f1e2b7 templates/webapps/galaxy/admin/index.mako --- a/templates/webapps/galaxy/admin/index.mako +++ b/templates/webapps/galaxy/admin/index.mako @@ -42,11 +42,11 @@ <div class="toolSectionTitle">Security</div><div class="toolSectionBody"><div class="toolSectionBg"> - <div class="toolTitle"><a href="${h.url_for( controller='admin', action='users', webapp=webapp )}" target="galaxy_main">Manage users</a></div> - <div class="toolTitle"><a href="${h.url_for( controller='admin', action='groups', webapp=webapp )}" target="galaxy_main">Manage groups</a></div> - <div class="toolTitle"><a href="${h.url_for( controller='admin', action='roles', webapp=webapp )}" target="galaxy_main">Manage roles</a></div> + <div class="toolTitle"><a href="${h.url_for( controller='admin', action='users' )}" target="galaxy_main">Manage users</a></div> + <div class="toolTitle"><a href="${h.url_for( controller='admin', action='groups' )}" target="galaxy_main">Manage groups</a></div> + <div class="toolTitle"><a href="${h.url_for( controller='admin', action='roles' )}" target="galaxy_main">Manage roles</a></div> %if trans.app.config.allow_user_impersonation: - <div class="toolTitle"><a href="${h.url_for( controller='admin', action='impersonate', webapp=webapp )}" target="galaxy_main">Impersonate a user</a></div> + <div class="toolTitle"><a href="${h.url_for( controller='admin', action='impersonate' )}" target="galaxy_main">Impersonate a user</a></div> %endif </div></div> @@ -54,7 +54,7 @@ <div class="toolSectionTitle">Data</div><div class="toolSectionBody"><div class="toolSectionBg"> - <div class="toolTitle"><a href="${h.url_for( controller='admin', action='quotas', webapp=webapp )}" target="galaxy_main">Manage quotas</a></div> + <div class="toolTitle"><a href="${h.url_for( controller='admin', action='quotas' )}" target="galaxy_main">Manage quotas</a></div><div class="toolTitle"><a href="${h.url_for( controller='library_admin', action='browse_libraries' )}" target="galaxy_main">Manage data libraries</a></div> %if trans.app.config.enable_beta_job_managers: <div class="toolTitle"><a href="${h.url_for( controller='data_admin', action='manage_data' )}" target="galaxy_main">Manage local data</a></div> @@ -111,6 +111,6 @@ </%def><%def name="center_panel()"> - <% center_url = h.url_for( controller='admin', action='center', webapp='galaxy', message=message, status=status ) %> + <% center_url = h.url_for( controller='admin', action='center', message=message, status=status ) %><iframe name="galaxy_main" id="galaxy_main" frameborder="0" style="position: absolute; width: 100%; height: 100%;" src="${center_url}"></iframe></%def> diff -r ee2feed164a9efc9201409b3e6191e2707ec3e18 -r 5b977db5fc50b50caa5309838f37a77010f1e2b7 templates/webapps/galaxy/base_panels.mako --- a/templates/webapps/galaxy/base_panels.mako +++ b/templates/webapps/galaxy/base_panels.mako @@ -136,7 +136,7 @@ # Menu for user who is not logged in. menu_options = [ [ _("Login"), h.url_for( controller='/user', action='login' ), "galaxy_main" ] ] if app.config.allow_user_creation: - menu_options.append( [ _("Register"), h.url_for( controller='/user', action='create', cntrller='user', webapp='galaxy' ), "galaxy_main" ] ) + menu_options.append( [ _("Register"), h.url_for( controller='/user', action='create', cntrller='user' ), "galaxy_main" ] ) extra_class = "loggedout-only" visible = ( trans.user == None ) tab( "user", _("User"), None, visible=visible, menu_options=menu_options ) @@ -151,20 +151,20 @@ if app.config.remote_user_logout_href: menu_options.append( [ _('Logout'), app.config.remote_user_logout_href, "_top" ] ) else: - menu_options.append( [ _('Preferences'), h.url_for( controller='/user', action='index', cntrller='user', webapp='galaxy' ), "galaxy_main" ] ) + menu_options.append( [ _('Preferences'), h.url_for( controller='/user', action='index', cntrller='user' ), "galaxy_main" ] ) menu_options.append( [ 'Custom Builds', h.url_for( controller='/user', action='dbkeys' ), "galaxy_main" ] ) if app.config.require_login: - logout_url = h.url_for( controller='/root', action='index', m_c='user', m_a='logout', webapp='galaxy' ) + logout_url = h.url_for( controller='/root', action='index', m_c='user', m_a='logout' ) else: - logout_url = h.url_for( controller='/user', action='logout', webapp='galaxy' ) + logout_url = h.url_for( controller='/user', action='logout' ) menu_options.append( [ 'Logout', logout_url, "_top" ] ) menu_options.append( None ) menu_options.append( [ _('Saved Histories'), h.url_for( controller='/history', action='list' ), "galaxy_main" ] ) menu_options.append( [ _('Saved Datasets'), h.url_for( controller='/dataset', action='list' ), "galaxy_main" ] ) menu_options.append( [ _('Saved Pages'), h.url_for( controller='/page', action='list' ), "_top" ] ) - menu_options.append( [ _('API Keys'), h.url_for( controller='/user', action='api_keys', cntrller='user', webapp='galaxy' ), "galaxy_main" ] ) + menu_options.append( [ _('API Keys'), h.url_for( controller='/user', action='api_keys', cntrller='user' ), "galaxy_main" ] ) if app.config.use_remote_user: - menu_options.append( [ _('Public Name'), h.url_for( controller='/user', action='edit_username', cntrller='user', webapp='galaxy' ), "galaxy_main" ] ) + menu_options.append( [ _('Public Name'), h.url_for( controller='/user', action='edit_username', cntrller='user' ), "galaxy_main" ] ) extra_class = "loggedin-only" visible = ( trans.user != None ) Repository URL: https://bitbucket.org/galaxy/galaxy-central/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email.
participants (1)
-
Bitbucket