Incorporate latest grid features into managing users, groups and roles from the admin view.

This commit is contained in:
Greg Von Kuster
2009-11-09 23:00:55 -05:00
parent 5371e0e6da
commit 00c3f84f40
19 changed files with 460 additions and 828 deletions
+324 -112
View File
@@ -2,20 +2,31 @@ import string, sys
from datetime import datetime, timedelta
from galaxy import util, datatypes
from galaxy.web.base.controller import *
from galaxy.util.odict import odict
from galaxy.model.orm import *
from galaxy.web.framework.helpers import time_ago, iff, grids
import logging
log = logging.getLogger( __name__ )
# States for passing messages
SUCCESS, INFO, WARNING, ERROR = "done", "info", "warning", "error"
class UserListGrid( grids.Grid ):
class EmailColumn( grids.GridColumn ):
class EmailColumn( grids.TextColumn ):
def get_value( self, trans, grid, user ):
return user.email
class UserNameColumn( grids.GridColumn ):
class UserNameColumn( grids.TextColumn ):
def get_value( self, trans, grid, user ):
if user.username:
return user.username
return 'not set'
class StatusColumn( grids.GridColumn ):
def get_value( self, trans, grid, user ):
if user.purged:
return "purged"
elif user.deleted:
return "deleted"
return ""
class GroupsColumn( grids.GridColumn ):
def get_value( self, trans, grid, user ):
if user.groups:
@@ -36,56 +47,242 @@ class UserListGrid( grids.Grid ):
if user.galaxy_sessions:
return self.format( user.galaxy_sessions[ 0 ].update_time )
return 'never'
class DeletedColumn( grids.GridColumn ):
def get_accepted_filters( self ):
""" Returns a list of accepted filters for this column. """
accepted_filter_labels_and_vals = { "active" : "False", "deleted" : "True", "all": "All" }
accepted_filters = []
for label, val in accepted_filter_labels_and_vals.items():
args = { self.key: val }
accepted_filters.append( grids.GridColumnFilter( label, args) )
return accepted_filters
# Grid definition
title = "Users"
model_class = model.User
template='/admin/user/grid.mako'
default_sort_key = "email"
columns = [
EmailColumn( "Email", link=( lambda item: dict( operation="information", id=item.id ) ), attach_popup=True ),
UserNameColumn( "User Name", attach_popup=False ),
EmailColumn( "Email",
key="email",
model_class=model.User,
link=( lambda item: dict( operation="information", id=item.id ) ),
attach_popup=True,
filterable="advanced" ),
UserNameColumn( "User Name",
key="username",
model_class=model.User,
attach_popup=False,
filterable="advanced" ),
GroupsColumn( "Groups", attach_popup=False ),
RolesColumn( "Roles", attach_popup=False ),
ExternalColumn( "External", attach_popup=False ),
LastLoginColumn( "Last Login", format=time_ago ),
# Valid for filtering but invisible
grids.GridColumn( "Deleted", key="deleted", visible=False )
StatusColumn( "Status", attach_popup=False ),
# Columns that are valid for filtering but are not visible.
DeletedColumn( "Deleted", key="deleted", visible=False, filterable="advanced" )
]
columns.append( grids.MulticolFilterColumn( "Search",
cols_to_filter=[ columns[0], columns[1] ],
key="free-text-search",
visible=False,
filterable="standard" ) )
global_actions = [
grids.GridAction( "Create new user", dict( controller='admin', action='users', operation='create' ) )
]
operations = [
grids.GridOperation( "Manage Roles & Groups", condition=( lambda item: not item.deleted ), allow_multiple=False )
]
#TODO: enhance to account for trans.app.config.allow_user_deletion here so that we can eliminate these operations if
# the setting is False
operations.append( grids.GridOperation( "Reset Password", condition=( lambda item: not item.deleted ), allow_multiple=True, allow_popup=False ) )
operations.append( grids.GridOperation( "Delete", condition=( lambda item: not item.deleted ), allow_multiple=True ) )
operations.append( grids.GridOperation( "Undelete", condition=( lambda item: item.deleted ), allow_multiple=True ) )
operations.append( grids.GridOperation( "Purge", condition=( lambda item: item.deleted ), allow_multiple=True ) )
operations.append( grids.GridOperation( "Undelete", condition=( lambda item: item.deleted and not item.purged ), allow_multiple=True ) )
operations.append( grids.GridOperation( "Purge", condition=( lambda item: item.deleted and not item.purged ), allow_multiple=True ) )
standard_filters = [
grids.GridColumnFilter( "Active", args=dict( deleted=False ) ),
grids.GridColumnFilter( "Deleted", args=dict( deleted=True, purged=False ) ),
grids.GridColumnFilter( "Purged", args=dict( purged=True ) ),
grids.GridColumnFilter( "All", args=dict( deleted='All' ) )
]
default_filter = dict( email="All", username="All", deleted="False", purged="False" )
num_rows_per_page = 50
preserve_state = False
use_paging = True
def get_current_item( self, trans ):
return trans.user
def build_initial_query( self, session ):
return session.query( self.model_class )
class RoleListGrid( grids.Grid ):
class NameColumn( grids.TextColumn ):
def get_value( self, trans, grid, role ):
return role.name
class DescriptionColumn( grids.TextColumn ):
def get_value( self, trans, grid, role ):
if role.description:
return role.description
return ''
class TypeColumn( grids.TextColumn ):
def get_value( self, trans, grid, role ):
return role.type
class StatusColumn( grids.GridColumn ):
def get_value( self, trans, grid, role ):
if role.deleted:
return "deleted"
return ""
class DeletedColumn( grids.GridColumn ):
def get_accepted_filters( self ):
""" Returns a list of accepted filters for this column. """
accepted_filter_labels_and_vals = { "active" : "False", "deleted" : "True", "all": "All" }
accepted_filters = []
for label, val in accepted_filter_labels_and_vals.items():
args = { self.key: val }
accepted_filters.append( grids.GridColumnFilter( label, args) )
return accepted_filters
class GroupsColumn( grids.GridColumn ):
def get_value( self, trans, grid, role ):
if role.groups:
return len( role.groups )
return 0
class UsersColumn( grids.GridColumn ):
def get_value( self, trans, grid, role ):
if role.users:
return len( role.users )
return 0
# Grid definition
title = "Roles"
model_class = model.Role
template='/admin/dataset_security/role/grid.mako'
default_sort_key = "name"
columns = [
NameColumn( "Name",
key="name",
link=( lambda item: dict( controller="admin", action="role", id=item.id ) ),
model_class=model.Role,
attach_popup=True,
filterable="advanced" ),
DescriptionColumn( "Description",
key='description',
model_class=model.Role,
attach_popup=False,
filterable="advanced" ),
TypeColumn( "Type",
key='type',
model_class=model.Role,
attach_popup=False,
filterable="advanced" ),
GroupsColumn( "Groups", attach_popup=False ),
UsersColumn( "Users", attach_popup=False ),
StatusColumn( "Status", attach_popup=False ),
# Columns that are valid for filtering but are not visible.
DeletedColumn( "Deleted", key="deleted", visible=False, filterable="advanced" )
]
columns.append( grids.MulticolFilterColumn( "Search",
cols_to_filter=[ columns[0], columns[1], columns[2] ],
key="free-text-search",
visible=False,
filterable="standard" ) )
global_actions = [
grids.GridAction( "Add new role", dict( controller='admin', action='roles', operation='create' ) )
]
operations = [ grids.GridOperation( "Delete", condition=( lambda item: not item.deleted ), allow_multiple=True ),
grids.GridOperation( "Undelete", condition=( lambda item: item.deleted ), allow_multiple=True ),
grids.GridOperation( "Purge", condition=( lambda item: item.deleted ), allow_multiple=True ) ]
standard_filters = [
grids.GridColumnFilter( "Active", args=dict( deleted=False ) ),
grids.GridColumnFilter( "Deleted", args=dict( deleted=True ) ),
grids.GridColumnFilter( "All", args=dict( deleted='All' ) )
]
default_filter = dict( deleted=False )
default_filter = dict( name="All", deleted="False", description="All", type="All" )
num_rows_per_page = 50
preserve_state = False
use_paging = True
def get_current_item( self, trans ):
return trans.user
return None
def build_initial_query( self, session ):
return session.query( self.model_class )
def apply_default_filter( self, trans, query, **kwargs ):
email_filter = kwargs.get( "email_filter", None )
if email_filter:
if email_filter == 'all':
return query
else:
return query.filter( or_( trans.app.model.User.table.c.email.like( '%s' % email_filter.lower() + '%' ),
trans.app.model.User.table.c.email.like( '%s' % email_filter.upper() + '%' ) ) )
elif query.count() > 200:
return query.filter( or_( trans.app.model.User.table.c.email.like( 'A%' ),
trans.app.model.User.table.c.email.like( 'a%' ) ) )
return query
return query.filter( model.Role.type != model.Role.types.PRIVATE )
class GroupListGrid( grids.Grid ):
class NameColumn( grids.TextColumn ):
def get_value( self, trans, grid, group ):
return group.name
class StatusColumn( grids.GridColumn ):
def get_value( self, trans, grid, group ):
if group.deleted:
return "deleted"
return ""
class DeletedColumn( grids.GridColumn ):
def get_accepted_filters( self ):
""" Returns a list of accepted filters for this column. """
accepted_filter_labels_and_vals = { "active" : "False", "deleted" : "True", "all": "All" }
accepted_filters = []
for label, val in accepted_filter_labels_and_vals.items():
args = { self.key: val }
accepted_filters.append( grids.GridColumnFilter( label, args) )
return accepted_filters
class RolesColumn( grids.GridColumn ):
def get_value( self, trans, grid, group ):
if group.roles:
return len( group.roles )
return 0
class UsersColumn( grids.GridColumn ):
def get_value( self, trans, grid, group ):
if group.members:
return len( group.members )
return 0
# Grid definition
title = "Groups"
model_class = model.Group
template='/admin/dataset_security/group/grid.mako'
default_sort_key = "name"
columns = [
NameColumn( "Name",
key="name",
link=( lambda item: dict( controller="admin", action="group", id=item.id ) ),
model_class=model.Group,
attach_popup=True,
filterable="advanced" ),
UsersColumn( "Users", attach_popup=False ),
RolesColumn( "Roles", attach_popup=False ),
StatusColumn( "Status", attach_popup=False ),
# Columns that are valid for filtering but are not visible.
DeletedColumn( "Deleted", key="deleted", visible=False, filterable="advanced" )
]
columns.append( grids.MulticolFilterColumn( "Search",
cols_to_filter=[ columns[0], columns[1], columns[2] ],
key="free-text-search",
visible=False,
filterable="standard" ) )
global_actions = [
grids.GridAction( "Add new group", dict( controller='admin', action='groups', operation='create' ) )
]
operations = [ grids.GridOperation( "Delete", condition=( lambda item: not item.deleted ), allow_multiple=True ),
grids.GridOperation( "Undelete", condition=( lambda item: item.deleted ), allow_multiple=True ),
grids.GridOperation( "Purge", condition=( lambda item: item.deleted ), allow_multiple=True ) ]
standard_filters = [
grids.GridColumnFilter( "Active", args=dict( deleted=False ) ),
grids.GridColumnFilter( "Deleted", args=dict( deleted=True ) ),
grids.GridColumnFilter( "All", args=dict( deleted='All' ) )
]
default_filter = dict( name="All", deleted="False" )
num_rows_per_page = 50
preserve_state = False
use_paging = True
def get_current_item( self, trans ):
return None
def build_initial_query( self, session ):
return session.query( self.model_class )
class Admin( BaseController ):
user_list_grid = UserListGrid()
role_list_grid = RoleListGrid()
group_list_grid = GroupListGrid()
@web.expose
@web.require_admin
@@ -117,17 +314,23 @@ class Admin( BaseController ):
# Galaxy Role Stuff
@web.expose
@web.require_admin
def roles( self, trans, **kwd ):
params = util.Params( kwd )
msg = util.restore_text( params.get( 'msg', '' ) )
messagetype = params.get( 'messagetype', 'done' )
roles = trans.sa_session.query( trans.app.model.Role ).filter( and_( trans.app.model.Role.table.c.deleted==False,
trans.app.model.Role.table.c.type != trans.app.model.Role.types.PRIVATE ) ) \
.order_by( trans.app.model.Role.table.c.name )
return trans.fill_template( '/admin/dataset_security/roles.mako',
roles=roles,
msg=msg,
messagetype=messagetype )
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 & groups":
return self.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 ):
@@ -164,7 +367,7 @@ class Admin( BaseController ):
( group.name, role.name, len( in_users ), len( in_groups ) )
else:
msg = "Role '%s' has been created 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', msg=util.sanitize_text( msg ), messagetype='done' ) )
trans.response.send_redirect( web.url_for( controller='admin', action='roles', message=util.sanitize_text( msg ), status='done' ) )
trans.response.send_redirect( web.url_for( controller='admin', action='create_role', msg=util.sanitize_text( msg ), messagetype='error' ) )
out_users = []
for user in trans.sa_session.query( trans.app.model.User ) \
@@ -176,7 +379,7 @@ class Admin( BaseController ):
.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_create.mako',
return trans.fill_template( '/admin/dataset_security/role/role_create.mako',
in_users=[],
out_users=out_users,
in_groups=[],
@@ -189,7 +392,7 @@ class Admin( BaseController ):
params = util.Params( kwd )
msg = util.restore_text( params.get( 'msg', '' ) )
messagetype = params.get( 'messagetype', 'done' )
role = trans.sa_session.query( trans.app.model.Role ).get( int( params.role_id ) )
role = get_role( trans, params.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:
@@ -210,7 +413,7 @@ class Admin( BaseController ):
trans.app.security_agent.set_entity_role_associations( roles=[ role ], users=in_users, groups=in_groups )
trans.sa_session.refresh( role )
msg = "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( action='roles', msg=util.sanitize_text( msg ), messagetype=messagetype ) )
trans.response.send_redirect( web.url_for( action='roles', message=util.sanitize_text( msg ), status=messagetype ) )
elif params.get( 'rename', False ):
if params.rename == 'submitted':
old_name = role.name
@@ -218,17 +421,17 @@ class Admin( BaseController ):
new_description = util.restore_text( params.description )
if not new_name:
msg = 'Enter a valid name'
return trans.fill_template( '/admin/dataset_security/role_rename.mako', role=role, msg=msg, messagetype='error' )
return trans.fill_template( '/admin/dataset_security/role/role_rename.mako', role=role, msg=msg, messagetype='error' )
elif trans.sa_session.query( trans.app.model.Role ).filter( trans.app.model.Role.table.c.name==new_name ).first():
msg = 'A role with that name already exists'
return trans.fill_template( '/admin/dataset_security/role_rename.mako', role=role, msg=msg, messagetype='error' )
return trans.fill_template( '/admin/dataset_security/role/role_rename.mako', role=role, msg=msg, messagetype='error' )
else:
role.name = new_name
role.description = new_description
role.flush()
msg = "Role '%s' has been renamed to '%s'" % ( old_name, new_name )
return trans.response.send_redirect( web.url_for( action='roles', msg=util.sanitize_text( msg ), messagetype='done' ) )
return trans.fill_template( '/admin/dataset_security/role_rename.mako', role=role, msg=msg, messagetype=messagetype )
return trans.response.send_redirect( web.url_for( action='roles', message=util.sanitize_text( msg ), status='done' ) )
return trans.fill_template( '/admin/dataset_security/role/role_rename.mako', role=role, msg=msg, messagetype=messagetype )
in_users = []
out_users = []
in_groups = []
@@ -273,7 +476,7 @@ class Admin( BaseController ):
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.mako',
return trans.fill_template( '/admin/dataset_security/role/role.mako',
role=role,
in_users=in_users,
out_users=out_users,
@@ -286,33 +489,20 @@ class Admin( BaseController ):
@web.require_admin
def mark_role_deleted( self, trans, **kwd ):
params = util.Params( kwd )
role = trans.sa_session.query( trans.app.model.Role ).get( int( params.role_id ) )
role = get_role( trans, params.id )
role.deleted = True
role.flush()
msg = "Role '%s' has been marked as deleted." % role.name
trans.response.send_redirect( web.url_for( action='roles', msg=util.sanitize_text( msg ), messagetype='done' ) )
@web.expose
@web.require_admin
def deleted_roles( self, trans, **kwd ):
params = util.Params( kwd )
msg = util.restore_text( params.get( 'msg', '' ) )
messagetype = params.get( 'messagetype', 'done' )
roles = trans.sa_session.query( trans.app.model.Role ) \
.filter( trans.app.model.Role.table.c.deleted==True ) \
.order_by( trans.app.model.Role.table.c.name )
return trans.fill_template( '/admin/dataset_security/deleted_roles.mako',
roles=roles,
msg=msg,
messagetype=messagetype )
message = "Role '%s' has been marked as deleted." % role.name
trans.response.send_redirect( web.url_for( action='roles', message=util.sanitize_text( message ), status='done' ) )
@web.expose
@web.require_admin
def undelete_role( self, trans, **kwd ):
params = util.Params( kwd )
role = trans.sa_session.query( trans.app.model.Role ).get( int( params.role_id ) )
role = get_role( trans, params.id )
role.deleted = False
role.flush()
msg = "Role '%s' has been marked as not deleted." % role.name
trans.response.send_redirect( web.url_for( action='roles', msg=util.sanitize_text( msg ), messagetype='done' ) )
message = "Role '%s' has been marked as not deleted." % role.name
trans.response.send_redirect( web.url_for( action='roles', message=util.sanitize_text( message ), status='done' ) )
@web.expose
@web.require_admin
def purge_role( self, trans, **kwd ):
@@ -324,11 +514,10 @@ class Admin( BaseController ):
# - GroupRoleAssociations where role_id == Role.id
# - DatasetPermissionss where role_id == Role.id
params = util.Params( kwd )
role = trans.sa_session.query( trans.app.model.Role ).get( int( params.role_id ) )
role = get_role( trans, params.id )
if not role.deleted:
# We should never reach here, but just in case there is a bug somewhere...
msg = "Role '%s' has not been deleted, so it cannot be purged." % role.name
trans.response.send_redirect( web.url_for( action='roles', msg=util.sanitize_text( msg ), messagetype='error' ) )
message = "Role '%s' has not been deleted, so it cannot be purged." % role.name
trans.response.send_redirect( web.url_for( 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 )
@@ -353,54 +542,60 @@ class Admin( BaseController ):
for dp in role.dataset_actions:
trans.sa_session.delete( dp )
dp.flush()
msg = "The following have been purged from the database for role '%s': " % role.name
msg += "DefaultUserPermissions, DefaultHistoryPermissions, UserRoleAssociations, GroupRoleAssociations, DatasetPermissionss."
trans.response.send_redirect( web.url_for( action='deleted_roles', msg=util.sanitize_text( msg ), messagetype='done' ) )
message = "The following have been purged from the database for role '%s': " % role.name
message += "DefaultUserPermissions, DefaultHistoryPermissions, UserRoleAssociations, GroupRoleAssociations, DatasetPermissionss."
trans.response.send_redirect( web.url_for( action='roles', message=util.sanitize_text( message ), status='done' ) )
# Galaxy Group Stuff
@web.expose
@web.require_admin
def groups( self, trans, **kwd ):
params = util.Params( kwd )
msg = util.restore_text( params.get( 'msg', '' ) )
messagetype = params.get( 'messagetype', 'done' )
groups = 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 )
return trans.fill_template( '/admin/dataset_security/groups.mako',
groups=groups,
msg=msg,
messagetype=messagetype )
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 & roles":
return self.group( trans, **kwargs )
# Render the list view
return self.group_list_grid( trans, **kwargs )
@web.expose
@web.require_admin
def group( self, trans, **kwd ):
params = util.Params( kwd )
msg = util.restore_text( params.get( 'msg', '' ) )
messagetype = params.get( 'messagetype', 'done' )
group = trans.sa_session.query( trans.app.model.Group ).get( int( params.group_id ) )
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 )
msg += "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( action='groups', msg=util.sanitize_text( msg ), messagetype=messagetype ) )
trans.response.send_redirect( web.url_for( action='groups', message=util.sanitize_text( msg ), status=messagetype ) )
if params.get( 'rename', False ):
if params.rename == 'submitted':
old_name = group.name
new_name = util.restore_text( params.name )
if not new_name:
msg = 'Enter a valid name'
return trans.fill_template( '/admin/dataset_security/group_rename.mako', group=group, msg=msg, messagetype='error' )
return trans.fill_template( '/admin/dataset_security/group/group_rename.mako', group=group, msg=msg, messagetype='error' )
elif trans.sa_session.query( trans.app.model.Group ).filter( trans.app.model.Group.table.c.name==new_name ).first():
msg = 'A group with that name already exists'
return trans.fill_template( '/admin/dataset_security/group_rename.mako', group=group, msg=msg, messagetype='error' )
return trans.fill_template( '/admin/dataset_security/group/group_rename.mako', group=group, msg=msg, messagetype='error' )
else:
group.name = new_name
group.flush()
msg = "Group '%s' has been renamed to '%s'" % ( old_name, new_name )
return trans.response.send_redirect( web.url_for( action='groups', msg=util.sanitize_text( msg ), messagetype='done' ) )
return trans.fill_template( '/admin/dataset_security/group_rename.mako', group=group, msg=msg, messagetype=messagetype )
return trans.fill_template( '/admin/dataset_security/group/group_rename.mako', group=group, msg=msg, messagetype=messagetype )
in_roles = []
out_roles = []
in_users = []
@@ -420,7 +615,7 @@ class Admin( BaseController ):
else:
out_users.append( ( user.id, user.email ) )
msg += '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.mako',
return trans.fill_template( '/admin/dataset_security/group/group.mako',
group=group,
in_roles=in_roles,
out_roles=out_roles,
@@ -455,7 +650,7 @@ class Admin( BaseController ):
gra = trans.app.model.GroupRoleAssociation( group, role )
gra.flush()
msg = "Group '%s' has been created with %d associated users and %d associated roles" % ( name, len( in_users ), len( in_roles ) )
trans.response.send_redirect( web.url_for( controller='admin', action='groups', msg=util.sanitize_text( msg ), messagetype='done' ) )
trans.response.send_redirect( web.url_for( controller='admin', action='groups', message=util.sanitize_text( msg ), status='done' ) )
trans.response.send_redirect( web.url_for( controller='admin', action='create_group', msg=util.sanitize_text( msg ), messagetype='error' ) )
out_users = []
for user in trans.sa_session.query( trans.app.model.User ) \
@@ -467,7 +662,7 @@ class Admin( BaseController ):
.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_create.mako',
return trans.fill_template( '/admin/dataset_security/group/group_create.mako',
in_users=[],
out_users=out_users,
in_roles=[],
@@ -478,44 +673,31 @@ class Admin( BaseController ):
@web.require_admin
def mark_group_deleted( self, trans, **kwd ):
params = util.Params( kwd )
group = trans.sa_session.query( trans.app.model.Group ).get( int( params.group_id ) )
group = get_group( trans, params.id )
group.deleted = True
group.flush()
msg = "Group '%s' has been marked as deleted." % group.name
trans.response.send_redirect( web.url_for( action='groups', msg=util.sanitize_text( msg ), messagetype='done' ) )
@web.expose
@web.require_admin
def deleted_groups( self, trans, **kwd ):
params = util.Params( kwd )
msg = util.restore_text( params.get( 'msg', '' ) )
messagetype = params.get( 'messagetype', 'done' )
groups = trans.sa_session.query( trans.app.model.Group ) \
.filter( trans.app.model.Group.table.c.deleted==True ) \
.order_by( trans.app.model.Group.table.c.name )
return trans.fill_template( '/admin/dataset_security/deleted_groups.mako',
groups=groups,
msg=msg,
messagetype=messagetype )
trans.response.send_redirect( web.url_for( action='groups', message=util.sanitize_text( msg ), status='done' ) )
@web.expose
@web.require_admin
def undelete_group( self, trans, **kwd ):
params = util.Params( kwd )
group = trans.sa_session.query( trans.app.model.Group ).get( int( params.group_id ) )
group = get_group( trans, params.id )
group.deleted = False
group.flush()
msg = "Group '%s' has been marked as not deleted." % group.name
trans.response.send_redirect( web.url_for( action='groups', msg=util.sanitize_text( msg ), messagetype='done' ) )
trans.response.send_redirect( web.url_for( action='groups', message=util.sanitize_text( msg ), 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 )
group = trans.sa_session.query( trans.app.model.Group ).get( int( params.group_id ) )
group = get_group( trans, params.id )
if not group.deleted:
# We should never reach here, but just in case there is a bug somewhere...
msg = "Group '%s' has not been deleted, so it cannot be purged." % group.name
trans.response.send_redirect( web.url_for( action='groups', msg=util.sanitize_text( msg ), messagetype='error' ) )
trans.response.send_redirect( web.url_for( action='groups', message=util.sanitize_text( msg ), status='error' ) )
# Delete UserGroupAssociations
for uga in group.users:
trans.sa_session.delete( uga )
@@ -525,8 +707,8 @@ class Admin( BaseController ):
trans.sa_session.delete( gra )
gra.flush()
# Delete the Group
msg = "The following have been purged from the database for group '%s': UserGroupAssociations, GroupRoleAssociations." % group.name
trans.response.send_redirect( web.url_for( action='deleted_groups', msg=util.sanitize_text( msg ), messagetype='done' ) )
message = "The following have been purged from the database for group '%s': UserGroupAssociations, GroupRoleAssociations." % group.name
trans.response.send_redirect( web.url_for( action='groups', message=util.sanitize_text( message ), status='done' ) )
# Galaxy User Stuff
@web.expose
@@ -645,11 +827,12 @@ class Admin( BaseController ):
message = "No user ids received for deleting"
trans.response.send_redirect( web.url_for( 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
user.flush()
message = "Deleted %d users" % len( ids )
message += " %s " % user.email
trans.response.send_redirect( web.url_for( action='users', message=util.sanitize_text( message ), status='done' ) )
@web.expose
@web.require_admin
@@ -660,13 +843,15 @@ class Admin( BaseController ):
trans.response.send_redirect( web.url_for( 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 user.deleted:
user.deleted = False
user.flush()
count += 1
message = "Undeleted %d users" % count
undeleted_users += " %s" % user.email
message = "Undeleted %d users: %s" % ( count, undeleted_users )
trans.response.send_redirect( web.url_for( action='users',
message=util.sanitize_text( message ),
status='done' ) )
@@ -691,6 +876,7 @@ class Admin( BaseController ):
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:
@@ -726,7 +912,7 @@ class Admin( BaseController ):
# Purge the user
user.purged = True
user.flush()
message = "Purged %d users" % len( ids )
message += "%s " % user.email
trans.response.send_redirect( web.url_for( controller='admin',
action='users',
message=util.sanitize_text( message ),
@@ -750,6 +936,8 @@ class Admin( BaseController ):
return self.create_new_user( trans, **kwargs )
if operation == "information":
return self.user_info( trans, **kwargs )
if operation == "manage roles & groups":
return self.user( trans, **kwargs )
# Render the list view
return self.user_list_grid( trans, **kwargs )
@web.expose
@@ -774,6 +962,14 @@ class Admin( BaseController ):
admin_view=True, **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 user( self, trans, **kwd ):
user_id = kwd.get( 'id', None )
message = ''
@@ -932,5 +1128,21 @@ def get_user( trans, id ):
id = trans.security.decode_id( id )
user = trans.sa_session.query( model.User ).get( id )
if not user:
err+msg( "User not found" )
return trans.show_error_message( "User not found for id (%s)" % str( id ) )
return user
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( 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( model.Group ).get( id )
if not group:
return trans.show_error_message( "Group not found for id (%s)" % str( id ) )
return group
@@ -1,101 +0,0 @@
<%inherit file="/base.mako"/>
<%namespace file="/message.mako" import="render_msg" />
## Render a row
<%def name="render_row( group, ctr, anchored, curr_anchor )">
%if ctr % 2 == 1:
<tr class="odd_row">
%else:
<tr>
%endif
<td>
${group.name}
<a id="group-${group.id}-popup" class="popup-arrow" style="display: none;">&#9660;</a>
<div popupmenu="group-${group.id}-popup">
<a class="action-button" href="${h.url_for( action='undelete_group', group_id=group.id )}">Undelete</a>
<a class="action-button" href="${h.url_for( action='purge_group', group_id=group.id )}">Purge</a>
</div>
</td>
<td>
${len( group.members )}
</td>
<td>
${len( group.roles )}
%if not anchored:
<a name="${curr_anchor}"></a>
<div style="float: right;"><a href="#TOP">top</a></div>
%endif
</td>
</tr>
</%def>
<a name="TOP"><h2>Deleted Groups</h2></a>
%if msg:
${render_msg( msg, messagetype )}
%endif
## TODO: make this a grid
%if not groups:
There are no deleted Galaxy groups
%else:
<table class="manage-table colored" border="0" cellspacing="0" cellpadding="0" width="100%">
<%
render_quick_find = groups.count() > 200
ctr = 0
%>
%if render_quick_find:
<%
anchors = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
anchor_loc = 0
anchored = False
curr_anchor = 'A'
%>
<tr style="background: #EEE">
<td colspan="3" style="text-align: center; border-bottom: 1px solid #D8B365">
Jump to letter:
%for a in anchors:
| <a href="#${a}">${a}</a>
%endfor
</td>
</tr>
%endif
<tr class="header">
<td>Name</td>
<td>Users</td>
<td>Roles</td>
</tr>
%for ctr, group in enumerate( groups ):
%if render_quick_find and not group.name.upper().startswith( curr_anchor ):
<% anchored = False %>
%endif
%if render_quick_find and group.name.upper().startswith( curr_anchor ):
%if not anchored:
${render_row( group, ctr, anchored, curr_anchor )}
<% anchored = True %>
%else:
${render_row( group, ctr, anchored, curr_anchor )}
%endif
%elif render_quick_find:
%for anchor in anchors[ anchor_loc: ]:
%if group.name.upper().startswith( anchor ):
%if not anchored:
<% curr_anchor = anchor %>
${render_row( group, ctr, anchored, curr_anchor )}
<% anchored = True %>
%else:
${render_row( group, ctr, anchored, curr_anchor )}
%endif
<%
anchor_loc = anchors.index( anchor )
break
%>
%endif
%endfor
%else:
${render_row( group, ctr, True, '' )}
%endif
%endfor
</table>
%endif
@@ -1,103 +0,0 @@
<%inherit file="/base.mako"/>
<%namespace file="/message.mako" import="render_msg" />
## Render a row
<%def name="render_row( role, ctr, anchored, curr_anchor )">
%if ctr % 2 == 1:
<tr class="odd_row">
%else:
<tr>
%endif
<td>
${role.name}
<a id="role-${role.id}-popup" class="popup-arrow" style="display: none;">&#9660;</a>
<div popupmenu="role-${role.id}-popup">
<a class="action-button" href="${h.url_for( action='undelete_role', role_id=role.id )}">Undelete</a>
<a class="action-button" href="${h.url_for( action='purge_role', role_id=role.id )}">Purge</a>
</div>
</td>
<td>${role.description}</td>
<td>${role.type}</td>
<td>
${len( role.users )}
</td>
<td>
${len( role.groups )}
%if not anchored:
<a name="${curr_anchor}"></a>
<div style="float: right;"><a href="#TOP">top</a></div>
%endif
</td>
</tr>
</%def>
<a name="TOP"><h2>Deleted Roles</h2></a>
%if msg:
${render_msg( msg, messagetype )}
%endif
%if not roles:
There are no deleted Galaxy roles
%else:
<table class="manage-table colored" border="0" cellspacing="0" cellpadding="0" width="100%">
<%
render_quick_find = roles.count() > 200
ctr = 0
%>
%if render_quick_find:
<%
anchors = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
anchor_loc = 0
anchored = False
curr_anchor = 'A'
%>
<tr style="background: #EEE">
<td colspan="3" style="text-align: center; border-bottom: 1px solid #D8B365">
Jump to letter:
%for a in anchors:
| <a href="#${a}">${a}</a>
%endfor
</td>
</tr>
%endif
<tr class="header">
<td>Name</td>
<td>Description</td>
<td>Type</td>
<td>Users</td>
<td>Groups</td>
</tr>
%for ctr, role in enumerate( roles ):
%if render_quick_find and not role.name.upper().startswith( curr_anchor ):
<% anchored = False %>
%endif
%if render_quick_find and role.name.upper().startswith( curr_anchor ):
%if not anchored:
${render_row( role, ctr, anchored, curr_anchor )}
<% anchored = True %>
%else:
${render_row( role, ctr, anchored, curr_anchor )}
%endif
%elif render_quick_find:
%for anchor in anchors[ anchor_loc: ]:
%if role.name.upper().startswith( anchor ):
%if not anchored:
<% curr_anchor = anchor %>
${render_row( role, ctr, anchored, curr_anchor )}
<% anchored = True %>
%else:
${render_row( role, ctr, anchored, curr_anchor )}
%endif
<%
anchor_loc = anchors.index( anchor )
break
%>
%endif
%endfor
%else:
${render_row( role, ctr, True, '' )}
%endif
%endfor
</table>
%endif
@@ -0,0 +1 @@
<%inherit file="/grid_base.mako"/>
@@ -24,7 +24,7 @@
</div>
<div class="form-row">
<div style="float: left; width: 250px; margin-right: 10px;">
<input type="hidden" name="group_id" value="${group.id}"/>
<input type="hidden" name="id" value="${ trans.security.encode_id( group.id )}"/>
</div>
<div style="clear: both"></div>
</div>
@@ -1,107 +0,0 @@
<%inherit file="/base.mako"/>
<%namespace file="/message.mako" import="render_msg" />
## Render a row
<%def name="render_row( group, ctr, anchored, curr_anchor )">
%if ctr % 2 == 1:
<tr class="odd_row">
%else:
<tr>
%endif
<td>
<a href="${h.url_for( controller='admin', action='group', group_id=group.id )}">${group.name}</a>
<a id="group-${group.id}-popup" class="popup-arrow" style="display: none;">&#9660;</a>
<div popupmenu="group-${group.id}-popup">
<a class="action-button" href="${h.url_for( controller='admin', action='group', rename=True, group_id=group.id )}">Rename this group</a>
<a class="action-button" href="${h.url_for( controller='admin', action='group', group_id=group.id )}">Change associated users and roles</a>
<a class="action-button" href="${h.url_for( controller='admin', action='mark_group_deleted', group_id=group.id )}">Mark group deleted</a>
</div>
</td>
<td>
${len( group.members )}
</td>
<td>
${len( group.roles )}
%if not anchored:
<a name="${curr_anchor}"></a>
<div style="float: right;"><a href="#TOP">top</a></div>
%endif
</td>
</tr>
</%def>
<a name="TOP"><h2>Groups</h2></a>
<ul class="manage-table-actions">
<li><a class="action-button" href="${h.url_for( controller='admin', action='create_group' )}">Create a new group</a></li>
<li><a class="action-button" href="${h.url_for( controller='admin', action='deleted_groups' )}">Manage deleted groups</a></li>
</ul>
%if msg:
${render_msg( msg, messagetype )}
%endif
## TODO: make this a grid
%if not groups:
There are no Galaxy groups
%else:
<table class="manage-table colored" border="0" cellspacing="0" cellpadding="0" width="100%">
<%
render_quick_find = groups.count() > 200
ctr = 0
%>
%if render_quick_find:
<%
anchors = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
anchor_loc = 0
anchored = False
curr_anchor = 'A'
%>
<tr style="background: #EEE">
<td colspan="3" style="border-bottom: 1px solid #D8B365; text-align: center;">
Jump to letter:
%for a in anchors:
| <a href="#${a}">${a}</a>
%endfor
</td>
</tr>
%endif
<tr class="header">
<td>Name</td>
<td>Users</td>
<td>Roles</td>
</tr>
%for ctr, group in enumerate( groups ):
%if render_quick_find and not group.name.upper().startswith( curr_anchor ):
<% anchored = False %>
%endif
%if render_quick_find and group.name.upper().startswith( curr_anchor ):
%if not anchored:
${render_row( group, ctr, anchored, curr_anchor )}
<% anchored = True %>
%else:
${render_row( group, ctr, anchored, curr_anchor )}
%endif
%elif render_quick_find:
%for anchor in anchors[ anchor_loc: ]:
%if group.name.upper().startswith( anchor ):
%if not anchored:
<% curr_anchor = anchor %>
${render_row( group, ctr, anchored, curr_anchor )}
<% anchored = True %>
%else:
${render_row( group, ctr, anchored, curr_anchor )}
%endif
<%
anchor_loc = anchors.index( anchor )
break
%>
%endif
%endfor
%else:
${render_row( group, ctr, True, '' )}
%endif
%endfor
</table>
%endif
@@ -0,0 +1 @@
<%inherit file="/grid_base.mako"/>
@@ -31,7 +31,7 @@
</div>
<div class="form-row">
<div style="float: left; width: 250px; margin-right: 10px;">
<input type="hidden" name="role_id" value="${role.id}"/>
<input type="hidden" name="id" value="${trans.security.encode_id( role.id )}"/>
</div>
<div style="clear: both"></div>
</div>
-109
View File
@@ -1,109 +0,0 @@
<%inherit file="/base.mako"/>
<%namespace file="/message.mako" import="render_msg" />
## Render a row
<%def name="render_row( role, ctr, anchored, curr_anchor )">
%if ctr % 2 == 1:
<tr class="odd_row">
%else:
<tr>
%endif
<td>
<a href="${h.url_for( controller='admin', action='role', role_id=role.id )}">${role.name}</a>
<a id="role-${role.id}-popup" class="popup-arrow" style="display: none;">&#9660;</a>
<div popupmenu="role-${role.id}-popup">
<a class="action-button" href="${h.url_for( controller='admin', action='role', rename=True, role_id=role.id )}">Rename this role</a>
<a class="action-button" href="${h.url_for( controller='admin', action='role', role_id=role.id )}">Change associated users and groups</a>
<a class="action-button" href="${h.url_for( controller='admin', action='mark_role_deleted', role_id=role.id )}">Mark role deleted</a>
</div>
</td>
<td>${role.description}</td>
<td>${role.type}</td>
<td>
${len( role.users )}
</td>
<td>
${len( role.groups )}
%if not anchored:
<a name="${curr_anchor}"></a>
<div style="float: right;"><a href="#TOP">top</a></div>
%endif
</td>
</tr>
</%def>
<a name="TOP"><h2>Roles</h2></a>
<ul class="manage-table-actions">
<li><a class="action-button" href="${h.url_for( controller='admin', action='create_role' )}">Create a new role</a></li>
<li><a class="action-button" href="${h.url_for( controller='admin', action='deleted_roles' )}">Manage deleted roles</a></li>
</ul>
%if msg:
${render_msg( msg, messagetype )}
%endif
%if not roles:
There are no non-private Galaxy roles
%else:
<table class="manage-table colored" border="0" cellspacing="0" cellpadding="0" width="100%">
<%
render_quick_find = roles.count() > 200
ctr = 0
%>
%if render_quick_find:
<%
anchors = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
anchor_loc = 0
anchored = False
curr_anchor = 'A'
%>
<tr style="background: #EEE">
<td colspan="4" style="text-align: center; border-bottom: 1px solid #D8B365">
Jump to letter:
%for a in anchors:
| <a href="#${a}">${a}</a>
%endfor
</td>
</tr>
%endif
<tr class="header">
<td>Name</td>
<td>Description</td>
<td>Type</td>
<td>Users</td>
<td>Groups</td>
</tr>
%for ctr, role in enumerate( roles ):
%if render_quick_find and not role.name.upper().startswith( curr_anchor ):
<% anchored = False %>
%endif
%if render_quick_find and role.name.upper().startswith( curr_anchor ):
%if not anchored:
${render_row( role, ctr, anchored, curr_anchor )}
<% anchored = True %>
%else:
${render_row( role, ctr, anchored, curr_anchor )}
%endif
%elif render_quick_find:
%for anchor in anchors[ anchor_loc: ]:
%if role.name.upper().startswith( anchor ):
%if not anchored:
<% curr_anchor = anchor %>
${render_row( role, ctr, anchored, curr_anchor )}
<% anchored = True %>
%else:
${render_row( role, ctr, anchored, curr_anchor )}
%endif
<%
anchor_loc = anchors.index( anchor )
break
%>
%endif
%endfor
%else:
${render_row( role, ctr, True, '' )}
%endif
%endfor
</table>
%endif
+1 -224
View File
@@ -1,224 +1 @@
<%inherit file="/base.mako"/>
<%def name="title()">${grid.title}</%def>
<% from galaxy import util %>
%if message:
<p>
<div class="${message_type}message transient-message">${util.restore_text( message )}</div>
<div style="clear: both"></div>
</p>
%endif
<%def name="javascripts()">
${parent.javascripts()}
${h.js("jquery.autocomplete", "autocomplete_tagging" )}
<script type="text/javascript">
## TODO: generalize and move into galaxy.base.js
$(document).ready(function() {
$(".grid").each( function() {
var grid = this;
var checkboxes = $(this).find("input.grid-row-select-checkbox");
var update = $(this).find( "span.grid-selected-count" );
$(checkboxes).each( function() {
$(this).change( function() {
var n = $(checkboxes).filter("[checked]").size();
update.text( n );
});
})
});
});
## Can this be moved into base.mako?
%if refresh_frames:
%if 'masthead' in refresh_frames:
## Refresh masthead == user changes (backward compatibility)
if ( parent.user_changed ) {
%if trans.user:
parent.user_changed( "${trans.user.email}", ${int( app.config.is_admin_user( trans.user ) )} );
%else:
parent.user_changed( null, false );
%endif
}
%endif
%if 'history' in refresh_frames:
if ( parent.frames && parent.frames.galaxy_history ) {
parent.frames.galaxy_history.location.href="${h.url_for( controller='root', action='history')}";
if ( parent.force_right_panel ) {
parent.force_right_panel( 'show' );
}
}
%endif
%if 'tools' in refresh_frames:
if ( parent.frames && parent.frames.galaxy_tools ) {
parent.frames.galaxy_tools.location.href="${h.url_for( controller='root', action='tool_menu')}";
if ( parent.force_left_panel ) {
parent.force_left_panel( 'show' );
}
}
%endif
%endif
</script>
</%def>
<%def name="stylesheets()">
${h.css( "base", "autocomplete_tagging" )}
<style>
## Not generic to all grids -- move to base?
.count-box {
min-width: 1.1em;
padding: 5px;
border-width: 1px;
border-style: solid;
text-align: center;
display: inline-block;
}
</style>
</%def>
%if grid.standard_filters:
<div class="grid-header">
<h2>${grid.title}</h2>
<span class="title">Filter:</span>
%for i, filter in enumerate( grid.standard_filters ):
%if i > 0:
<span>|</span>
%endif
<span class="filter"><a href="${url( filter.get_url_args() )}">${filter.label}</a></span>
%endfor
</div>
%endif
<ul class="manage-table-actions">
<li><a class="action-button" href="${h.url_for( controller='admin', action='users', operation='create' )}">Create a new user</a></li>
</ul>
%if query.count() == 0:
No users were returned for the current query. Click the Show all users button or a letter below.
%endif:
<%
letters = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
%>
<div class="toolFormBody">
<div class="form-row">
<a class="action-button" href="${h.url_for( controller='admin', action='users', email_filter='all' )}"><span>Show all users</span></a>
<div class="toolParamHelp" style="clear: both;">
Default behavior is displaying only users whose email begins with 'a' if there are more than 200 total users
</div>
</div>
<div class="form-row">
<label>Show only users whose email starts with:</label>
%for letter in letters:
| <a href="${h.url_for( controller='admin', action='users', email_filter=letter )}">${letter}</a>
%endfor
<div style="clear: both"></div>
</div>
<form name="user_actions" action="${url()}" method="post">
<table class="grid">
<thead>
<tr>
<th></th>
%for column in grid.columns:
%if column.visible:
<%
href = ""
extra = ""
if column.sortable:
if sort_key == column.key:
if sort_order == "asc":
href = url( sort=( "-" + column.key ) )
extra = "&darr;"
else:
href = url( sort=( column.key ) )
extra = "&uarr;"
else:
href = url( sort=column.key )
%>
<th\
%if column.ncells > 1:
colspan="${column.ncells}"
%endif
>
%if href:
<a href="${href}">${column.label}</a>
%else:
${column.label}
%endif
<span>${extra}</span>
</th>
%endif
%endfor
<th></th>
</tr>
</thead>
<tbody>
%for i, item in enumerate( query ):
<tr \
%if current_item == item:
class="current" \
%endif
>
## Item selection column
<td style="width: 1.5em;">
<input type="checkbox" name="id" value=${trans.security.encode_id( item.id )} class="grid-row-select-checkbox" />
</td>
## Data columns
%for column in grid.columns:
%if column.visible:
<%
# Link
link = column.get_link( trans, grid, item )
if link:
href = url( **link )
else:
href = None
# Value (coerced to list so we can loop)
value = column.get_value( trans, grid, item )
if column.ncells == 1:
value = [ value ]
%>
%for cellnum, v in enumerate( value ):
<%
# Attach popup menu?
if column.attach_popup and cellnum == 0:
extra = '<a id="grid-%d-popup" class="arrow" style="display: none;"><span>&#9660;</span></a>' % i
else:
extra = ""
%>
%if href:
<td><div class="menubutton split" style="float: left;"><a class="label" href="${href}">${v}${extra}</a> </td>
%else:
<td >${v}${extra}</td>
%endif
%endfor
%endif
%endfor
## Actions column
<td>
<div popupmenu="grid-${i}-popup">
%for operation in grid.operations:
%if operation.allowed( item ) and operation.allow_popup:
<a class="action-button" href="${url( operation=operation.label, id=item.id )}">${operation.label}</a>
%endif
%endfor
</div>
</td>
</tr>
%endfor
</tbody>
%if grid.operations:
<tfoot>
<tr>
<td></td>
<td colspan="100">
For <span class="grid-selected-count"></span> selected users:
%for operation in grid.operations:
%if operation.allow_multiple:
<input type="submit" name="operation" value="${operation.label}" class="action-button">
%endif
%endfor
</td>
</tr>
</tfoot>
%endif
</table>
</form>
</div>
<%inherit file="/grid_base.mako"/>
+9 -2
View File
@@ -1,5 +1,6 @@
<%!
from galaxy.model import History, HistoryDatasetAssociation
from galaxy.model import History, HistoryDatasetAssociation, User, Role, Group
import galaxy.util
def inherit(context):
if context.get('use_panels'):
return '/base_panels.mako'
@@ -11,7 +12,7 @@
## Render the grid's basic elements. Each of these elements can be subclassed.
%if message:
<p>
<div class="${message_type}message transient-message">${message}</div>
<div class="${message_type}message transient-message">${util.restore_text( message )}</div>
<div style="clear: both"></div>
</p>
%endif
@@ -303,6 +304,12 @@ ${self.grid_table()}
items_plural = "histories"
elif grid.model_class == HistoryDatasetAssociation:
items_plural = "datasets"
elif grid.model_class == User:
items_plural = "users"
elif grid.model_class == Role:
items_plural = "roles"
elif grid.model_class == Group:
items_plural = "groups"
%>
%if num_pages > 1:
<tr>
+20 -12
View File
@@ -672,7 +672,8 @@ class TwillTestCase( unittest.TestCase ):
self.check_page_for_string( "The user information has been updated with the changes." )
for value in info_values:
self.check_page_for_string( value )
def user_set_default_permissions( self, permissions_out=[], permissions_in=[], role_id=2 ): # role.id = 2 is Private Role for test2@bx.psu.edu
def user_set_default_permissions( self, permissions_out=[], permissions_in=[], role_id='2' ):
# role.id = 2 is Private Role for test2@bx.psu.edu
# NOTE: Twill has a bug that requires the ~/user/permissions page to contain at least 1 option value
# in each select list or twill throws an exception, which is: ParseError: OPTION outside of SELECT
# Due to this bug, we'll bypass visiting the page, and simply pass the permissions on to the
@@ -921,6 +922,7 @@ class TwillTestCase( unittest.TestCase ):
# Tests associated with users
def create_new_account_as_admin( self, email='test4@bx.psu.edu', password='testuser' ):
"""Create a new account for another user"""
# TODO: fix this so that it uses the form rather than the following URL.
self.home()
self.visit_url( "%s/user/create?admin_view=True&email=%s&password=%s&confirm=%s&create_user_button=Submit&subscribe=False" \
% ( self.url, email, password, password ) )
@@ -983,7 +985,13 @@ class TwillTestCase( unittest.TestCase ):
self.home()
# Tests associated with roles
def create_role( self, name='Role One', description="This is Role One", in_user_ids=[], in_group_ids=[], create_group_for_role='no', private_role='' ):
def create_role( self,
name='Role One',
description="This is Role One",
in_user_ids=[],
in_group_ids=[],
create_group_for_role='no',
private_role='' ):
"""Create a new role"""
url = "%s/admin/create_role?create_role_button=Save&name=%s&description=%s" % ( self.url, name.replace( ' ', '+' ), description.replace( ' ', '+' ) )
if in_user_ids:
@@ -1017,7 +1025,7 @@ class TwillTestCase( unittest.TestCase ):
def rename_role( self, role_id, name='Role One Renamed', description='This is Role One Re-described' ):
"""Rename a role"""
self.home()
self.visit_url( "%s/admin/role?rename=True&role_id=%s" % ( self.url, role_id ) )
self.visit_url( "%s/admin/role?rename=True&id=%s" % ( self.url, role_id ) )
self.check_page_for_string( 'Change role name and description' )
tc.fv( "1", "name", name )
tc.fv( "1", "description", description )
@@ -1026,28 +1034,28 @@ class TwillTestCase( unittest.TestCase ):
def mark_role_deleted( self, role_id, role_name ):
"""Mark a role as deleted"""
self.home()
self.visit_url( "%s/admin/mark_role_deleted?role_id=%s" % ( self.url, role_id ) )
self.visit_url( "%s/admin/roles?operation=delete&id=%s" % ( self.url, role_id ) )
check_str = "Role '%s' has been marked as deleted" % role_name
self.check_page_for_string( check_str )
self.home()
def undelete_role( self, role_id, role_name ):
"""Undelete an existing role"""
self.home()
self.visit_url( "%s/admin/undelete_role?role_id=%s" % ( self.url, role_id ) )
self.visit_url( "%s/admin/roles?operation=undelete&id=%s" % ( self.url, role_id ) )
check_str = "Role '%s' has been marked as not deleted" % role_name
self.check_page_for_string( check_str )
self.home()
def purge_role( self, role_id, role_name ):
"""Purge an existing role"""
self.home()
self.visit_url( "%s/admin/purge_role?role_id=%s" % ( self.url, role_id ) )
self.visit_url( "%s/admin/roles?operation=purge&id=%s" % ( self.url, role_id ) )
check_str = "The following have been purged from the database for role '%s': " % role_name
check_str += "DefaultUserPermissions, DefaultHistoryPermissions, UserRoleAssociations, GroupRoleAssociations, DatasetPermissionss."
self.check_page_for_string( check_str )
self.home()
def associate_users_and_groups_with_role( self, role_id, role_name, user_ids=[], group_ids=[] ):
self.home()
url = "%s/admin/role?role_id=%s&role_members_edit_button=Save" % ( self.url, role_id )
url = "%s/admin/role?id=%s&role_members_edit_button=Save" % ( self.url, role_id )
if user_ids:
url += "&in_users=%s" % ','.join( user_ids )
if group_ids:
@@ -1076,14 +1084,14 @@ class TwillTestCase( unittest.TestCase ):
def rename_group( self, group_id, name='Group One Renamed' ):
"""Rename a group"""
self.home()
self.visit_url( "%s/admin/group?rename=True&group_id=%s" % ( self.url, group_id ) )
self.visit_url( "%s/admin/group?rename=True&id=%s" % ( self.url, group_id ) )
self.check_page_for_string( 'Change group name' )
tc.fv( "1", "name", name )
tc.submit( "rename_group_button" )
self.home()
def associate_users_and_roles_with_group( self, group_id, group_name, user_ids=[], role_ids=[] ):
self.home()
url = "%s/admin/group?group_id=%s&group_roles_users_edit_button=Save" % ( self.url, group_id )
url = "%s/admin/group?id=%s&group_roles_users_edit_button=Save" % ( self.url, group_id )
if user_ids:
url += "&in_users=%s" % ','.join( user_ids )
if role_ids:
@@ -1095,21 +1103,21 @@ class TwillTestCase( unittest.TestCase ):
def mark_group_deleted( self, group_id, group_name ):
"""Mark a group as deleted"""
self.home()
self.visit_url( "%s/admin/mark_group_deleted?group_id=%s" % ( self.url, group_id ) )
self.visit_url( "%s/admin/groups?operation=delete&id=%s" % ( self.url, group_id ) )
check_str = "Group '%s' has been marked as deleted" % group_name
self.check_page_for_string( check_str )
self.home()
def undelete_group( self, group_id, group_name ):
"""Undelete an existing group"""
self.home()
self.visit_url( "%s/admin/undelete_group?group_id=%s" % ( self.url, group_id ) )
self.visit_url( "%s/admin/groups?operation=undelete&id=%s" % ( self.url, group_id ) )
check_str = "Group '%s' has been marked as not deleted" % group_name
self.check_page_for_string( check_str )
self.home()
def purge_group( self, group_id, group_name ):
"""Purge an existing group"""
self.home()
self.visit_url( "%s/admin/purge_group?group_id=%s" % ( self.url, group_id ) )
self.visit_url( "%s/admin/groups?operation=purge&id=%s" % ( self.url, group_id ) )
check_str = "The following have been purged from the database for group '%s': UserGroupAssociations, GroupRoleAssociations." % group_name
self.check_page_for_string( check_str )
self.home()
+2 -2
View File
@@ -780,8 +780,8 @@ class TestHistory( TwillTestCase ):
self.delete_history( id=self.security.encode_id( history4.id ) )
self.delete_history( id=self.security.encode_id( history5.id ) )
# Eliminate Sharing role for: test@bx.psu.edu, test2@bx.psu.edu
self.mark_role_deleted( str( sharing_role.id ), sharing_role.name )
self.purge_role( str( sharing_role.id ), sharing_role.name )
self.mark_role_deleted( self.security.encode_id( sharing_role.id ), sharing_role.name )
self.purge_role( self.security.encode_id( sharing_role.id ), sharing_role.name )
# Manually delete the sharing role from the database
sa_session.refresh( sharing_role )
sa_session.delete( sharing_role )
+58 -44
View File
@@ -327,8 +327,12 @@ class TestSecurityAndLibraries( TwillTestCase ):
name = 'Role One'
description = "This is Role Ones description"
user_ids=[ str( admin_user.id ), str( regular_user1.id ), str( regular_user3.id ) ]
self.create_role( name=name, description=description, in_user_ids=user_ids, in_group_ids=[],
create_group_for_role='yes', private_role=admin_user.email )
self.create_role( name=name,
description=description,
in_user_ids=user_ids,
in_group_ids=[],
create_group_for_role='yes',
private_role=admin_user.email )
# Get the role object for later tests
global role_one
role_one = sa_session.query( galaxy.model.Role ).filter( galaxy.model.Role.table.c.name==name ).first()
@@ -352,13 +356,13 @@ class TestSecurityAndLibraries( TwillTestCase ):
# Rename the role
rename = "Role One's been Renamed"
redescription="This is Role One's Re-described"
self.rename_role( str( role_one.id ), name=rename, description=redescription )
self.rename_role( self.security.encode_id( role_one.id ), name=rename, description=redescription )
self.home()
self.visit_page( 'admin/roles' )
self.check_page_for_string( rename )
self.check_page_for_string( redescription )
# Reset the role back to the original name and description
self.rename_role( str( role_one.id ), name=name, description=description )
self.rename_role( self.security.encode_id( role_one.id ), name=name, description=description )
def test_050_create_group( self ):
"""Testing creating new group with 3 members and 1 associated role, then renaming it"""
name = "Group One's Name"
@@ -384,12 +388,12 @@ class TestSecurityAndLibraries( TwillTestCase ):
% ( len( group_one.roles ), group_one.id, len( role_ids ) ) )
# Rename the group
rename = "Group One's been Renamed"
self.rename_group( str( group_one.id ), name=rename, )
self.rename_group( self.security.encode_id( group_one.id ), name=rename, )
self.home()
self.visit_page( 'admin/groups' )
self.check_page_for_string( rename )
# Reset the group back to the original name
self.rename_group( str( group_one.id ), name=name )
self.rename_group( self.security.encode_id( group_one.id ), name=name )
def test_055_add_members_and_role_to_group( self ):
"""Testing editing user membership and role associations of an existing group"""
name = 'Group Two'
@@ -405,10 +409,12 @@ class TestSecurityAndLibraries( TwillTestCase ):
if group_two.roles:
raise AssertionError( '%d GroupRoleAssociations were created for group id %d when it was created ( should have been 0 )' \
% ( len( group_two.roles ), group_two.id ) )
group_two_id = str( group_two.id )
user_ids = [ str( regular_user1.id ) ]
role_ids = [ str( role_one.id ) ]
self.associate_users_and_roles_with_group( group_two.id, group_two.name, user_ids=user_ids, role_ids=role_ids )
self.associate_users_and_roles_with_group( self.security.encode_id( group_two.id ),
group_two.name,
user_ids=user_ids,
role_ids=role_ids )
def test_060_create_role_with_user_and_group_associations( self ):
"""Testing creating a role with user and group associations"""
# NOTE: To get this to work with twill, all select lists on the ~/admin/role page must contain at least
@@ -421,7 +427,11 @@ class TestSecurityAndLibraries( TwillTestCase ):
group_ids=[ str( group_two.id ) ]
private_role=admin_user.email
# Create the role
self.create_role( name=name, description=description, in_user_ids=user_ids, in_group_ids=group_ids, private_role=private_role )
self.create_role( name=name,
description=description,
in_user_ids=user_ids,
in_group_ids=group_ids,
private_role=private_role )
# Get the role object for later tests
global role_two
role_two = sa_session.query( galaxy.model.Role ).filter( galaxy.model.Role.table.c.name==name ).first()
@@ -451,7 +461,11 @@ class TestSecurityAndLibraries( TwillTestCase ):
user_ids=[]
group_ids=[]
private_role=admin_user.email
self.create_role( name=name, description=description, in_user_ids=user_ids, in_group_ids=group_ids, private_role=private_role )
self.create_role( name=name,
description=description,
in_user_ids=user_ids,
in_group_ids=group_ids,
private_role=private_role )
# Get the role object for later tests
global role_three
role_three = sa_session.query( galaxy.model.Role ).filter( galaxy.model.Role.table.c.name==name ).first()
@@ -466,8 +480,11 @@ class TestSecurityAndLibraries( TwillTestCase ):
for uga in admin_user.groups:
group_ids.append( str( uga.group_id ) )
check_str = "User '%s' has been updated with %d associated roles and %d associated groups" % ( admin_user.email, len( role_ids ), len( group_ids ) )
self.associate_roles_and_groups_with_user( self.security.encode_id( admin_user.id ), str( admin_user.email ),
in_role_ids=role_ids, in_group_ids=group_ids, check_str=check_str )
self.associate_roles_and_groups_with_user( self.security.encode_id( admin_user.id ),
str( admin_user.email ),
in_role_ids=role_ids,
in_group_ids=group_ids,
check_str=check_str )
sa_session.refresh( admin_user )
# admin_user should now be associated with 4 roles: private, role_one, role_two, role_three
if len( admin_user.roles ) != 4:
@@ -1374,7 +1391,7 @@ class TestSecurityAndLibraries( TwillTestCase ):
self.home()
self.visit_url( '%s/admin/groups' % self.url )
self.check_page_for_string( group_two.name )
self.mark_group_deleted( str( group_two.id ), group_two.name )
self.mark_group_deleted( self.security.encode_id( group_two.id ), group_two.name )
sa_session.refresh( group_two )
if not group_two.deleted:
raise AssertionError( '%s was not correctly marked as deleted.' % group_two.name )
@@ -1386,7 +1403,7 @@ class TestSecurityAndLibraries( TwillTestCase ):
def test_175_undelete_group( self ):
"""Testing undeleting a deleted group"""
# Logged in as admin_user
self.undelete_group( str( group_two.id ), group_two.name )
self.undelete_group( self.security.encode_id( group_two.id ), group_two.name )
sa_session.refresh( group_two )
if group_two.deleted:
raise AssertionError( '%s was not correctly marked as not deleted.' % group_two.name )
@@ -1396,7 +1413,7 @@ class TestSecurityAndLibraries( TwillTestCase ):
self.home()
self.visit_url( '%s/admin/roles' % self.url )
self.check_page_for_string( role_two.name )
self.mark_role_deleted( str( role_two.id ), role_two.name )
self.mark_role_deleted( self.security.encode_id( role_two.id ), role_two.name )
sa_session.refresh( role_two )
if not role_two.deleted:
raise AssertionError( '%s was not correctly marked as deleted.' % role_two.name )
@@ -1408,7 +1425,7 @@ class TestSecurityAndLibraries( TwillTestCase ):
def test_185_undelete_role( self ):
"""Testing undeleting a deleted role"""
# Logged in as admin_user
self.undelete_role( str( role_two.id ), role_two.name )
self.undelete_role( self.security.encode_id( role_two.id ), role_two.name )
def test_190_mark_dataset_deleted( self ):
"""Testing marking a library dataset as deleted"""
# Logged in as admin_user
@@ -1541,59 +1558,57 @@ class TestSecurityAndLibraries( TwillTestCase ):
def test_235_purge_group( self ):
"""Testing purging a group"""
# Logged in as admin_user
group_id = str( group_two.id )
self.mark_group_deleted( group_id, group_two.name )
self.purge_group( group_id, group_two.name )
self.mark_group_deleted( self.security.encode_id( group_two.id ), group_two.name )
self.purge_group( self.security.encode_id( group_two.id ), group_two.name )
# Make sure there are no UserGroupAssociations
uga = sa_session.query( galaxy.model.UserGroupAssociation ) \
.filter( galaxy.model.UserGroupAssociation.table.c.group_id == group_id ) \
.filter( galaxy.model.UserGroupAssociation.table.c.group_id == group_two.id ) \
.first()
if uga:
raise AssertionError( "Purging the group did not delete the UserGroupAssociations for group_id '%s'" % group_id )
raise AssertionError( "Purging the group did not delete the UserGroupAssociations for group_id '%s'" % group_two.id )
# Make sure there are no GroupRoleAssociations
gra = sa_session.query( galaxy.model.GroupRoleAssociation ) \
.filter( galaxy.model.GroupRoleAssociation.table.c.group_id == group_id ) \
.filter( galaxy.model.GroupRoleAssociation.table.c.group_id == group_two.id ) \
.first()
if gra:
raise AssertionError( "Purging the group did not delete the GroupRoleAssociations for group_id '%s'" % group_id )
raise AssertionError( "Purging the group did not delete the GroupRoleAssociations for group_id '%s'" % group_two.id )
# Undelete the group for later test runs
self.undelete_group( group_id, group_two.name )
self.undelete_group( self.security.encode_id( group_two.id ), group_two.name )
def test_240_purge_role( self ):
"""Testing purging a role"""
# Logged in as admin_user
role_id = str( role_two.id )
self.mark_role_deleted( role_id, role_two.name )
self.purge_role( role_id, role_two.name )
self.mark_role_deleted( self.security.encode_id( role_two.id ), role_two.name )
self.purge_role( self.security.encode_id( role_two.id ), role_two.name )
# Make sure there are no UserRoleAssociations
uras = sa_session.query( galaxy.model.UserRoleAssociation ) \
.filter( galaxy.model.UserRoleAssociation.table.c.role_id == role_id ) \
.filter( galaxy.model.UserRoleAssociation.table.c.role_id == role_two.id ) \
.all()
if uras:
raise AssertionError( "Purging the role did not delete the UserRoleAssociations for role_id '%s'" % role_id )
raise AssertionError( "Purging the role did not delete the UserRoleAssociations for role_id '%s'" % role_two.id )
# Make sure there are no DefaultUserPermissions associated with the Role
dups = sa_session.query( galaxy.model.DefaultUserPermissions ) \
.filter( galaxy.model.DefaultUserPermissions.table.c.role_id == role_id ) \
.filter( galaxy.model.DefaultUserPermissions.table.c.role_id == role_two.id ) \
.all()
if dups:
raise AssertionError( "Purging the role did not delete the DefaultUserPermissions for role_id '%s'" % role_id )
raise AssertionError( "Purging the role did not delete the DefaultUserPermissions for role_id '%s'" % role_two.id )
# Make sure there are no DefaultHistoryPermissions associated with the Role
dhps = sa_session.query( galaxy.model.DefaultHistoryPermissions ) \
.filter( galaxy.model.DefaultHistoryPermissions.table.c.role_id == role_id ) \
.filter( galaxy.model.DefaultHistoryPermissions.table.c.role_id == role_two.id ) \
.all()
if dhps:
raise AssertionError( "Purging the role did not delete the DefaultHistoryPermissions for role_id '%s'" % role_id )
raise AssertionError( "Purging the role did not delete the DefaultHistoryPermissions for role_id '%s'" % role_two.id )
# Make sure there are no GroupRoleAssociations
gra = sa_session.query( galaxy.model.GroupRoleAssociation ) \
.filter( galaxy.model.GroupRoleAssociation.table.c.role_id == role_id ) \
.filter( galaxy.model.GroupRoleAssociation.table.c.role_id == role_two.id ) \
.first()
if gra:
raise AssertionError( "Purging the role did not delete the GroupRoleAssociations for role_id '%s'" % role_id )
raise AssertionError( "Purging the role did not delete the GroupRoleAssociations for role_id '%s'" % role_two.id )
# Make sure there are no DatasetPermissionss
dp = sa_session.query( galaxy.model.DatasetPermissions ) \
.filter( galaxy.model.DatasetPermissions.table.c.role_id == role_id ) \
.filter( galaxy.model.DatasetPermissions.table.c.role_id == role_two.id ) \
.first()
if dp:
raise AssertionError( "Purging the role did not delete the DatasetPermissionss for role_id '%s'" % role_id )
raise AssertionError( "Purging the role did not delete the DatasetPermissionss for role_id '%s'" % role_two.id )
def test_245_manually_unpurge_role( self ):
"""Testing manually un-purging a role"""
# Logged in as admin_user
@@ -1601,7 +1616,7 @@ class TestSecurityAndLibraries( TwillTestCase ):
# TODO: If we decide to implement the GUI feature for un-purging a role, replace this with a method call
role_two.purged = False
role_two.flush()
self.undelete_role( str( role_two.id ), role_two.name )
self.undelete_role( self.security.encode_id( role_two.id ), role_two.name )
def test_250_purge_library( self ):
"""Testing purging a library"""
# Logged in as admin_user
@@ -1815,8 +1830,8 @@ class TestSecurityAndLibraries( TwillTestCase ):
# Eliminate all non-private roles
##################
for role in [ role_one, role_two, role_three ]:
self.mark_role_deleted( str( role.id ), role.name )
self.purge_role( str( role.id ), role.name )
self.mark_role_deleted( self.security.encode_id( role.id ), role.name )
self.purge_role( self.security.encode_id( role.id ), role.name )
# Manually delete the role from the database
sa_session.refresh( role )
sa_session.delete( role )
@@ -1825,8 +1840,8 @@ class TestSecurityAndLibraries( TwillTestCase ):
# Eliminate all groups
##################
for group in [ group_zero, group_one, group_two ]:
self.mark_group_deleted( str( group.id ), group.name )
self.purge_group( str( group.id ), group.name )
self.mark_group_deleted( self.security.encode_id( group.id ), group.name )
self.purge_group( self.security.encode_id( group.id ), group.name )
# Manually delete the group from the database
sa_session.refresh( group )
sa_session.delete( group )
@@ -1846,7 +1861,6 @@ class TestSecurityAndLibraries( TwillTestCase ):
# Change DefaultHistoryPermissions for regular_user1 back to the default
permissions_in = [ 'DATASET_MANAGE_PERMISSIONS' ]
permissions_out = [ 'DATASET_ACCESS' ]
role_id = str( regular_user1_private_role.id )
self.user_set_default_permissions( permissions_in=permissions_in, permissions_out=permissions_out, role_id=role_id )
self.user_set_default_permissions( permissions_in=permissions_in, permissions_out=permissions_out, role_id=str( regular_user1_private_role.id ) )
self.logout()
self.login( email=admin_user.email )
+42 -10
View File
@@ -8,6 +8,7 @@
<tool file="data_source/biomart.xml" />
<tool file="data_source/gramene_mart.xml" />
<tool file="data_source/flymine.xml" />
<tool file="data_source/eupathdb.xml" />
<tool file="data_source/encode_db.xml" />
<tool file="data_source/epigraph_import.xml" />
</section>
@@ -27,6 +28,7 @@
<tool file="filters/catWrapper.xml" />
<tool file="filters/condense_characters.xml" />
<tool file="filters/convert_characters.xml" />
<tool file="filters/mergeCols.xml" />
<tool file="filters/CreateInterval.xml" />
<tool file="filters/cutWrapper.xml" />
<tool file="filters/changeCase.xml" />
@@ -34,15 +36,17 @@
<tool file="filters/remove_beginning.xml" />
<tool file="filters/headWrapper.xml" />
<tool file="filters/tailWrapper.xml" />
<tool file="filters/trimmer.xml" />
</section>
<section name="Convert Formats" id="convert">
<tool file="filters/bed2gff.xml" />
<tool file="fasta_tools/fasta_to_tabular.xml" />
<tool file="filters/gff2bed.xml" />
<tool file="maf/maf_to_bed.xml" />
<tool file="maf/maf_to_interval.xml" />
<tool file="maf/maf_to_interval.xml" />
<tool file="maf/maf_to_fasta.xml" />
<tool file="fasta_tools/tabular_to_fasta.xml" />
<tool file="fastx_toolkit/fastq_to_fasta.xml" />
</section>
<section name="FASTA manipulation" id="fasta_manipulation">
<tool file="fasta_tools/fasta_compute_length.xml" />
@@ -50,6 +54,9 @@
<tool file="fasta_tools/fasta_concatenate_by_species.xml" />
<tool file="fasta_tools/fasta_to_tabular.xml" />
<tool file="fasta_tools/tabular_to_fasta.xml" />
<tool file="fastx_toolkit/fasta_formatter.xml" />
<tool file="fastx_toolkit/fasta_nucleotide_changer.xml" />
<tool file="fastx_toolkit/fastx_collapser.xml" />
</section>
<section name="Filter and Sort" id="filter">
<tool file="stats/filtering.xml" />
@@ -80,9 +87,7 @@
<tool file="maf/maf_limit_size.xml"/>
<tool file="maf/maf_by_block_number.xml"/>
<tool file="maf/maf_filter.xml"/>
<!--
<tool file="maf/maf_reverse_complement.xml"/>
-->
</section>
<section name="Get Genomic Scores" id="scores">
<tool file="stats/wiggle_to_simple.xml" />
@@ -90,7 +95,7 @@
<tool file="extract/phastOdds/phastOdds_tool.xml" />
</section>
<section name="Operate on Genomic Intervals" id="bxops">
<tool file="new_operations/intersect.xml" />
<tool file="new_operations/intersect.xml" />
<tool file="new_operations/subtract.xml" />
<tool file="new_operations/merge.xml" />
<tool file="new_operations/concat.xml" />
@@ -147,12 +152,6 @@
<tool file="taxonomy/lca.xml" />
<tool file="taxonomy/poisson2test.xml" />
</section>
<section name="Short Read Analysis" id="short_read_analysis">
<tool file="metag_tools/short_reads_figure_score.xml" />
<tool file="metag_tools/short_reads_trim_seq.xml" />
<tool file="metag_tools/megablast_wrapper.xml" />
<tool file="metag_tools/megablast_xml_parser.xml" />
</section>
<section name="EMBOSS" id="EMBOSSLite">
<tool file="emboss_5/emboss_antigenic.xml" />
<tool file="emboss_5/emboss_backtranseq.xml" />
@@ -262,4 +261,37 @@
<tool file="emboss_5/emboss_wordcount.xml" />
<tool file="emboss_5/emboss_wordmatch.xml" />
</section>
<label text="NGS Toolbox Beta" id="ngs" />
<section name="NGS: QC and manipulation" id="cshl_library_information">
<label text="Generic FASTQ data" id="fastq" />
<tool file="next_gen_conversion/fastq_gen_conv.xml" />
<tool file="fastx_toolkit/fastq_quality_converter.xml" />
<tool file="fastx_toolkit/fastx_quality_statistics.xml" />
<tool file="fastx_toolkit/fastq_quality_boxplot.xml" />
<tool file="fastx_toolkit/fastx_nucleotides_distribution.xml" />
<tool file="metag_tools/split_paired_reads.xml" />
<label text="Roche-454 data" id="454" />
<tool file="metag_tools/short_reads_figure_score.xml" />
<tool file="metag_tools/short_reads_trim_seq.xml" />
<label text="AB-SOLiD data" id="solid" />
<tool file="next_gen_conversion/solid_to_fastq.xml" />
<tool file="solid_tools/solid_qual_stats.xml" />
<tool file="solid_tools/solid_qual_boxplot.xml" />
</section>
<section name="NGS: Mapping" id="solexa_tools">
<tool file="sr_mapping/bowtie_wrapper.xml" />
<tool file="sr_mapping/bwa_wrapper.xml" />
<!-- <tool file="sr_mapping/lastz_wrapper.xml" /> -->
<tool file="metag_tools/megablast_wrapper.xml" />
<tool file="metag_tools/megablast_xml_parser.xml" />
</section>
<section name="NGS: SAM Tools" id="samtools">
<tool file="samtools/sam_bitwise_flag_filter.xml" />
<tool file="samtools/sam2interval.xml" />
<tool file="samtools/sam_to_bam.xml" />
<tool file="samtools/sam_merge.xml" />
<tool file="samtools/sam_pileup.xml" />
<tool file="samtools/pileup_parser.xml" />
<tool file="samtools/pileup_interval.xml" />
</section>
</toolbox>