lims: added request_types permissions

This commit is contained in:
Ramkrishna Chakrabarty
2010-04-22 21:11:17 -04:00
parent f8eabb60fd
commit b83c9aca9a
8 changed files with 253 additions and 9 deletions
+19
View File
@@ -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',
+15
View File
@@ -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
+37 -1
View File
@@ -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 ):
"""
+1 -2
View File
@@ -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:
+54 -5
View File
@@ -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>
+1 -1
View File
@@ -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">