Edgewall Software

Ticket #1396: TicketClosePermissions-r1496.2.diff

File TicketClosePermissions-r1496.2.diff, 11.3 KB (added by ludde, 4 years ago)
  • trac/attachment.py

     
    6363                self.render_view(req, parent_type, parent_id, filename) 
    6464 
    6565    def render_form(self, req, parent_type, parent_id): 
    66         perm_map = {'ticket': perm.TICKET_MODIFY, 'wiki': perm.WIKI_MODIFY} 
     66        perm_map = {'ticket': perm.TICKET_ATTACH, 'wiki': perm.WIKI_MODIFY} 
    6767        self.perm.assert_permission(perm_map[parent_type]) 
    6868 
    6969        text, link = self.get_parent_link(parent_type, parent_id) 
     
    7979        req.display('attachment.cs') 
    8080 
    8181    def save_attachment(self, req, parent_type, parent_id): 
    82         perm_map = {'ticket': perm.TICKET_MODIFY, 'wiki': perm.WIKI_MODIFY} 
     82        perm_map = {'ticket': perm.TICKET_ATTACH, 'wiki': perm.WIKI_MODIFY} 
    8383        self.perm.assert_permission(perm_map[parent_type]) 
    8484 
    8585        if req.args.has_key('cancel'): 
  • trac/perm.py

     
    2424    'TIMELINE_VIEW', 'SEARCH_VIEW', 'CONFIG_VIEW', 'LOG_VIEW', 'FILE_VIEW', 
    2525    'CHANGESET_VIEW', 'BROWSER_VIEW', 'ROADMAP_VIEW', 
    2626     
    27     'TICKET_VIEW', 'TICKET_CREATE', 'TICKET_MODIFY', 
     27    'TICKET_VIEW', 'TICKET_CREATE', 'TICKET_CHGPROP', 'TICKET_RESOLVE',  
     28    'TICKET_APPEND','TICKET_ATTACH', 
    2829     
    2930    'REPORT_VIEW', 'REPORT_SQL_VIEW', 'REPORT_CREATE', 'REPORT_MODIFY', 
    3031    'REPORT_DELETE', 
     
    4041                   'TIMELINE_VIEW', 'SEARCH_VIEW', 'CONFIG_VIEW', 'LOG_VIEW', 
    4142                   'FILE_VIEW', 'CHANGESET_VIEW', 'BROWSER_VIEW'], 
    4243    'TICKET_ADMIN': ['TICKET_VIEW', 'TICKET_CREATE', 'TICKET_MODIFY'], 
     44    'TICKET_MODIFY': ['TICKET_CHGPROP', 'TICKET_RESOLVE', 'TICKET_ATTACH'], 
    4345    'REPORT_ADMIN': ['REPORT_VIEW', 'REPORT_SQL_VIEW', 'REPORT_CREATE', 
    4446                     'REPORT_MODIFY', 'REPORT_DELETE'], 
    4547    'WIKI_ADMIN': ['WIKI_VIEW', 'WIKI_CREATE', 'WIKI_MODIFY', 'WIKI_DELETE'], 
  • trac/Ticket.py

     
    366366 
    367367        req.display('newticket.cs') 
    368368 
     369def 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'])) 
    369387 
    370388class TicketModule (Module): 
    371389 
    372390    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.') 
    375395 
    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) 
    378399 
    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) 
    381402 
    382         if req.args.has_key('reporter'): 
    383             self.perm.assert_permission (perm.TICKET_ADMIN) 
     403            ticket.populate(req.args) 
    384404 
     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 
    385418        # TODO: this should not be hard-coded like this 
    386         action = req.args.get('action', None) 
    387419        if action == 'accept': 
    388420            ticket['status'] =  'assigned' 
    389421            ticket['owner'] = req.authname 
     
    397429            ticket['status'] = 'reopened' 
    398430            ticket['resolution'] = '' 
    399431 
    400         ticket.populate(req.args) 
    401  
    402432        now = int(time.time()) 
    403433        ticket.save_changes(self.db, req.args.get('author', req.authname), 
    404434                            req.args.get('comment'), when=now) 
     
    491521        # List attached files 
    492522        self.env.get_attachments_hdf(self.db, 'ticket', str(id), req.hdf, 
    493523                                     '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) 
    495526 
     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 
    496531    def render(self, req): 
    497532        self.perm.assert_permission (perm.TICKET_VIEW) 
    498533 
  • templates/ticket.cs

     
    128128 /each ?></div><?cs 
    129129/if ?> 
    130130 
    131 <?cs if $trac.acl.TICKET_MODIFY ?> 
     131<?cs if $trac.acl.TICKET_CHGPROP || $trac.acl.TICKET_APPEND ?> 
    132132<form action="<?cs var:cgi_location ?>#preview" method="post"> 
    133133 <hr /> 
    134134 <h3><a name="edit" onfocus="document.getElementById('comment').focus()">Add/Change #<?cs 
     
    155155  /if ?> 
    156156 </div> 
    157157 
     158 <?cs if $trac.acl.TICKET_CHGPROP ?> 
    158159 <fieldset id="properties"> 
    159160  <legend>Change Properties</legend> 
    160161  <div class="main"> 
     
    203204   <?cs call:ticket_custom_props(ticket) ?> 
    204205  </div><?cs /if ?> 
    205206 </fieldset> 
     207 <?cs /if ?> 
    206208 
     209 <?cs if ticket.workflow.accept || ticket.workflow.reopen || ticket.workflow.resolve || ticket.workflow.reassign ?> 
    207210 <fieldset id="action"> 
    208211  <legend>Action</legend><?cs 
    209212  if:!ticket.action ?><?cs set:ticket.action = 'leave' ?><?cs 
     
    214217     /if ?> /><?cs 
    215218  /def ?> 
    216219  <?cs call:action_radio('leave') ?> 
    217   <label for="leave">leave as <?cs var:ticket.status ?></label><br /><?cs 
    218   if $ticket.status == "new" ?> 
    219    <?cs call:action_radio('accept') ?> 
    220    <label for="accept">accept ticket</label><br /><?cs 
     220    <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 
    221224  /if ?><?cs 
    222   if $ticket.status == "closed" ?> 
    223    <?cs call:action_radio('reopen') ?> 
    224    <label for="reopen">reopen ticket</label><br /><?cs 
     225  if ticket.workflow.reopen ?><?cs 
     226    call:action_radio('reopen') ?> 
     227    <label for="reopen">reopen ticket</label><br /><?cs 
    225228  /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 
    240234  /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 ?> 
    248261     }; 
    249262     addEvent(window, 'load', updateActionFields); 
    250263     addEvent(document.getElementById("leave"), 'click', updateActionFields);<?cs 
    251     if $ticket.status == "new" ?> 
     264   if ticket.workflow.accept ?> 
    252265     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 ?> 
    256276   </script><?cs 
    257277  /if ?> 
    258278 </fieldset> 
     279 <?cs else ?> 
     280 <input type="hidden" name="action" value="leave" /> 
     281 <?cs /if ?> 
    259282 
    260283 <script type="text/javascript" src="<?cs 
    261284   var:htdocs_location ?>js/wikitoolbar.js"></script> 
     
    263286 <div class="buttons"> 
    264287  <input type="reset" value="Reset" />&nbsp; 
    265288  <input type="submit" name="preview" value="Preview" />&nbsp; 
    266   <input type="submit" value="Submit changes" />  
     289  <input type="submit" value="Submit changes" /> 
    267290 </div> 
    268291</form> 
    269292<?cs /if ?>