Ticket #1396: TicketClosePermissions-r1496.diff
| File TicketClosePermissions-r1496.diff, 10.4 KB (added by ludde, 4 years ago) |
|---|
-
trac/perm.py
24 24 'TIMELINE_VIEW', 'SEARCH_VIEW', 'CONFIG_VIEW', 'LOG_VIEW', 'FILE_VIEW', 25 25 'CHANGESET_VIEW', 'BROWSER_VIEW', 'ROADMAP_VIEW', 26 26 27 'TICKET_VIEW', 'TICKET_CREATE', 'TICKET_MODIFY', 27 'TICKET_VIEW', 'TICKET_CREATE', 'TICKET_CHGPROP', 'TICKET_RESOLVE', 28 'TICKET_APPEND','TICKET_ATTACH', 28 29 29 30 'REPORT_VIEW', 'REPORT_SQL_VIEW', 'REPORT_CREATE', 'REPORT_MODIFY', 30 31 'REPORT_DELETE', … … 40 41 'TIMELINE_VIEW', 'SEARCH_VIEW', 'CONFIG_VIEW', 'LOG_VIEW', 41 42 'FILE_VIEW', 'CHANGESET_VIEW', 'BROWSER_VIEW'], 42 43 'TICKET_ADMIN': ['TICKET_VIEW', 'TICKET_CREATE', 'TICKET_MODIFY'], 44 'TICKET_MODIFY': ['TICKET_CHGPROP', 'TICKET_RESOLVE', 'TICKET_ATTACH'], 43 45 'REPORT_ADMIN': ['REPORT_VIEW', 'REPORT_SQL_VIEW', 'REPORT_CREATE', 44 46 'REPORT_MODIFY', 'REPORT_DELETE'], 45 47 'WIKI_ADMIN': ['WIKI_VIEW', 'WIKI_CREATE', 'WIKI_MODIFY', 'WIKI_DELETE'], -
trac/Ticket.py
366 366 367 367 req.display('newticket.cs') 368 368 369 def get_ticket_actions(ticket, prm): 370 """ Returns the actions that can be performed on the ticket""" 371 actions = { 372 'new': ['leave', 'resolve', 'reassign', 'accept'], 373 'assigned': ['leave', 'resolve', 'reassign' ], 374 'reopened': ['leave', 'resolve', 'reassign' ], 375 'closed': ['leave', 'reopen'] 376 } 377 permissions = { 378 'resolve': perm.TICKET_RESOLVE, 379 'reassign': perm.TICKET_CHGPROP, 380 'accept': perm.TICKET_CHGPROP, 381 'reopen': perm.TICKET_CREATE 382 } 383 def has_perm(p): 384 n = permissions.get(p, None) 385 return not n or prm.has_permission(n) 386 return filter(has_perm, actions.get(ticket['status'], ['leave'])) 369 387 370 388 class TicketModule (Module): 371 389 372 390 def save_changes(self, req, id): 373 self.perm.assert_permission (perm.TICKET_MODIFY) 374 ticket = Ticket(self.db, id) 391 if self.perm.has_permission(perm.TICKET_CHGPROP): 392 # TICKET_CHGPROP gives permission to edit the ticket 393 if not req.args.get('summary'): 394 raise util.TracError('Tickets must contain Summary.') 375 395 376 if not req.args.get('summary'): 377 raise util.TracError('Tickets must contain Summary.') 396 ticket = Ticket(self.db, id) 397 if req.args.has_key('description'): 398 self.perm.assert_permission (perm.TICKET_ADMIN) 378 399 379 if req.args.has_key('description'):380 self.perm.assert_permission (perm.TICKET_ADMIN)400 if req.args.has_key('reporter'): 401 self.perm.assert_permission (perm.TICKET_ADMIN) 381 402 382 if req.args.has_key('reporter'): 383 self.perm.assert_permission (perm.TICKET_ADMIN) 403 ticket.populate(req.args) 384 404 405 elif self.perm.has_permission(perm.TICKET_APPEND): 406 # Allow appending a comment to the ticket only 407 ticket = Ticket(self.db, id) 408 else: 409 raise perm.PermissionError(perm.TICKET_CHGPROP) 410 411 # Do any action on the ticket? 412 action = req.args.get('action', None) 413 414 # Make sure the action is valid 415 if action not in get_ticket_actions(ticket, self.perm): 416 raise util.TracError('Invalid action') 417 385 418 # TODO: this should not be hard-coded like this 386 action = req.args.get('action', None)387 419 if action == 'accept': 388 420 ticket['status'] = 'assigned' 389 421 ticket['owner'] = req.authname … … 397 429 ticket['status'] = 'reopened' 398 430 ticket['resolution'] = '' 399 431 400 ticket.populate(req.args)401 402 432 now = int(time.time()) 403 433 ticket.save_changes(self.db, req.args.get('author', req.authname), 404 434 req.args.get('comment'), when=now) … … 491 521 # List attached files 492 522 self.env.get_attachments_hdf(self.db, 'ticket', str(id), req.hdf, 493 523 'ticket.attachments') 494 req.hdf['ticket.attach_href'] = self.env.href.attachment('ticket', id) 524 if self.perm.has_permission(perm.TICKET_ATTACH): 525 req.hdf['ticket.attach_href'] = self.env.href.attachment('ticket', id) 495 526 527 # Add the possible workflow paths to hdf 528 for action in get_ticket_actions(ticket,self.perm): 529 req.hdf['ticket.workflow.' + action] = '1' 530 496 531 def render(self, req): 497 532 self.perm.assert_permission (perm.TICKET_VIEW) 498 533 -
templates/ticket.cs
128 128 /each ?></div><?cs 129 129 /if ?> 130 130 131 <?cs if $trac.acl.TICKET_ MODIFY?>131 <?cs if $trac.acl.TICKET_CHGPROP || $trac.acl.TICKET_APPEND ?> 132 132 <form action="<?cs var:cgi_location ?>#preview" method="post"> 133 133 <hr /> 134 134 <h3><a name="edit" onfocus="document.getElementById('comment').focus()">Add/Change #<?cs … … 155 155 /if ?> 156 156 </div> 157 157 158 <?cs if $trac.acl.TICKET_CHGPROP ?> 158 159 <fieldset id="properties"> 159 160 <legend>Change Properties</legend> 160 161 <div class="main"> … … 203 204 <?cs call:ticket_custom_props(ticket) ?> 204 205 </div><?cs /if ?> 205 206 </fieldset> 207 <?cs /if ?> 206 208 209 <?cs if ticket.workflow.accept || ticket.workflow.reopen || ticket.workflow.resolve || ticket.workflow.reassign ?> 207 210 <fieldset id="action"> 208 211 <legend>Action</legend><?cs 209 212 if:!ticket.action ?><?cs set:ticket.action = 'leave' ?><?cs … … 214 217 /if ?> /><?cs 215 218 /def ?> 216 219 <?cs call:action_radio('leave') ?> 217 <label for="leave">leave as <?cs var:ticket.status ?></label><br /><?cs218 if $ticket.status == "new" ?>219 <?cscall:action_radio('accept') ?>220 <label for="accept">accept ticket</label><br /><?cs220 <label for="leave">leave as <?cs var:ticket.status ?></label><br /><?cs 221 if ticket.workflow.accept ?><?cs 222 call:action_radio('accept') ?> 223 <label for="accept">accept ticket</label><br /><?cs 221 224 /if ?><?cs 222 if $ticket.status == "closed" ?>223 <?cscall:action_radio('reopen') ?>224 <label for="reopen">reopen ticket</label><br /><?cs225 if ticket.workflow.reopen ?><?cs 226 call:action_radio('reopen') ?> 227 <label for="reopen">reopen ticket</label><br /><?cs 225 228 /if ?><?cs 226 if $ticket.status == "new" || $ticket.status == "assigned" || $ticket.status == "reopened" ?> 227 <?cs call:action_radio('resolve') ?> 228 <label for="resolve">resolve</label> 229 <label for="resolve_resolution">as:</label> 230 <?cs call:hdf_select(enums.resolution, "resolve_resolution", args.resolve_resolution, 0) ?><br /> 231 <?cs call:action_radio('reassign') ?> 232 <label for="reassign">reassign</label> 233 <label>to:<?cs 234 if:len(ticket.users) ?><?cs 235 call:hdf_select(ticket.users, "reassign_owner", ticket.reassign_owner, 0) ?><?cs 236 else ?> 237 <input type="text" id="reassign_owner" name="reassign_owner" size="40" value="<?cs 238 var:ticket.reassign_owner ?>" /><?cs 239 /if ?></label><?cs 229 if ticket.workflow.resolve ?><?cs 230 call:action_radio('resolve') ?> 231 <label for="resolve">resolve</label> 232 <label for="resolve_resolution">as:</label> 233 <?cs call:hdf_select(enums.resolution, "resolve_resolution", args.resolve_resolution, 0) ?><br /><?cs 240 234 /if ?><?cs 241 if $ticket.status == "new" || $ticket.status == "assigned" || $ticket.status == "reopened" ?> 242 <script type="text/javascript"> 243 var resolve = document.getElementById("resolve"); 244 var reassign = document.getElementById("reassign"); 245 var updateActionFields = function() { 246 enableControl('resolve_resolution', resolve.checked); 247 enableControl('reassign_owner', reassign.checked); 235 if ticket.workflow.reassign ?><?cs 236 call:action_radio('reassign') ?> 237 <label for="reassign">reassign</label> 238 <label>to:<?cs 239 if:len(ticket.users) ?><?cs 240 call:hdf_select(ticket.users, "reassign_owner", ticket.reassign_owner, 0) ?><?cs 241 else ?> 242 <input type="text" id="reassign_owner" name="reassign_owner" size="40" value="<?cs 243 var:ticket.reassign_owner ?>" /><?cs 244 /if ?></label><?cs 245 /if ?><?cs 246 if ticket.workflow.resolve || ticket.workflow.reassign ?> 247 <script type="text/javascript"><?cs 248 if ticket.workflow.resolve ?> 249 var resolve = document.getElementById("resolve");<?cs 250 /if ?><?cs 251 if ticket.workflow.reassign ?> 252 var reassign = document.getElementById("reassign");<?cs 253 /if ?> 254 var updateActionFields = function() {<?cs 255 if ticket.workflow.resolve ?> 256 enableControl('resolve_resolution', resolve.checked);<?cs 257 /if ?><?cs 258 if ticket.workflow.reassign ?> 259 enableControl('reassign_owner', reassign.checked);<?cs 260 /if ?> 248 261 }; 249 262 addEvent(window, 'load', updateActionFields); 250 263 addEvent(document.getElementById("leave"), 'click', updateActionFields);<?cs 251 if $ticket.status == "new"?>264 if ticket.workflow.accept ?> 252 265 addEvent(document.getElementById("accept"), 'click', updateActionFields);<?cs 253 /if ?> 254 addEvent(resolve, 'click', updateActionFields); 255 addEvent(reassign, 'click', updateActionFields); 266 /if ?><?cs 267 if ticket.workflow.resolve ?> 268 addEvent(resolve, 'click', updateActionFields);<?cs 269 /if ?><?cs 270 if ticket.workflow.reopen ?> 271 addEvent(document.getElementById("reopen"), 'click', updateActionFields);<?cs 272 /if ?><?cs 273 if ticket.workflow.reassign ?> 274 addEvent(reassign, 'click', updateActionFields);<?cs 275 /if ?> 256 276 </script><?cs 257 277 /if ?> 258 278 </fieldset> 279 <?cs else ?> 280 <input type="hidden" name="action" value="leave" /> 281 <?cs /if ?> 259 282 260 283 <script type="text/javascript" src="<?cs 261 284 var:htdocs_location ?>js/wikitoolbar.js"></script> … … 263 286 <div class="buttons"> 264 287 <input type="reset" value="Reset" /> 265 288 <input type="submit" name="preview" value="Preview" /> 266 <input type="submit" value="Submit changes" /> 289 <input type="submit" value="Submit changes" /> 267 290 </div> 268 291 </form> 269 292 <?cs /if ?>
