mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-21 13:50:20 +08:00
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:
@@ -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."""
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
@@ -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 = "↓"
|
||||
else:
|
||||
href = url( sort=( column.key ) )
|
||||
extra = "↑"
|
||||
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>▼</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>
|
||||
Reference in New Issue
Block a user