Added security to libraries. Non-admin users can now only see libraries that contain datasets associated with the user's groups, and each library will only display those datasets that are associated with the user's groups.

This commit is contained in:
Greg Von Kuster
2008-08-19 10:04:30 -04:00
parent 751cca164b
commit f50ee0fff3
6 changed files with 142 additions and 41 deletions
+5 -1
View File
@@ -703,6 +703,8 @@ class Admin( BaseController ):
gdpa_dict[ group_id ].append( dpa )
else:
gdpa_dict[ group_id ] = [ dpa ]
# Refresh the Dataset to ensure we have a valid set of DatasetGroupAssociations
dataset.dataset.refresh()
# Check to see if we need to delete any GroupDatasetAssociations. This occurs if
# the user unchecked all boxes for a group
for group_dataset_assoc in dataset.dataset.groups:
@@ -761,9 +763,11 @@ class Admin( BaseController ):
dataset_actions.sort()
# Get the permitted_actions of each GroupDatasetAssociation to send to the form
gdas = []
# Refresh the dataset to ensure we have a valid set of DatasetGroupAssociations
# Refresh the Dataset to ensure we have a valid set of GroupDatasetAssociations
dataset.dataset.refresh()
for group_dataset_assoc in dataset.dataset.groups:
# Refresh the GroupDatasetAssociation to ensure we have a valid set of permitted_actions
group_dataset_assoc.refresh()
group = galaxy.model.Group.get( group_dataset_assoc.group_id )
gdas.append( ( group.id, group.name, group_dataset_assoc.permitted_actions ) )
if "dbkey" in dataset.datatype.metadata_spec and not dataset.metadata.dbkey:
+77 -4
View File
@@ -6,9 +6,12 @@ log = logging.getLogger( __name__ )
class Library( BaseController ):
@web.expose
def index( self, trans, library_id = None, import_ids = [], **kwd ):
#use for importing an entry into your history
def index( self, trans, library_id=None, import_ids=[], **kwd ):
# Need user to get associated Groups and Datasets
user = trans.get_user()
libraries = []
if import_ids:
# Used for importing a dataset into a user's history
if not isinstance( import_ids, list ):
import_ids = [import_ids]
history = trans.get_history()
@@ -19,5 +22,75 @@ class Library( BaseController ):
history.flush()
return trans.show_ok_message( "%i datasets have been imported into your history" % len( import_ids ), refresh_frames=['history'] )
elif library_id:
return trans.fill_template( '/library/library.mako', library=trans.app.model.Library.get( library_id ) )
return trans.fill_template( '/library/libraries.mako', libraries=trans.app.model.Library.select() )
# Since permitted_actions are kept with the GroupDatasetAssociation, each accessible Library will only
# display the subset of [ it's complete set of ] datasets that the user has permission to access. We
# pass group_ids so this can be handled in the template.
if not user:
group_ids = [ trans.app.model.Group.select_by( name='public' )[0].id ]
else:
group_ids = []
for user_group_assoc in user.groups:
group_ids.append( user_group_assoc.group_id )
library = trans.app.model.Library.get( library_id )
return trans.fill_template( '/library/library.mako', library=library, group_ids=group_ids )
if user:
# Only display libraries that contain datasets associated with the user's groups
group_ids = []
for user_group_assoc in user.groups:
group = trans.app.model.Group.get( user_group_assoc.group_id )
group_ids.append( group.id )
libs = trans.app.model.Library.select()
for library in libs:
user_can_access = False
# Check for public datasets in the Library's root folder
for library_folder_dataset_assoc in library.root_folder.datasets:
if user_can_access:
break
dataset = trans.app.model.Dataset.get( library_folder_dataset_assoc.dataset_id )
for group_dataset_assoc in dataset.groups:
if group_dataset_assoc.group_id in group_ids:
libraries.append( library )
user_can_access = True
break
for folder in library.root_folder.folders:
if user_can_access:
break
for library_folder_dataset_assoc in folder.datasets:
if user_can_access:
break
dataset = trans.app.model.Dataset.get( library_folder_dataset_assoc.dataset_id )
for group_dataset_assoc in dataset.groups:
if group_dataset_assoc.group_id in group_ids:
libraries.append( library )
user_can_access = True
break
else:
# Only display libraries that contain datasets associated with the public group
group_ids = [ trans.app.model.Group.select_by( name='public' )[0].id ]
libs = trans.app.model.Library.select()
for library in libs:
public_library = False
# Check for public datasets in the Library's root folder
for library_folder_dataset_assoc in library.root_folder.datasets:
if public_library:
break
dataset = trans.app.model.Dataset.get( library_folder_dataset_assoc.dataset_id )
for group_dataset_assoc in dataset.groups:
if group_dataset_assoc.group_id in group_ids:
libraries.append( library )
public_library = True
break
# Check for public datasets in the root folder's sub-folders
for folder in library.root_folder.folders:
if public_library:
break
for library_folder_dataset_assoc in folder.datasets:
if public_library:
break
dataset = trans.app.model.Dataset.get( library_folder_dataset_assoc.dataset_id )
for group_dataset_assoc in dataset.groups:
if group_dataset_assoc.group_id in group_ids:
libraries.append( library )
public_library = True
break
return trans.fill_template( '/library/libraries.mako', group_ids=group_ids, libraries=libraries )
+24 -21
View File
@@ -1,6 +1,7 @@
<%inherit file="/base.mako"/>
<%def name="title()">Edit Dataset Attributes</%def>
<%def name="datatype( dataset, datatypes )">
<select name="datatype">
## $datatypes.sort()
@@ -13,35 +14,37 @@
%endfor
</select>
</%def>
<%def name="group_dataset_permitted_actions( dataset_actions, gda )">
%for da in dataset_actions:
<% check = False %>
%for action in gda[2]:
%if action == da:
<%
check = True
break
%>
%endif
%endfor
%if check:
<input type="checkbox" name="actions" value="${gda[0]},${da}" checked/>
%else:
<input type="checkbox" name="actions" value="${gda[0]},${da}"/>
%endif
${da}<br/>
%endfor
</%def>
<div class="toolForm">
<div class="toolFormTitle">Group Associations</div>
<div class="toolFormBody">
<form name="edit_group_associations" action="${h.url_for( controller='admin', action='dataset' )}" method="post">
<input type="hidden" name="id" value="${dataset.id}">
%for gda in gdas:
<div class="form-row">
<label>Group:</label>${gda[1]}
</div>
<div class="form-row"><label>Group:</label>${gda[1]}</div>
<div class="form-row"><label>Permitted actions on dataset:</label></div>
<div class="form-row">
%for da in dataset_actions:
<% check = False %>
%for action in gda[2]:
%if action == da:
<%
check = True
break
%>
%endif
%endfor
%if check:
<input type="checkbox" name="actions" value="${gda[0]},${da}" checked/>
%else:
<input type="checkbox" name="actions" value="${gda[0]},${da}"/>
%endif
${da}<br/>
%endfor
<br/>
${group_dataset_permitted_actions( dataset_actions, gda )}
</div>
%endfor
<div class="form-row"><input type="submit" name="change_permitted_actions" value="Save"></div>
+3 -3
View File
@@ -1,12 +1,12 @@
<%inherit file="/base.mako"/>
<%def name="title()">View Libraries</%def>
<%def name="title()">Libraries You Can Access</%def>
<div class="toolForm">
<div class="toolFormTitle">View Library</div>
<div class="toolFormTitle">Libraries You Can Access</div>
<div class="toolFormBody">
%for library in libraries:
<div class="form-row">
<a href="${h.url_for( 'index', library_id = library.id )}">${library.name}</a>
<a href="${h.url_for( '/library/index', library_id=library.id )}">${library.name}</a>
</div>
%endfor
</div>
+28 -3
View File
@@ -3,17 +3,41 @@
<%def name="render_component( component )">
<%
if isinstance( component, trans.app.model.LibraryFolder ):
return render_folder( component )
render = False
# Check the folder's datasets to see what can be rendered
for library_folder_dataset_assoc in component.datasets:
if render:
break
dataset = trans.app.model.Dataset.get( library_folder_dataset_assoc.dataset_id )
for group_dataset_assoc in dataset.groups:
if group_dataset_assoc.group_id in group_ids:
render = True
break
# TODO: Do we need to upgrade sqlalchemy? The following shouldn't be necessary if the mappers work correctly.
# Check the folder's sub-folders to see what can be rendered
for library_folder in component.folders:
render_component( library_folder )
if render:
return render_folder( component )
elif isinstance( component, trans.app.model.LibraryFolderDatasetAssociation ):
return render_dataset( component )
render = False
dataset = trans.app.model.Dataset.get( component.dataset_id )
for group_dataset_assoc in dataset.groups:
if group_dataset_assoc.group_id in group_ids:
render = True
break
if render:
return render_dataset( component )
%>
</%def>
## Render the dataset `data` as history item, using `hid` as the displayed id
<%def name="render_dataset( data )">
<div>
<input type="checkbox" name="import_ids" value="${data.id}">${data.name}
<div>
</%def>
## Render a folder
<%def name="render_folder( this_folder )">
<div>
@@ -31,11 +55,12 @@
</blockquote>
</div>
</%def>
<%def name="title()">View Library: ${library.name}</%def>
<div class="toolForm">
<div class="toolFormTitle">Import from Library: ${library.name}</div>
<div class="toolFormBody">
<form name="view_library" action="${h.url_for( 'index' )}" method="post">
<form name="view_library" action="${h.url_for( '/library/index' )}" method="post">
${render_folder( library.root_folder )}
<div style="clear: both"></div>
<input type="submit" class="primary-button" name="import_dataset" value="Import Datasets">
+5 -9
View File
@@ -1,11 +1,7 @@
<?xml version="1.0"?>
<tool name="Access Libraries" id="library_access1">
<description>stored locally</description>
<inputs action="library/index" method="get">
<param name="bogus_param" type="hidden" value="needed" />
</inputs>
</tool>
<description>stored locally</description>
<inputs action="library/index" method="get">
<param name="bogus_param" type="hidden" value="needed" />
</inputs>
</tool>