On Tuesday, July 19, 2016 at 6:43:54 AM UTC-7, Florian Schricker wrote:I am uncertain whether this is possible at all so I am asking here: I would like to disable modifying the ticket description when the ticket is in a given state while still allowing commenting. Can anything like this be configured in a workflow?
1. BlackMagicTicketsPlugin (1) allows a permission to be specified to edit a ticket field.
2. ExtraPermissionsProvider (2) allow you to define new permissions.
3. A permissions policy could be implemented, similar to ReadonlySignedTickets (3), to deny a permission when the ticket is in a particular state.Putting those three things together, I think it might work to define a new permission for editing the ticket description, and deny the permission when the ticket is in a particular state.
author = "xxxx"
from trac.core import *from trac.perm import IPermissionPolicyfrom trac.ticket.model import Ticket
class XxxxxxReadonlyTicketsPlugin(Component): implements(IPermissionPolicy)
def check_permission(self, action, username, resource, perm): if resource is None or resource.realm != 'ticket' or \ resource.id is None or \ action in ['TICKET_VIEW', 'TICKET_APPEND'] or \ action == 'TICKET_ADMIN' or 'TICKET_ADMIN' in perm: return None
t = Ticket(self.env, resource.id) if t['status'] == 'closed' and t['type'] == 'review': return False
permission_policies = PrivateWikiSystem, PrivateTicketsPolicy, AttachmentDeletePolicy, DefaultPermissionPolicy, LegacyAttachmentPolicy
2016-08-29 09:40:26,888 Trac[web_ui] ERROR: Timeline event provider failed:Traceback (most recent call last): File "/usr/lib/python2.6/site-packages/Trac-1.0-py2.6.egg/trac/timeline/web_ui.py", line 190, in process_request filters) or []: File "/usr/lib/python2.6/site-packages/Trac-1.0-py2.6.egg/trac/ticket/web_ui.py", line 335, in get_timeline_events for (ev, t) in produce_ticket_change_events(db): File "/usr/lib/python2.6/site-packages/Trac-1.0-py2.6.egg/trac/ticket/web_ui.py", line 308, in produce_ticket_change_events cid) File "/usr/lib/python2.6/site-packages/Trac-1.0-py2.6.egg/trac/ticket/web_ui.py", line 262, in produce_event if 'TICKET_VIEW' not in req.perm(ticket): File "/usr/lib/python2.6/site-packages/Trac-1.0-py2.6.egg/trac/perm.py", line 556, in has_permission return self._has_permission(action, resource) File "/usr/lib/python2.6/site-packages/Trac-1.0-py2.6.egg/trac/perm.py", line 570, in _has_permission check_permission(action, perm.username, resource, perm) File "/usr/lib/python2.6/site-packages/Trac-1.0-py2.6.egg/trac/perm.py", line 462, in check_permission perm) File "/usr/lib/python2.6/site-packages/TracPrivateTickets-2.0.2dev_r11777-py2.6.egg/privatetickets/policy.py", line 34, in check_permission 'TRAC_ADMIN' in perm: File "/usr/lib/python2.6/site-packages/Trac-1.0-py2.6.egg/trac/perm.py", line 556, in has_permission return self._has_permission(action, resource) File "/usr/lib/python2.6/site-packages/Trac-1.0-py2.6.egg/trac/perm.py", line 570, in _has_permission check_permission(action, perm.username, resource, perm) File "/usr/lib/python2.6/site-packages/Trac-1.0-py2.6.egg/trac/perm.py", line 462, in check_permission perm) File "/var/trac/imstec/plugins/XxxxxReadonlyTicketsPlugin.py", line 14, in check_permission
action == 'TICKET_ADMIN' or 'TICKET_ADMIN' in perm:
File "/usr/lib/python2.6/site-packages/Trac-1.0-py2.6.egg/trac/perm.py", line 556, in has_permission return self._has_permission(action, resource) File "/usr/lib/python2.6/site-packages/Trac-1.0-py2.6.egg/trac/perm.py", line 570, in _has_permission check_permission(action, perm.username, resource, perm) File "/usr/lib/python2.6/site-packages/Trac-1.0-py2.6.egg/trac/perm.py", line 462, in check_permission perm) File "/usr/lib/python2.6/site-packages/TracPrivateTickets-2.0.2dev_r11777-py2.6.egg/privatetickets/policy.py", line 34, in check_permission 'TRAC_ADMIN' in perm: File "/usr/lib/python2.6/site-packages/Trac-1.0-py2.6.egg/trac/perm.py", line 556, in has_permission return self._has_permission(action, resource) File "/usr/lib/python2.6/site-packages/Trac-1.0-py2.6.egg/trac/perm.py", line 570, in _has_permission check_permission(action, perm.username, resource, perm) File "/usr/lib/python2.6/site-packages/Trac-1.0-py2.6.egg/trac/perm.py", line 462, in check_permission perm) File "/var/trac/imstec/plugins/XxxxxReadonlyTicketsPlugin.py", line 14, in check_permission
action == 'TICKET_ADMIN' or 'TICKET_ADMIN' in perm:
File "/usr/lib/python2.6/site-packages/Trac-1.0-py2.6.egg/trac/perm.py", line 556, in has_permission return self._has_permission(action, resource) File "/usr/lib/python2.6/site-packages/Trac-1.0-py2.6.egg/trac/perm.py", line 570, in _has_permission check_permission(action, perm.username, resource, perm) File "/usr/lib/python2.6/site-packages/Trac-1.0-py2.6.egg/trac/perm.py", line 462, in check_permission perm)[... and so on ...]
File "/usr/lib/python2.6/site-packages/TracPrivateTickets-2.0.2dev_r11777-py2.6.egg/privatetickets/policy.py", line 34, in check_permission
'TRAC_ADMIN' in perm:
...
File "/var/trac/imstec/plugins/XxxxxReadonlyTicketsPlugin.py", line 14, in check_permissionaction == 'TICKET_ADMIN' or 'TICKET_ADMIN' in perm:
As can be seen "TracPrivateTickets" might be the culprit?Any idea? Or a workaround in my XxxxxReadonlyTicketsPlugin?
action ==
'TRAC_ADMIN'`
to the check as
follows:
def check_permission(self, action, username, resource, perm):if resource is None or resource.realm != 'ticket' or \resource.id is None or \
action in ['TICKET_VIEW', 'TICKET_APPEND'] or \
action == 'TRAC_ADMIN' or \
action == 'TICKET_ADMIN' or 'TICKET_ADMIN' in perm:return None
While this now fixes the Timeline function, modifying tickets now fails with the same recursion error. I have not yet checked the logs.For a better understanding let me ask the following question:From my research I was not expecting the policies to "interact" with each other recursively at all. I was thinking that all configured policies are asked in sequence until some policy returns True or False, with returning None just meaning "ask the next policy". Where is the recursion? Is it a bug in TracPrivateTickets?
(I checked the TracPrivateTickets defects, newer revisions do not fix anything wrt to permissions.)
Unfortunately it still fails.
This time I am attaching a more or less complete log from tracd-start until "recursion error" and the source file of the plugin I am using.
I hope that helps - I am more than willing in testing anything while providing any information I can collect. Any config files or other files of interest? Just let me know.
regards,Florian
Am Freitag, 16. September 2016 03:16:17 UTC+2 schrieb RjOllos:On Tuesday, August 30, 2016 at 12:25:26 AM UTC-7, Florian Schricker wrote:While this now fixes the Timeline function, modifying tickets now fails with the same recursion error. I have not yet checked the logs.
For a better understanding let me ask the following question:
From my research I was not expecting the policies to "interact" with each other recursively at all. I was thinking that all configured policies are asked in sequence until some policy returns True or False, with returning None just meaning "ask the next policy". Where is the recursion? Is it a bug in TracPrivateTickets?
Am Freitag, 16. September 2016 03:16:17 UTC+2 schrieb RjOllos:
There shouldn't be recursion in ReadonlySignedTickets because of the check "action == 'TICKET_ADMIN' or 'TICKET_ADMIN' in perm". "'TICKET_ADMIN' in perm" will cause a recursive permission check for the action TICKET_ADMIN, but when ReadonlySignedTickets is called again it will return None due to the "action == 'TICKET_ADMIN'" conditional.
On 21.09.2016 09:06, Florian Schricker wrote:
Unfortunately it still fails.
This time I am attaching a more or less complete log from tracd-start until "recursion error" and the source file of the plugin I am using.
I hope that helps - I am more than willing in testing anything while providing any information I can collect. Any config files or other files of interest? Just let me know.
regards,Florian
Am Freitag, 16. September 2016 03:16:17 UTC+2 schrieb RjOllos:On Tuesday, August 30, 2016 at 12:25:26 AM UTC-7, Florian Schricker wrote:While this now fixes the Timeline function, modifying tickets now fails with the same recursion error. I have not yet checked the logs.
For a better understanding let me ask the following question:
From my research I was not expecting the policies to "interact" with each other recursively at all. I was thinking that all configured policies are asked in sequence until some policy returns True or False, with returning None just meaning "ask the next policy". Where is the recursion? Is it a bug in TracPrivateTickets?
It's "mutual recursion". Unfortunately that means it's not a simple bug you can necessarily fix in one plugin alone. It's an unfortunate interaction between the two plugins.
The idea was, exactly as you say, to ask each policy in turn. But each plugin basically says: "Hang on, before I answer, let me ask you this first: Is this other thing allowed?"
And again each policy is asked in turn about this new question, and so on forever...
Each policy is protected against its own such recursive questions:
Am Freitag, 16. September 2016 03:16:17 UTC+2 schrieb RjOllos:
But neither policy can detect re-entrancy in general. It only shortcuts its own kind of followup question.There shouldn't be recursion in ReadonlySignedTickets because of the check "action == 'TICKET_ADMIN' or 'TICKET_ADMIN' in perm". "'TICKET_ADMIN' in perm" will cause a recursive permission check for the action TICKET_ADMIN, but when ReadonlySignedTickets is called again it will return None due to the "action == 'TICKET_ADMIN'" conditional.
Since the other policy asks about a different kind of permission, this is not detected.
Detailed step-by-step description of events:1. The initial question is from web_ui.py about TICKET_VIEW.
2. The Permission System asks each policy about this in turn.
3. First it asks the privatetickets policy, which interjects (recursively calls):
"To answer that, I first need to know if TICKET_VIEW_REPORTER is available."
4. The Permission System again poses this new question to each policy in turn.
5. First it asks the privatetickets policy, which expected this and replies "None".
(This is not visible in the stack trace.)
6. Then it asks ReadonlyTicketsPlugin, which interjects:
"To answer that, I first need to know if TICKET_ADMIN is available."
7. The Permission System again poses this new question to each policy in turn.
8. First it asks the privatetickets policy, which interjects (recursively calls):
"To answer that I first need to know if TICKET_VIEW_REPORTER is available".
And since 8. is exactly the same situation as 3. it continues in the same way forever.
> I also posted modifications to SignedTickets, but I don't expect they
> will fix this "interaction" issue:
> https://trac.edgewall.org/wiki/CookBook/Configuration/SignedTickets?version=9
>>> - 'TICKET_ADMIN' in perm:
>>> + any(a in perm for a in self.admin_actions):
This change seems unnecessary and maybe even more problematic than before.
Unnecessary because TRAC_ADMIN implies TICKET_ADMIN anyway, so there's
no need to check for TRAC_ADMIN explicitly. (But there may be more
subtle details I'm missing.)
Problematic because checking more permissions leads to more potentially
problematic interactions (and possible mutual recursion) with other
policies.