1 | import tarfile |
---|
2 | from galaxy.web.base.controller import * |
---|
3 | from galaxy.webapps.community import model |
---|
4 | from galaxy.model.orm import * |
---|
5 | from galaxy.web.framework.helpers import time_ago, iff, grids |
---|
6 | from galaxy.web.form_builder import SelectField |
---|
7 | from galaxy.model.item_attrs import UsesItemRatings |
---|
8 | import logging |
---|
9 | log = logging.getLogger( __name__ ) |
---|
10 | |
---|
11 | # States for passing messages |
---|
12 | SUCCESS, INFO, WARNING, ERROR = "done", "info", "warning", "error" |
---|
13 | |
---|
14 | class ItemRatings( UsesItemRatings ): |
---|
15 | """Overrides rate_item method since we also allow for comments""" |
---|
16 | def rate_item( self, trans, user, item, rating, comment='' ): |
---|
17 | """ Rate an item. Return type is <item_class>RatingAssociation. """ |
---|
18 | item_rating = self.get_user_item_rating( trans.sa_session, user, item, webapp_model=trans.model ) |
---|
19 | if not item_rating: |
---|
20 | # User has not yet rated item; create rating. |
---|
21 | item_rating_assoc_class = self._get_item_rating_assoc_class( item, webapp_model=trans.model ) |
---|
22 | item_rating = item_rating_assoc_class() |
---|
23 | item_rating.user = trans.user |
---|
24 | item_rating.set_item( item ) |
---|
25 | item_rating.rating = rating |
---|
26 | item_rating.comment = comment |
---|
27 | trans.sa_session.add( item_rating ) |
---|
28 | trans.sa_session.flush() |
---|
29 | elif item_rating.rating != rating or item_rating.comment != comment: |
---|
30 | # User has previously rated item; update rating. |
---|
31 | item_rating.rating = rating |
---|
32 | item_rating.comment = comment |
---|
33 | trans.sa_session.flush() |
---|
34 | return item_rating |
---|
35 | |
---|
36 | class ToolListGrid( grids.Grid ): |
---|
37 | class NameColumn( grids.TextColumn ): |
---|
38 | def get_value( self, trans, grid, tool ): |
---|
39 | return tool.name |
---|
40 | class TypeColumn( grids.BooleanColumn ): |
---|
41 | def get_value( self, trans, grid, tool ): |
---|
42 | if tool.is_suite: |
---|
43 | return 'Suite' |
---|
44 | return 'Tool' |
---|
45 | class VersionColumn( grids.TextColumn ): |
---|
46 | def get_value( self, trans, grid, tool ): |
---|
47 | return tool.version |
---|
48 | class DescriptionColumn( grids.TextColumn ): |
---|
49 | def get_value( self, trans, grid, tool ): |
---|
50 | return tool.description |
---|
51 | class CategoryColumn( grids.TextColumn ): |
---|
52 | def get_value( self, trans, grid, tool ): |
---|
53 | rval = '<ul>' |
---|
54 | if tool.categories: |
---|
55 | for tca in tool.categories: |
---|
56 | rval += '<li><a href="browse_tools?operation=tools_by_category&id=%s&webapp=community">%s</a></li>' \ |
---|
57 | % ( trans.security.encode_id( tca.category.id ), tca.category.name ) |
---|
58 | else: |
---|
59 | rval += '<li>not set</li>' |
---|
60 | rval += '</ul>' |
---|
61 | return rval |
---|
62 | class ToolCategoryColumn( grids.GridColumn ): |
---|
63 | def filter( self, trans, user, query, column_filter ): |
---|
64 | """Modify query to filter by category.""" |
---|
65 | if column_filter == "All": |
---|
66 | pass |
---|
67 | return query.filter( model.Category.name == column_filter ) |
---|
68 | class UserColumn( grids.TextColumn ): |
---|
69 | def get_value( self, trans, grid, tool ): |
---|
70 | if tool.user: |
---|
71 | return tool.user.username |
---|
72 | return 'no user' |
---|
73 | class EmailColumn( grids.TextColumn ): |
---|
74 | def filter( self, trans, user, query, column_filter ): |
---|
75 | if column_filter == 'All': |
---|
76 | return query |
---|
77 | return query.filter( and_( model.Tool.table.c.user_id == model.User.table.c.id, |
---|
78 | model.User.table.c.email == column_filter ) ) |
---|
79 | # Grid definition |
---|
80 | title = "Tools" |
---|
81 | model_class = model.Tool |
---|
82 | template='/webapps/community/tool/grid.mako' |
---|
83 | default_sort_key = "name" |
---|
84 | columns = [ |
---|
85 | NameColumn( "Name", |
---|
86 | key="Tool.name", |
---|
87 | link=( lambda item: dict( operation="view_tool", id=item.id, webapp="community" ) ), |
---|
88 | attach_popup=False |
---|
89 | ), |
---|
90 | TypeColumn( "Type", |
---|
91 | key="suite", |
---|
92 | attach_popup=False ), |
---|
93 | VersionColumn( "Version", |
---|
94 | key="version", |
---|
95 | attach_popup=False, |
---|
96 | filterable="advanced" ), |
---|
97 | DescriptionColumn( "Description", |
---|
98 | key="description", |
---|
99 | attach_popup=False |
---|
100 | ), |
---|
101 | CategoryColumn( "Category", |
---|
102 | model_class=model.Category, |
---|
103 | key="Category.name", |
---|
104 | attach_popup=False ), |
---|
105 | UserColumn( "Uploaded By", |
---|
106 | model_class=model.User, |
---|
107 | link=( lambda item: dict( operation="tools_by_user", id=item.id, webapp="community" ) ), |
---|
108 | attach_popup=False, |
---|
109 | key="username" ), |
---|
110 | grids.CommunityRatingColumn( "Average Rating", |
---|
111 | key="rating" ), |
---|
112 | # Columns that are valid for filtering but are not visible. |
---|
113 | EmailColumn( "Email", |
---|
114 | model_class=model.User, |
---|
115 | key="email", |
---|
116 | visible=False ), |
---|
117 | ToolCategoryColumn( "Category", |
---|
118 | model_class=model.Category, |
---|
119 | key="Category.name", |
---|
120 | visible=False ) |
---|
121 | ] |
---|
122 | columns.append( grids.MulticolFilterColumn( "Search", |
---|
123 | cols_to_filter=[ columns[0], columns[1], columns[2] ], |
---|
124 | key="free-text-search", |
---|
125 | visible=False, |
---|
126 | filterable="standard" ) ) |
---|
127 | operations = [] |
---|
128 | standard_filters = [] |
---|
129 | default_filter = {} |
---|
130 | num_rows_per_page = 50 |
---|
131 | preserve_state = False |
---|
132 | use_paging = True |
---|
133 | def build_initial_query( self, trans, **kwd ): |
---|
134 | return trans.sa_session.query( self.model_class ) \ |
---|
135 | .join( model.User.table ) \ |
---|
136 | .join( model.ToolEventAssociation.table ) \ |
---|
137 | .join( model.Event.table ) \ |
---|
138 | .outerjoin( model.ToolCategoryAssociation.table ) \ |
---|
139 | .outerjoin( model.Category.table ) |
---|
140 | |
---|
141 | class CategoryListGrid( grids.Grid ): |
---|
142 | class NameColumn( grids.TextColumn ): |
---|
143 | def get_value( self, trans, grid, category ): |
---|
144 | return category.name |
---|
145 | class DescriptionColumn( grids.TextColumn ): |
---|
146 | def get_value( self, trans, grid, category ): |
---|
147 | return category.description |
---|
148 | class ToolsColumn( grids.TextColumn ): |
---|
149 | def get_value( self, trans, grid, category ): |
---|
150 | if category.tools: |
---|
151 | viewable_tools = 0 |
---|
152 | for tca in category.tools: |
---|
153 | viewable_tools += 1 |
---|
154 | return viewable_tools |
---|
155 | return 0 |
---|
156 | |
---|
157 | # Grid definition |
---|
158 | webapp = "community" |
---|
159 | title = "Categories" |
---|
160 | model_class = model.Category |
---|
161 | template='/webapps/community/category/grid.mako' |
---|
162 | default_sort_key = "name" |
---|
163 | columns = [ |
---|
164 | NameColumn( "Name", |
---|
165 | key="name", |
---|
166 | link=( lambda item: dict( operation="tools_by_category", id=item.id, webapp="community" ) ), |
---|
167 | attach_popup=False, |
---|
168 | filterable="advanced" |
---|
169 | ), |
---|
170 | DescriptionColumn( "Description", |
---|
171 | key="description", |
---|
172 | attach_popup=False, |
---|
173 | filterable="advanced" |
---|
174 | ), |
---|
175 | # Columns that are valid for filtering but are not visible. |
---|
176 | grids.DeletedColumn( "Deleted", |
---|
177 | key="deleted", |
---|
178 | visible=False, |
---|
179 | filterable="advanced" ), |
---|
180 | ToolsColumn( "Tools", |
---|
181 | model_class=model.Tool, |
---|
182 | attach_popup=False ) |
---|
183 | ] |
---|
184 | columns.append( grids.MulticolFilterColumn( "Search", |
---|
185 | cols_to_filter=[ columns[0], columns[1] ], |
---|
186 | key="free-text-search", |
---|
187 | visible=False, |
---|
188 | filterable="standard" ) ) |
---|
189 | |
---|
190 | # Override these |
---|
191 | global_actions = [] |
---|
192 | operations = [] |
---|
193 | standard_filters = [] |
---|
194 | num_rows_per_page = 50 |
---|
195 | preserve_state = False |
---|
196 | use_paging = True |
---|
197 | |
---|
198 | class CommonController( BaseController, ItemRatings ): |
---|
199 | @web.expose |
---|
200 | def edit_tool( self, trans, cntrller, **kwd ): |
---|
201 | params = util.Params( kwd ) |
---|
202 | message = util.restore_text( params.get( 'message', '' ) ) |
---|
203 | status = params.get( 'status', 'done' ) |
---|
204 | id = params.get( 'id', None ) |
---|
205 | if not id: |
---|
206 | return trans.response.send_redirect( web.url_for( controller=cntrller, |
---|
207 | action='browse_tools', |
---|
208 | message='Select a tool to edit', |
---|
209 | status='error' ) ) |
---|
210 | tool = get_tool( trans, id ) |
---|
211 | can_edit = trans.app.security_agent.can_edit( trans.user, trans.user_is_admin(), cntrller, tool ) |
---|
212 | if not can_edit: |
---|
213 | return trans.response.send_redirect( web.url_for( controller=cntrller, |
---|
214 | action='browse_tools', |
---|
215 | message='You are not allowed to edit this tool', |
---|
216 | status='error' ) ) |
---|
217 | if params.get( 'edit_tool_button', False ): |
---|
218 | if params.get( 'in_categories', False ): |
---|
219 | in_categories = [ trans.sa_session.query( trans.app.model.Category ).get( x ) for x in util.listify( params.in_categories ) ] |
---|
220 | trans.app.security_agent.set_entity_category_associations( tools=[ tool ], categories=in_categories ) |
---|
221 | else: |
---|
222 | # There must not be any categories associated with the tool |
---|
223 | trans.app.security_agent.set_entity_category_associations( tools=[ tool ], categories=[] ) |
---|
224 | user_description = util.restore_text( params.get( 'user_description', '' ) ) |
---|
225 | if user_description: |
---|
226 | tool.user_description = user_description |
---|
227 | else: |
---|
228 | tool.user_description = '' |
---|
229 | trans.sa_session.add( tool ) |
---|
230 | trans.sa_session.flush() |
---|
231 | message = "Tool '%s' description and category associations have been saved" % tool.name |
---|
232 | return trans.response.send_redirect( web.url_for( controller='common', |
---|
233 | action='edit_tool', |
---|
234 | cntrller=cntrller, |
---|
235 | id=id, |
---|
236 | message=message, |
---|
237 | status='done' ) ) |
---|
238 | elif params.get( 'approval_button', False ): |
---|
239 | user_description = util.restore_text( params.get( 'user_description', '' ) ) |
---|
240 | if user_description: |
---|
241 | tool.user_description = user_description |
---|
242 | if params.get( 'in_categories', False ): |
---|
243 | in_categories = [ trans.sa_session.query( trans.app.model.Category ).get( x ) for x in util.listify( params.in_categories ) ] |
---|
244 | trans.app.security_agent.set_entity_category_associations( tools=[ tool ], categories=in_categories ) |
---|
245 | else: |
---|
246 | # There must not be any categories associated with the tool |
---|
247 | trans.app.security_agent.set_entity_category_associations( tools=[ tool ], categories=[] ) |
---|
248 | trans.sa_session.add( tool ) |
---|
249 | trans.sa_session.flush() |
---|
250 | # Move the state from NEW to WAITING |
---|
251 | event = trans.app.model.Event( state=trans.app.model.Tool.states.WAITING ) |
---|
252 | tea = trans.app.model.ToolEventAssociation( tool, event ) |
---|
253 | trans.sa_session.add_all( ( event, tea ) ) |
---|
254 | trans.sa_session.flush() |
---|
255 | message = "Tool '%s' has been submitted for approval and can no longer be modified" % ( tool.name ) |
---|
256 | return trans.response.send_redirect( web.url_for( controller='common', |
---|
257 | action='view_tool', |
---|
258 | cntrller=cntrller, |
---|
259 | id=id, |
---|
260 | message=message, |
---|
261 | status='done' ) ) |
---|
262 | else: |
---|
263 | # The user_description field is required when submitting for approval |
---|
264 | message = 'A user description is required prior to approval.' |
---|
265 | status = 'error' |
---|
266 | in_categories = [] |
---|
267 | out_categories = [] |
---|
268 | for category in get_categories( trans ): |
---|
269 | if category in [ x.category for x in tool.categories ]: |
---|
270 | in_categories.append( ( category.id, category.name ) ) |
---|
271 | else: |
---|
272 | out_categories.append( ( category.id, category.name ) ) |
---|
273 | if tool.is_rejected: |
---|
274 | # Include the comments regarding the reason for rejection |
---|
275 | reason_for_rejection = tool.latest_event.comment |
---|
276 | else: |
---|
277 | reason_for_rejection = '' |
---|
278 | can_approve_or_reject = trans.app.security_agent.can_approve_or_reject( trans.user, trans.user_is_admin(), cntrller, tool ) |
---|
279 | can_delete = trans.app.security_agent.can_delete( trans.user, trans.user_is_admin(), cntrller, tool ) |
---|
280 | can_download = trans.app.security_agent.can_download( trans.user, trans.user_is_admin(), cntrller, tool ) |
---|
281 | can_purge = trans.app.security_agent.can_purge( trans.user, trans.user_is_admin(), cntrller ) |
---|
282 | can_upload_new_version = trans.app.security_agent.can_upload_new_version( trans.user, tool ) |
---|
283 | can_view = trans.app.security_agent.can_view( trans.user, trans.user_is_admin(), cntrller, tool ) |
---|
284 | return trans.fill_template( '/webapps/community/tool/edit_tool.mako', |
---|
285 | cntrller=cntrller, |
---|
286 | tool=tool, |
---|
287 | id=id, |
---|
288 | in_categories=in_categories, |
---|
289 | out_categories=out_categories, |
---|
290 | can_approve_or_reject=can_approve_or_reject, |
---|
291 | can_delete=can_delete, |
---|
292 | can_download=can_download, |
---|
293 | can_edit=can_edit, |
---|
294 | can_purge=can_purge, |
---|
295 | can_upload_new_version=can_upload_new_version, |
---|
296 | can_view=can_view, |
---|
297 | reason_for_rejection=reason_for_rejection, |
---|
298 | message=message, |
---|
299 | status=status ) |
---|
300 | @web.expose |
---|
301 | def view_tool( self, trans, cntrller, **kwd ): |
---|
302 | params = util.Params( kwd ) |
---|
303 | message = util.restore_text( params.get( 'message', '' ) ) |
---|
304 | status = params.get( 'status', 'done' ) |
---|
305 | id = params.get( 'id', None ) |
---|
306 | if not id: |
---|
307 | return trans.response.send_redirect( web.url_for( controller=cntrller, |
---|
308 | action='browse_tools', |
---|
309 | message='Select a tool to view', |
---|
310 | status='error' ) ) |
---|
311 | tool = get_tool( trans, id ) |
---|
312 | can_view = trans.app.security_agent.can_view( trans.user, trans.user_is_admin(), cntrller, tool ) |
---|
313 | if not can_view: |
---|
314 | return trans.response.send_redirect( web.url_for( controller=cntrller, |
---|
315 | action='browse_tools', |
---|
316 | message='You are not allowed to view this tool', |
---|
317 | status='error' ) ) |
---|
318 | avg_rating, num_ratings = self.get_ave_item_rating_data( trans.sa_session, tool, webapp_model=trans.model ) |
---|
319 | can_approve_or_reject = trans.app.security_agent.can_approve_or_reject( trans.user, trans.user_is_admin(), cntrller, tool ) |
---|
320 | can_delete = trans.app.security_agent.can_delete( trans.user, trans.user_is_admin(), cntrller, tool ) |
---|
321 | can_download = trans.app.security_agent.can_download( trans.user, trans.user_is_admin(), cntrller, tool ) |
---|
322 | can_edit = trans.app.security_agent.can_edit( trans.user, trans.user_is_admin(), cntrller, tool ) |
---|
323 | can_purge = trans.app.security_agent.can_purge( trans.user, trans.user_is_admin(), cntrller ) |
---|
324 | can_rate = trans.app.security_agent.can_rate( trans.user, trans.user_is_admin(), cntrller, tool ) |
---|
325 | can_upload_new_version = trans.app.security_agent.can_upload_new_version( trans.user, tool ) |
---|
326 | categories = [ tca.category for tca in tool.categories ] |
---|
327 | display_reviews = util.string_as_bool( params.get( 'display_reviews', False ) ) |
---|
328 | tool_file_contents = tarfile.open( tool.file_name, 'r' ).getnames() |
---|
329 | tra = self.get_user_item_rating( trans.sa_session, trans.user, tool, webapp_model=trans.model ) |
---|
330 | visible_versions = trans.app.security_agent.get_visible_versions( trans.user, trans.user_is_admin(), cntrller, tool ) |
---|
331 | if tool.is_rejected: |
---|
332 | # Include the comments regarding the reason for rejection |
---|
333 | reason_for_rejection = tool.latest_event.comment |
---|
334 | else: |
---|
335 | reason_for_rejection = '' |
---|
336 | return trans.fill_template( '/webapps/community/tool/view_tool.mako', |
---|
337 | avg_rating=avg_rating, |
---|
338 | categories=categories, |
---|
339 | can_approve_or_reject=can_approve_or_reject, |
---|
340 | can_delete=can_delete, |
---|
341 | can_download=can_download, |
---|
342 | can_edit=can_edit, |
---|
343 | can_purge=can_purge, |
---|
344 | can_rate=can_rate, |
---|
345 | can_upload_new_version=can_upload_new_version, |
---|
346 | can_view=can_view, |
---|
347 | cntrller=cntrller, |
---|
348 | display_reviews=display_reviews, |
---|
349 | num_ratings=num_ratings, |
---|
350 | reason_for_rejection=reason_for_rejection, |
---|
351 | tool=tool, |
---|
352 | tool_file_contents=tool_file_contents, |
---|
353 | tra=tra, |
---|
354 | visible_versions=visible_versions, |
---|
355 | message=message, |
---|
356 | status=status ) |
---|
357 | @web.expose |
---|
358 | def delete_tool( self, trans, cntrller, **kwd ): |
---|
359 | params = util.Params( kwd ) |
---|
360 | message = util.restore_text( params.get( 'message', '' ) ) |
---|
361 | status = params.get( 'status', 'done' ) |
---|
362 | id = params.get( 'id', None ) |
---|
363 | if not id: |
---|
364 | message='Select a tool to delete' |
---|
365 | status='error' |
---|
366 | else: |
---|
367 | tool = get_tool( trans, id ) |
---|
368 | if not trans.app.security_agent.can_delete( trans.user, trans.user_is_admin(), cntrller, tool ): |
---|
369 | return trans.response.send_redirect( web.url_for( controller=cntrller, |
---|
370 | action='browse_tools', |
---|
371 | message='You are not allowed to delete this tool', |
---|
372 | status='error' ) ) |
---|
373 | # Create a new event |
---|
374 | event = trans.model.Event( state=trans.model.Tool.states.DELETED ) |
---|
375 | # Flush so we can get an event id |
---|
376 | trans.sa_session.add( event ) |
---|
377 | trans.sa_session.flush() |
---|
378 | # Associate the tool with the event |
---|
379 | tea = trans.model.ToolEventAssociation( tool=tool, event=event ) |
---|
380 | # Delete the tool, keeping state for categories, events and versions |
---|
381 | tool.deleted = True |
---|
382 | trans.sa_session.add_all( ( tool, tea ) ) |
---|
383 | trans.sa_session.flush() |
---|
384 | # TODO: What if the tool has versions, should they all be deleted? |
---|
385 | message = "Tool '%s' has been marked deleted" % tool.name |
---|
386 | status = 'done' |
---|
387 | return trans.response.send_redirect( web.url_for( controller=cntrller, |
---|
388 | action='browse_tools', |
---|
389 | message=message, |
---|
390 | status=status ) ) |
---|
391 | @web.expose |
---|
392 | def download_tool( self, trans, cntrller, **kwd ): |
---|
393 | params = util.Params( kwd ) |
---|
394 | id = params.get( 'id', None ) |
---|
395 | if not id: |
---|
396 | return trans.response.send_redirect( web.url_for( controller='tool', |
---|
397 | action='browse_tools', |
---|
398 | message='Select a tool to download', |
---|
399 | status='error' ) ) |
---|
400 | tool = get_tool( trans, id ) |
---|
401 | if not trans.app.security_agent.can_download( trans.user, trans.user_is_admin(), cntrller, tool ): |
---|
402 | return trans.response.send_redirect( web.url_for( controller=cntrller, |
---|
403 | action='browse_tools', |
---|
404 | message='You are not allowed to download this tool', |
---|
405 | status='error' ) ) |
---|
406 | trans.response.set_content_type( tool.mimetype ) |
---|
407 | trans.response.headers['Content-Length'] = int( os.stat( tool.file_name ).st_size ) |
---|
408 | trans.response.headers['Content-Disposition'] = 'attachment; filename=%s' % tool.download_file_name |
---|
409 | return open( tool.file_name ) |
---|
410 | @web.expose |
---|
411 | def upload_new_tool_version( self, trans, cntrller, **kwd ): |
---|
412 | params = util.Params( kwd ) |
---|
413 | message = util.restore_text( params.get( 'message', '' ) ) |
---|
414 | status = params.get( 'status', 'done' ) |
---|
415 | id = params.get( 'id', None ) |
---|
416 | if not id: |
---|
417 | return trans.response.send_redirect( web.url_for( controller=cntrller, |
---|
418 | action='browse_tools', |
---|
419 | message='Select a tool to upload a new version', |
---|
420 | status='error' ) ) |
---|
421 | tool = get_tool( trans, id ) |
---|
422 | if not trans.app.security_agent.can_upload_new_version( trans.user, tool ): |
---|
423 | return trans.response.send_redirect( web.url_for( controller=cntrller, |
---|
424 | action='browse_tools', |
---|
425 | message='You are not allowed to upload a new version of this tool', |
---|
426 | status='error' ) ) |
---|
427 | return trans.response.send_redirect( web.url_for( controller='upload', |
---|
428 | action='upload', |
---|
429 | message=message, |
---|
430 | status=status, |
---|
431 | replace_id=id ) ) |
---|
432 | @web.expose |
---|
433 | @web.require_login( "view tool history" ) |
---|
434 | def view_tool_history( self, trans, cntrller, **kwd ): |
---|
435 | params = util.Params( kwd ) |
---|
436 | message = util.restore_text( params.get( 'message', '' ) ) |
---|
437 | status = params.get( 'status', 'done' ) |
---|
438 | id = params.get( 'id', None ) |
---|
439 | if not id: |
---|
440 | return trans.response.send_redirect( web.url_for( controller=cntrller, |
---|
441 | action='browse_tools', |
---|
442 | message='Select a tool to view its history', |
---|
443 | status='error' ) ) |
---|
444 | tool = get_tool( trans, id ) |
---|
445 | can_view = trans.app.security_agent.can_view( trans.user, trans.user_is_admin(), cntrller, tool ) |
---|
446 | if not can_view: |
---|
447 | return trans.response.send_redirect( web.url_for( controller=cntrller, |
---|
448 | action='browse_tools', |
---|
449 | message="You are not allowed to view this tool's history", |
---|
450 | status='error' ) ) |
---|
451 | can_approve_or_reject = trans.app.security_agent.can_approve_or_reject( trans.user, trans.user_is_admin(), cntrller, tool ) |
---|
452 | can_edit = trans.app.security_agent.can_edit( trans.user, trans.user_is_admin(), cntrller, tool ) |
---|
453 | can_delete = trans.app.security_agent.can_delete( trans.user, trans.user_is_admin(), cntrller, tool ) |
---|
454 | can_download = trans.app.security_agent.can_download( trans.user, trans.user_is_admin(), cntrller, tool ) |
---|
455 | events = [ tea.event for tea in tool.events ] |
---|
456 | events = [ ( event.state, time_ago( event.update_time ), event.comment ) for event in events ] |
---|
457 | return trans.fill_template( '/webapps/community/common/view_tool_history.mako', |
---|
458 | cntrller=cntrller, |
---|
459 | events=events, |
---|
460 | tool=tool, |
---|
461 | can_approve_or_reject=can_approve_or_reject, |
---|
462 | can_edit=can_edit, |
---|
463 | can_delete=can_delete, |
---|
464 | can_download=can_download, |
---|
465 | can_view=can_view, |
---|
466 | message=message, |
---|
467 | status=status ) |
---|
468 | @web.expose |
---|
469 | @web.require_login( "rate tools" ) |
---|
470 | def rate_tool( self, trans, cntrller, **kwd ): |
---|
471 | """ Rate a tool and return updated rating data. """ |
---|
472 | params = util.Params( kwd ) |
---|
473 | message = util.restore_text( params.get( 'message', '' ) ) |
---|
474 | status = params.get( 'status', 'done' ) |
---|
475 | id = params.get( 'id', None ) |
---|
476 | if not id: |
---|
477 | return trans.response.send_redirect( web.url_for( controller=cntrller, |
---|
478 | action='browse_tools', |
---|
479 | message='Select a tool to rate', |
---|
480 | status='error' ) ) |
---|
481 | tool = get_tool( trans, id ) |
---|
482 | can_rate = trans.app.security_agent.can_rate( trans.user, trans.user_is_admin(), cntrller, tool ) |
---|
483 | if not can_rate: |
---|
484 | return trans.response.send_redirect( web.url_for( controller=cntrller, |
---|
485 | action='browse_tools', |
---|
486 | message="You are not allowed to rate this tool", |
---|
487 | status='error' ) ) |
---|
488 | if params.get( 'rate_button', False ): |
---|
489 | rating = int( params.get( 'rating', '0' ) ) |
---|
490 | comment = util.restore_text( params.get( 'comment', '' ) ) |
---|
491 | rating = self.rate_item( trans, trans.user, tool, rating, comment ) |
---|
492 | avg_rating, num_ratings = self.get_ave_item_rating_data( trans.sa_session, tool, webapp_model=trans.model ) |
---|
493 | can_approve_or_reject = trans.app.security_agent.can_approve_or_reject( trans.user, trans.user_is_admin(), cntrller, tool ) |
---|
494 | can_edit = trans.app.security_agent.can_edit( trans.user, trans.user_is_admin(), cntrller, tool ) |
---|
495 | can_delete = trans.app.security_agent.can_delete( trans.user, trans.user_is_admin(), cntrller, tool ) |
---|
496 | can_download = trans.app.security_agent.can_download( trans.user, trans.user_is_admin(), cntrller, tool ) |
---|
497 | display_reviews = util.string_as_bool( params.get( 'display_reviews', False ) ) |
---|
498 | tra = self.get_user_item_rating( trans.sa_session, trans.user, tool, webapp_model=trans.model ) |
---|
499 | return trans.fill_template( '/webapps/community/common/rate_tool.mako', |
---|
500 | cntrller=cntrller, |
---|
501 | tool=tool, |
---|
502 | avg_rating=avg_rating, |
---|
503 | can_approve_or_reject=can_approve_or_reject, |
---|
504 | can_edit=can_edit, |
---|
505 | can_delete=can_delete, |
---|
506 | can_download=can_download, |
---|
507 | can_rate=can_rate, |
---|
508 | display_reviews=display_reviews, |
---|
509 | num_ratings=num_ratings, |
---|
510 | tra=tra, |
---|
511 | message=message, |
---|
512 | status=status ) |
---|
513 | |
---|
514 | ## ---- Utility methods ------------------------------------------------------- |
---|
515 | |
---|
516 | def get_versions( item ): |
---|
517 | """Get all versions of item""" |
---|
518 | versions = [ item ] |
---|
519 | this_item = item |
---|
520 | while item.newer_version: |
---|
521 | versions.insert( 0, item.newer_version ) |
---|
522 | item = item.newer_version |
---|
523 | item = this_item |
---|
524 | while item.older_version: |
---|
525 | versions.append( item.older_version[ 0 ] ) |
---|
526 | item = item.older_version[ 0 ] |
---|
527 | return versions |
---|
528 | def get_categories( trans ): |
---|
529 | """Get all categories from the database""" |
---|
530 | return trans.sa_session.query( trans.model.Category ) \ |
---|
531 | .filter( trans.model.Category.table.c.deleted==False ) \ |
---|
532 | .order_by( trans.model.Category.table.c.name ).all() |
---|
533 | def get_category( trans, id ): |
---|
534 | """Get a category from the database""" |
---|
535 | return trans.sa_session.query( trans.model.Category ).get( trans.security.decode_id( id ) ) |
---|
536 | def get_tool( trans, id ): |
---|
537 | """Get a tool from the database""" |
---|
538 | return trans.sa_session.query( trans.model.Tool ).get( trans.security.decode_id( id ) ) |
---|
539 | def get_latest_versions_of_tools( trans ): |
---|
540 | """Get only the latest version of each tool from the database""" |
---|
541 | return trans.sa_session.query( trans.model.Tool ) \ |
---|
542 | .filter( trans.model.Tool.newer_version_id == None ) \ |
---|
543 | .order_by( trans.model.Tool.name ) |
---|
544 | def get_approved_tools( trans ): |
---|
545 | """Get the tools from the database whose state is APPROVED""" |
---|
546 | approved_tools = [] |
---|
547 | for tool in get_latest_versions_of_tools( trans ): |
---|
548 | if tool.state == trans.model.Tool.states.APPROVED: |
---|
549 | approved_tools.append( tool ) |
---|
550 | return approved_tools |
---|
551 | def get_event( trans, id ): |
---|
552 | """Get an event from the databse""" |
---|
553 | return trans.sa_session.query( trans.model.Event ).get( trans.security.decode_id( id ) ) |
---|
554 | def get_user( trans, id ): |
---|
555 | """Get a user from the database""" |
---|
556 | return trans.sa_session.query( trans.model.User ).get( trans.security.decode_id( id ) ) |
---|