mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
lims: added request_types permissions
This commit is contained in:
@@ -73,6 +73,18 @@ class User( object ):
|
||||
if can_show:
|
||||
libraries[ library ] = hidden_folder_ids
|
||||
return libraries
|
||||
def accessible_request_types(self, trans):
|
||||
# get all permitted libraries for this user
|
||||
all_rt_list = trans.sa_session.query( trans.app.model.RequestType ) \
|
||||
.filter( trans.app.model.RequestType.table.c.deleted == False ) \
|
||||
.order_by( trans.app.model.RequestType.name )
|
||||
roles = self.all_roles()
|
||||
rt_list = []
|
||||
for rt in all_rt_list:
|
||||
for permission in rt.actions:
|
||||
if permission.role.id in [r.id for r in roles]:
|
||||
rt_list.append(rt)
|
||||
return list(set(rt_list))
|
||||
|
||||
class Job( object ):
|
||||
"""
|
||||
@@ -1445,6 +1457,7 @@ class RequestEvent( object ):
|
||||
self.comment = comment
|
||||
|
||||
class RequestType( object ):
|
||||
permitted_actions = get_permitted_actions( filter='REQUEST_TYPE' )
|
||||
def __init__(self, name=None, desc=None, request_form=None, sample_form=None,
|
||||
datatx_info=None):
|
||||
self.name = name
|
||||
@@ -1452,6 +1465,12 @@ class RequestType( object ):
|
||||
self.request_form = request_form
|
||||
self.sample_form = sample_form
|
||||
self.datatx_info = datatx_info
|
||||
|
||||
class RequestTypePermissions( object ):
|
||||
def __init__( self, action, request_type, role ):
|
||||
self.action = action
|
||||
self.request_type = request_type
|
||||
self.role = role
|
||||
|
||||
class Sample( object ):
|
||||
transfer_status = Bunch( NOT_STARTED = 'Not started',
|
||||
|
||||
@@ -628,6 +628,14 @@ RequestType.table = Table('request_type', metadata,
|
||||
Column( "datatx_info", JSONType() ),
|
||||
Column( "deleted", Boolean, index=True, default=False ) )
|
||||
|
||||
RequestTypePermissions.table = Table( "request_type_permissions", metadata,
|
||||
Column( "id", Integer, primary_key=True ),
|
||||
Column( "create_time", DateTime, default=now ),
|
||||
Column( "update_time", DateTime, default=now, onupdate=now ),
|
||||
Column( "action", TEXT ),
|
||||
Column( "request_type_id", Integer, ForeignKey( "request_type.id" ), nullable=True, index=True ),
|
||||
Column( "role_id", Integer, ForeignKey( "role.id" ), index=True ) )
|
||||
|
||||
FormValues.table = Table('form_values', metadata,
|
||||
Column( "id", Integer, primary_key=True),
|
||||
Column( "create_time", DateTime, default=now ),
|
||||
@@ -923,6 +931,13 @@ assign_mapper( context, RequestType, RequestType.table,
|
||||
primaryjoin=( RequestType.table.c.sample_form_id == FormDefinition.table.c.id ) ),
|
||||
) )
|
||||
|
||||
assign_mapper( context, RequestTypePermissions, RequestTypePermissions.table,
|
||||
properties=dict(
|
||||
request_type=relation( RequestType, backref="actions" ),
|
||||
role=relation( Role, backref="request_type_actions" )
|
||||
)
|
||||
)
|
||||
|
||||
assign_mapper( context, FormDefinition, FormDefinition.table,
|
||||
properties=dict( current=relation( FormDefinitionCurrent,
|
||||
primaryjoin=( FormDefinition.table.c.form_definition_current_id == FormDefinitionCurrent.table.c.id ) )
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
"""
|
||||
Migration script to add the request_type_permissions table.
|
||||
"""
|
||||
|
||||
from sqlalchemy import *
|
||||
from migrate import *
|
||||
from migrate.changeset import *
|
||||
|
||||
import datetime
|
||||
now = datetime.datetime.utcnow
|
||||
|
||||
import logging
|
||||
log = logging.getLogger( __name__ )
|
||||
|
||||
metadata = MetaData( migrate_engine )
|
||||
|
||||
RequestTypePermissions_table = Table( "request_type_permissions", metadata,
|
||||
Column( "id", Integer, primary_key=True ),
|
||||
Column( "create_time", DateTime, default=now ),
|
||||
Column( "update_time", DateTime, default=now, onupdate=now ),
|
||||
Column( "action", TEXT ),
|
||||
Column( "request_type_id", Integer, ForeignKey( "request_type.id" ), nullable=True, index=True ),
|
||||
Column( "role_id", Integer, ForeignKey( "role.id" ), index=True ) )
|
||||
|
||||
def upgrade():
|
||||
print __doc__
|
||||
metadata.reflect()
|
||||
try:
|
||||
RequestTypePermissions_table.create()
|
||||
except Exception, e:
|
||||
log.debug( "Creating request_type_permissions table failed: %s" % str( e ) )
|
||||
|
||||
def downgrade():
|
||||
pass
|
||||
@@ -24,7 +24,10 @@ class RBACAgent:
|
||||
LIBRARY_ACCESS = Action( "access library", "Restrict access to this library to only role members", "restrict" ),
|
||||
LIBRARY_ADD = Action( "add library item", "Role members can add library items to this library item", "grant" ),
|
||||
LIBRARY_MODIFY = Action( "modify library item", "Role members can modify this library item", "grant" ),
|
||||
LIBRARY_MANAGE = Action( "manage library permissions", "Role members can manage roles associated with permissions on this library item", "grant" )
|
||||
LIBRARY_MANAGE = Action( "manage library permissions", "Role members can manage roles associated with permissions on this library item", "grant" ),
|
||||
# Request type permissions
|
||||
REQUEST_TYPE_ACCESS = Action( "access request_type", "Restrict access to this request_type to only role members", "restrict" )
|
||||
|
||||
)
|
||||
def get_action( self, name, default=None ):
|
||||
"""Get a permitted action by its dict key or action name"""
|
||||
@@ -754,6 +757,39 @@ class GalaxyRBACAgent( RBACAgent ):
|
||||
else:
|
||||
hidden_folder_ids = '%d' % sub_folder.id
|
||||
return False, hidden_folder_ids
|
||||
#
|
||||
# RequestType Permissions
|
||||
#
|
||||
def can_access_request_type( self, roles, request_type ):
|
||||
action = self.permitted_actions.REQUEST_TYPE_ACCESS
|
||||
request_type_actions = []
|
||||
for permission in request_type.actions:
|
||||
if permission.action == action.action:
|
||||
request_type_actions.append(permission)
|
||||
if not request_type_actions:
|
||||
return action.model == 'restrict'
|
||||
ret_val = False
|
||||
for item_action in item_actions:
|
||||
if item_action.role in roles:
|
||||
ret_val = True
|
||||
break
|
||||
return ret_val
|
||||
def set_request_type_permissions( self, request_type, permissions={} ):
|
||||
# Set new permissions on request_type, eliminating all current permissions
|
||||
for role_assoc in request_type.actions:
|
||||
self.sa_session.delete( role_assoc )
|
||||
# Add the new permissions on request_type
|
||||
item_class = self.model.RequestType
|
||||
permission_class = self.model.RequestTypePermissions
|
||||
for action, roles in permissions.items():
|
||||
if isinstance( action, Action ):
|
||||
action = action.action
|
||||
for role_assoc in [ permission_class( action, request_type, role ) for role in roles ]:
|
||||
self.sa_session.add( role_assoc )
|
||||
self.sa_session.flush()
|
||||
|
||||
|
||||
|
||||
|
||||
class HostAgent( RBACAgent ):
|
||||
"""
|
||||
|
||||
@@ -623,8 +623,7 @@ class Requests( BaseController ):
|
||||
details=details,
|
||||
edit_mode=edit_mode)
|
||||
def __select_request_type(self, trans, rtid):
|
||||
requesttype_list = trans.sa_session.query( trans.app.model.RequestType )\
|
||||
.order_by( trans.app.model.RequestType.name.asc() )
|
||||
requesttype_list = trans.user.accessible_request_types(trans)
|
||||
rt_ids = ['none']
|
||||
for rt in requesttype_list:
|
||||
if not rt.deleted:
|
||||
|
||||
@@ -195,7 +195,8 @@ class RequestTypeGrid( grids.Grid ):
|
||||
visible=False,
|
||||
filterable="standard" ) )
|
||||
operations = [
|
||||
#grids.GridOperation( "Update", allow_multiple=False, condition=( lambda item: not item.deleted ) ),
|
||||
grids.GridOperation( "Permissions", allow_multiple=False, condition=( lambda item: not item.deleted ) ),
|
||||
#grids.GridOperation( "Clone", allow_multiple=False, condition=( lambda item: not item.deleted ) ),
|
||||
grids.GridOperation( "Delete", allow_multiple=True, condition=( lambda item: not item.deleted ) ),
|
||||
grids.GridOperation( "Undelete", condition=( lambda item: item.deleted ) ),
|
||||
]
|
||||
@@ -258,6 +259,7 @@ class RequestsAdmin( BaseController ):
|
||||
'''
|
||||
List all request made by the current user
|
||||
'''
|
||||
#self.__sample_datasets(trans, **kwd)
|
||||
if 'operation' in kwd:
|
||||
operation = kwd['operation'].lower()
|
||||
if not kwd.get( 'id', None ):
|
||||
@@ -534,8 +536,7 @@ class RequestsAdmin( BaseController ):
|
||||
#---- Request Creation ----------------------------------------------------------
|
||||
#
|
||||
def __select_request_type(self, trans, rtid):
|
||||
requesttype_list = trans.sa_session.query( trans.app.model.RequestType )\
|
||||
.order_by( trans.app.model.RequestType.name.asc() )
|
||||
requesttype_list = trans.user.accessible_request_types(trans)
|
||||
rt_ids = ['none']
|
||||
for rt in requesttype_list:
|
||||
if not rt.deleted:
|
||||
@@ -1771,6 +1772,25 @@ class RequestsAdmin( BaseController ):
|
||||
dataset_index=dataset_index,
|
||||
message=message,
|
||||
status=status)
|
||||
|
||||
# def __sample_datasets(self, trans, **kwd):
|
||||
# samples = trans.sa_session.query( trans.app.model.Sample ).all()
|
||||
# for s in samples:
|
||||
# if s.dataset_files:
|
||||
# newdf = []
|
||||
# for df in s.dataset_files:
|
||||
# if type(s.dataset_files[0]) == type([1,2]):
|
||||
# filepath = df[0]
|
||||
# status = df[1]
|
||||
# newdf.append(dict(filepath=filepath,
|
||||
# status=status,
|
||||
# name=filepath.split('/')[-1],
|
||||
# error_msg='',
|
||||
# size='Unknown'))
|
||||
# s.dataset_files = newdf
|
||||
# trans.sa_session.add( s )
|
||||
# trans.sa_session.flush()
|
||||
#
|
||||
##
|
||||
#### Request Type Stuff ###################################################
|
||||
##
|
||||
@@ -1792,8 +1812,10 @@ class RequestsAdmin( BaseController ):
|
||||
return self.__delete_request_type( trans, **kwd )
|
||||
elif operation == "undelete":
|
||||
return self.__undelete_request_type( trans, **kwd )
|
||||
# elif operation == "update":
|
||||
# return self.__edit_request( trans, **kwd )
|
||||
elif operation == "clone":
|
||||
return self.__clone_request_type( trans, **kwd )
|
||||
elif operation == "permissions":
|
||||
return self.__show_request_type_permissions( trans, **kwd )
|
||||
# Render the grid view
|
||||
return self.requesttype_grid( trans, **kwd )
|
||||
def __view_request_type(self, trans, **kwd):
|
||||
@@ -1992,3 +2014,30 @@ class RequestsAdmin( BaseController ):
|
||||
action='manage_request_types',
|
||||
message='%i request type(s) has been undeleted' % len(id_list),
|
||||
status='done') )
|
||||
def __show_request_type_permissions(self, trans, **kwd ):
|
||||
params = util.Params( kwd )
|
||||
message = util.restore_text( params.get( 'message', '' ) )
|
||||
status = params.get( 'status', 'done' )
|
||||
try:
|
||||
rt = trans.sa_session.query( trans.app.model.RequestType ).get( trans.security.decode_id(kwd['id']) )
|
||||
except:
|
||||
return trans.response.send_redirect( web.url_for( controller='requests_admin',
|
||||
action='manage_request_types',
|
||||
status='error',
|
||||
message="Invalid requesttype ID") )
|
||||
roles = 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 params.get( 'update_roles_button', False ):
|
||||
permissions = {}
|
||||
for k, v in trans.app.model.RequestType.permitted_actions.items():
|
||||
in_roles = [ trans.sa_session.query( trans.app.model.Role ).get( x ) for x in util.listify( params.get( k + '_in', [] ) ) ]
|
||||
permissions[ trans.app.security_agent.get_action( v.action ) ] = in_roles
|
||||
trans.app.security_agent.set_request_type_permissions( rt, permissions )
|
||||
trans.sa_session.refresh( rt )
|
||||
message = "Permissions updated for request type '%s'" % rt.name
|
||||
return trans.fill_template( '/admin/requests/request_type_permissions.mako',
|
||||
request_type=rt,
|
||||
roles=roles,
|
||||
status=status,
|
||||
message=message)
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
<%inherit file="/base.mako"/>
|
||||
<%namespace file="/message.mako" import="render_msg" />
|
||||
|
||||
|
||||
%if message:
|
||||
${render_msg( message, status )}
|
||||
%endif
|
||||
|
||||
<script type="text/javascript">
|
||||
$( document ).ready( function () {
|
||||
$( '.role_add_button' ).click( function() {
|
||||
var action = this.id.substring( 0, this.id.lastIndexOf( '_add_button' ) )
|
||||
var in_select = '#' + action + '_in_select';
|
||||
var out_select = '#' + action + '_out_select';
|
||||
return !$( out_select + ' option:selected' ).remove().appendTo( in_select );
|
||||
});
|
||||
$( '.role_remove_button' ).click( function() {
|
||||
var action = this.id.substring( 0, this.id.lastIndexOf( '_remove_button' ) )
|
||||
var in_select = '#' + action + '_in_select';
|
||||
var out_select = '#' + action + '_out_select';
|
||||
return !$( in_select + ' option:selected' ).remove().appendTo( out_select );
|
||||
});
|
||||
$( 'form#edit_role_associations' ).submit( function() {
|
||||
$( '.in_select option' ).each(function( i ) {
|
||||
$( this ).attr( "selected", "selected" );
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<div class="toolForm">
|
||||
<div class="toolFormTitle">Manage permissions on "${request_type.name}"</div>
|
||||
<div class="toolFormBody">
|
||||
<form name="request_type_permissions" id="request_type_permissions" action="${h.url_for( controller='requests_admin', action='manage_request_types', operation="permissions", id=trans.security.encode_id(request_type.id))}" method="post">
|
||||
<div class="form-row">
|
||||
## %for k, v in permitted_actions:
|
||||
## %if k not in do_not_render:
|
||||
## <div class="form-row">
|
||||
## ${render_select( current_actions, k, v, all_roles )}
|
||||
## </div>
|
||||
## %endif
|
||||
## %endfor
|
||||
## <%def name="render_select( current_actions, action_key, action, all_roles )">
|
||||
<%
|
||||
obj_name = request_type.name
|
||||
current_actions = request_type.actions
|
||||
permitted_actions = trans.app.model.RequestType.permitted_actions.items()
|
||||
action = trans.app.model.RequestType.permitted_actions.REQUEST_TYPE_ACCESS
|
||||
obj_str = 'request_type %s' % obj_name
|
||||
obj_type = 'request_type'
|
||||
all_roles = roles
|
||||
action_key = 'REQUEST_TYPE_ACCESS'
|
||||
|
||||
import sets
|
||||
in_roles = sets.Set()
|
||||
for a in current_actions:
|
||||
if a.action == action.action:
|
||||
in_roles.add( a.role )
|
||||
out_roles = filter( lambda x: x not in in_roles, all_roles )
|
||||
%>
|
||||
<p>
|
||||
<b>${action.action}:</b> ${action.description}
|
||||
</p>
|
||||
<div style="width: 100%; white-space: nowrap;">
|
||||
<div style="float: left; width: 50%;">
|
||||
Roles associated:<br/>
|
||||
<select name="${action_key}_in" id="${action_key}_in_select" class="in_select" style="max-width: 98%; width: 98%; height: 150px; font-size: 100%;" multiple>
|
||||
%for role in in_roles:
|
||||
<option value="${role.id}">${role.name}</option>
|
||||
%endfor
|
||||
</select> <br/>
|
||||
<div style="width: 98%; text-align: right"><input type="submit" id="${action_key}_remove_button" class="role_remove_button" value=">>"/></div>
|
||||
</div>
|
||||
<div style="width: 50%;">
|
||||
Roles not associated:<br/>
|
||||
<select name="${action_key}_out" id="${action_key}_out_select" style="max-width: 98%; width: 98%; height: 150px; font-size: 100%;" multiple>
|
||||
%for role in out_roles:
|
||||
<option value="${role.id}">${role.name}</option>
|
||||
%endfor
|
||||
</select> <br/>
|
||||
<input type="submit" id="${action_key}_add_button" class="role_add_button" value="<<"/>
|
||||
</div>
|
||||
</div>
|
||||
## </%def>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<input type="submit" name="update_roles_button" value="Save"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@@ -36,7 +36,7 @@
|
||||
${tab( "libraries", "Data Libraries", h.url_for( controller='/library', action='index' ))}
|
||||
%endif
|
||||
|
||||
%if trans.user and trans.request_types():
|
||||
%if trans.user and trans.user.accessible_request_types(trans):
|
||||
<td class="tab">
|
||||
<a>Lab</a>
|
||||
<div class="submenu">
|
||||
|
||||
Reference in New Issue
Block a user