| 1 | from trac.core import * |
|---|
| 2 | from trac.perm import PermissionCache, IPermissionRequestor, IPermissionGroupProvider, IPermissionPolicy, PermissionSystem, DefaultPermissionStore, PermissionError |
|---|
| 3 | from trac.ticket.model import Ticket |
|---|
| 4 | from trac.config import IntOption, ListOption |
|---|
| 5 | from trac.util.compat import set |
|---|
| 6 | import traceback |
|---|
| 7 | |
|---|
| 8 | class InternalTicketsPolicy(Component): |
|---|
| 9 | """Hide internal tickets.""" |
|---|
| 10 | implements(IPermissionPolicy) |
|---|
| 11 | group_providers = ExtensionPoint(IPermissionGroupProvider) |
|---|
| 12 | |
|---|
| 13 | # IPermissionPolicy(Interface) |
|---|
| 14 | def check_permission(self, action, username, resource, perm): |
|---|
| 15 | self.log.debug("Internal: action:%s, user:%s, resource:%s, perm: %s" % |
|---|
| 16 | ( action, username, resource, perm)) |
|---|
| 17 | self.username = username |
|---|
| 18 | # Look up the resource parentage for a ticket. |
|---|
| 19 | while resource: |
|---|
| 20 | if resource.realm == 'ticket': |
|---|
| 21 | break |
|---|
| 22 | resource = resource.parent |
|---|
| 23 | if resource and resource.realm == 'ticket' and resource.id is not None: |
|---|
| 24 | rtn = self.check_ticket_access(perm, resource, username) |
|---|
| 25 | self.log.debug("Internal: RESULTS for %s: %s" % (action,rtn)) |
|---|
| 26 | return rtn |
|---|
| 27 | return None |
|---|
| 28 | |
|---|
| 29 | # Internal methods |
|---|
| 30 | def _get_groups(self, user): |
|---|
| 31 | # Get initial subjects |
|---|
| 32 | groups = set([user]) |
|---|
| 33 | for provider in self.group_providers: |
|---|
| 34 | for group in provider.get_permission_groups(user): |
|---|
| 35 | groups.add(group) |
|---|
| 36 | |
|---|
| 37 | # Essentially the default trac PermissionStore ignores user provided |
|---|
| 38 | # groups so we have to look them up manually: |
|---|
| 39 | |
|---|
| 40 | # changed this to only do this for the default permission |
|---|
| 41 | # store this has been reported as broken/very slow for the |
|---|
| 42 | # LDAP permission store |
|---|
| 43 | ps = PermissionSystem(self.env) |
|---|
| 44 | if isinstance(ps.store, DefaultPermissionStore): |
|---|
| 45 | perms = ps.get_all_permissions() |
|---|
| 46 | repeat = True |
|---|
| 47 | while repeat: |
|---|
| 48 | repeat = False |
|---|
| 49 | for subject, action in perms: |
|---|
| 50 | if subject in groups and not action.isupper() and action not in groups: |
|---|
| 51 | groups.add(action) |
|---|
| 52 | repeat = True |
|---|
| 53 | |
|---|
| 54 | return groups |
|---|
| 55 | |
|---|
| 56 | # Public methods |
|---|
| 57 | def check_ticket_access(self, perm, res, user): |
|---|
| 58 | """Return if this req is permitted access to the given ticket ID.""" |
|---|
| 59 | try: |
|---|
| 60 | tkt = Ticket(self.env, res.id) |
|---|
| 61 | except Exception, e: |
|---|
| 62 | self.log.warning("Internal: TandE ticket_policy failed to find a ticket for %s : error: %s" % (res, unicode(e))) |
|---|
| 63 | return None # Ticket doesn't exist / ticket id was invalid |
|---|
| 64 | private_tkt = tkt['internal'] == '1' |
|---|
| 65 | |
|---|
| 66 | if private_tkt: |
|---|
| 67 | # cant just check or we get in an infinite call loop |
|---|
| 68 | perm = PermissionCache(self.env, self.username, None, perm._cache) |
|---|
| 69 | groups = self._get_groups(user) |
|---|
| 70 | perm_or_group = self.config.get('ticket', 'internalgroup', 'TIME_ADMIN' ) |
|---|
| 71 | it = perm_or_group in groups or perm.has_permission(perm_or_group) |
|---|
| 72 | return it |
|---|
| 73 | return None |
|---|