Fix security problem with grids. Template should not be passed at call time, it must be passed at configure time.

This commit is contained in:
James Taylor
2009-08-23 12:28:36 -04:00
parent 886beeebe7
commit 975efff634
6 changed files with 209 additions and 9 deletions
+6 -4
View File
@@ -39,6 +39,7 @@ class HistoryListGrid( grids.Grid ):
# Grid definition
title = "Stored histories"
model_class = model.History
template='/history/grid.mako'
default_sort_key = "-create_time"
columns = [
grids.GridColumn( "Name", key="name",
@@ -86,6 +87,7 @@ class SharedHistoryListGrid( grids.Grid ):
return history.user.email
# Grid definition
title = "Histories shared with you by others"
template='/history/grid.mako'
model_class = model.History
default_sort_key = "-update_time"
columns = [
@@ -161,7 +163,7 @@ class HistoryController( BaseController ):
status, message = self._list_undelete( trans, histories )
trans.sa_session.flush()
# Render the list view
return self.stored_list_grid( trans, status=status, message=message, template='/history/grid.mako', **kwargs )
return self.stored_list_grid( trans, status=status, message=message, **kwargs )
def _list_delete( self, trans, histories ):
"""Delete histories"""
n_deleted = 0
@@ -240,14 +242,14 @@ class HistoryController( BaseController ):
if operation == "clone":
if not id:
message = "Select a history to clone"
return self.shared_list_grid( trans, status='error', message=message, template='/history/grid.mako', **kwargs )
return self.shared_list_grid( trans, status='error', message=message, **kwargs )
# When cloning shared histories, only copy active datasets
new_kwargs = { 'clone_choice' : 'active' }
return self.clone( trans, id, **new_kwargs )
elif operation == 'unshare':
if not id:
message = "Select a history to unshare"
return self.shared_list_grid( trans, status='error', message=message, template='/history/grid.mako', **kwargs )
return self.shared_list_grid( trans, status='error', message=message, **kwargs )
ids = util.listify( id )
histories = []
for history_id in ids:
@@ -261,7 +263,7 @@ class HistoryController( BaseController ):
message = "Unshared %d shared histories" % len( ids )
status = 'done'
# Render the list view
return self.shared_list_grid( trans, status=status, message=message, template='/history/grid.mako', **kwargs )
return self.shared_list_grid( trans, status=status, message=message, **kwargs )
@web.expose
def delete_current( self, trans ):
"""Delete just the active history -- this does not require a logged in user."""
+2 -1
View File
@@ -16,6 +16,7 @@ log = logging.getLogger( __name__ )
class RequestsListGrid( grids.Grid ):
title = "Sequencing Requests"
template = '/requests/grid.mako'
model_class = model.Request
default_sort_key = "-create_time"
show_filter = model.Request.states.UNSUBMITTED
@@ -103,7 +104,7 @@ class Requests( BaseController ):
self.request_grid.default_filter = dict(state=kwargs['show_filter'], deleted=False)
self.request_grid.show_filter = kwargs.get('show_filter', trans.app.model.Request.states.UNSUBMITTED)
# Render the list view
return self.request_grid( trans, template='/requests/grid.mako', **kwargs )
return self.request_grid( trans, **kwargs )
def __show_request(self, trans, id, add_sample=False):
try:
+2 -1
View File
@@ -14,6 +14,7 @@ log = logging.getLogger( __name__ )
class RequestsListGrid( grids.Grid ):
title = "Sequencing Requests"
template = "admin/requests/grid.mako"
model_class = model.Request
default_sort_key = "-create_time"
show_filter = model.Request.states.SUBMITTED
@@ -101,7 +102,7 @@ class Requests( BaseController ):
self.request_grid.default_filter = dict(state=kwargs['show_filter'], deleted=False)
self.request_grid.show_filter = kwargs.get('show_filter', trans.app.model.Request.states.SUBMITTED)
# Render the list view
return self.request_grid( trans, template='/admin/requests/grid.mako', **kwargs )
return self.request_grid( trans, **kwargs )
@web.expose
@web.require_admin
def edit(self, trans, **kwd):
+3 -3
View File
@@ -14,8 +14,9 @@ class Grid( object ):
title = ""
exposed = True
model_class = None
template = None
template = "grid.mako"
columns = []
operations = []
standard_filters = []
default_filter = None
default_sort_key = None
@@ -25,7 +26,6 @@ class Grid( object ):
def __call__( self, trans, **kwargs ):
status = kwargs.get( 'status', None )
message = kwargs.get( 'message', None )
template = kwargs.get( 'template', None )
session = trans.sa_session
# Build initial query
query = self.build_initial_query( session )
@@ -77,7 +77,7 @@ class Grid( object ):
else:
new_kwargs[ 'id' ] = trans.security.encode_id( id )
return url_for( **new_kwargs )
return trans.fill_template( template,
return trans.fill_template( self.template,
grid=self,
query=query,
sort_key=sort_key,
Regular → Executable
View File
+196
View File
@@ -0,0 +1,196 @@
<%inherit file="/base.mako"/>
<%def name="title()">${grid.title}</%def>
%if message:
<p>
<div class="${message_type}message transient-message">${message}</div>
<div style="clear: both"></div>
</p>
%endif
<%def name="javascripts()">
${parent.javascripts()}
<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()">
<link href="${h.url_for('/static/style/base.css')}" rel="stylesheet" type="text/css" />
<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>
<div class="grid-header">
<h2>${grid.title}</h2>
%if grid.standard_filters:
<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
%endif
</div>
<form 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"><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 ):
<a class="action-button" href="${url( operation=operation.label, id=item.id )}">${operation.label}</a>
%endif
%endfor
</div>
</td>
</tr>
%endfor
</tbody>
<tfoot>
<tr>
<td></td>
<td colspan="100">
For <span class="grid-selected-count"></span> selected items:
%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>
</table>
</form>