source: timingandestimationplugin/branches/trac0.12-Permissions/timingandestimationplugin/reports_filter.py

Last change on this file was 12966, checked in by Russ Tyndall, 10 years ago

remove hours/work summary reports from the view-tickets screen re #11005

File size: 5.4 KB
RevLine 
[8141]1from trac.web.api import ITemplateStreamFilter
2from trac.core import *
3from genshi.core import *
4from genshi.builder import tag
[8262]5from trac.perm import PermissionError
[8141]6try: 
7    set 
8except NameError: 
9    from sets import Set as set     # Python 2.3 fallback
10
11from genshi.filters.transform import Transformer
12import re
13import dbhelper
14
15from trac.ticket.report import ReportModule
16from trac.util.datefmt import format_datetime, format_time
17import csv
18from trac.web.api import RequestDone
[12966]19from trac.web.chrome import add_script
20from trac.web.api import IRequestFilter
[8141]21
[12966]22class ReportsFilter(Component):
23    """This component Removed rows from the report that require the
24       management screen to supply values"""
25    implements(IRequestFilter)
26    def pre_process_request(self, req, handler):
27        return handler
[8141]28
[12966]29    def post_process_request(self, req, template, data, content_type):
30        if template == 'report_list.html':
31            add_script(req, "billing/report_filter.js")
32        return (template, data, content_type)
33
[8141]34# This can go away once they fix http://genshi.edgewall.org/ticket/136
35# At that point we should use Transformer.filter
36# THIS IS STILL SOLVING PROBLEMS WELL AFTER THAT TICKET HAS BEEN CLOSED - A new ticket #290 [1000] has fixed the bug, but is
37# not the trac default yet
38# Without this (using the default filter) I was getting omitted closing tags for some tags (Based on whitespace afaict)
39class FilterTransformation(object):
40    """Apply a normal stream filter to the selection. The filter is called once
41    for each contiguous block of marked events."""
42
43    def __init__(self, filter):
44        """Create the transform.
45
46        :param filter: The stream filter to apply.
47        """
48        self.filter = filter
49
50    def __call__(self, stream):
51        """Apply the transform filter to the marked stream.
52
53        :param stream: The marked event stream to filter
54        """
55        def flush(queue):
56            if queue:
57                for event in self.filter(queue):
58                    yield event
59                del queue[:]
60
61        queue = []
62        for mark, event in stream:
63            if mark:
64                queue.append(event)
65            else:
66                for e in flush(queue):
67                    yield None,e
68                yield None,event
69        for event in flush(queue):
[12966]70            yield None,event               
[8141]71
72billing_report_regex = re.compile("\{(?P<reportid>\d*)\}")
73def report_id_from_text(text):
74    m = billing_report_regex.match(text)
75    if m:
76        return int(m.groupdict()["reportid"])
77
78def get_billing_reports(comp):
79    billing_reports = set()
80    rows = dbhelper.get_all(comp.env, "SELECT id FROM custom_report")[1]
81    if rows:
82        billing_reports = set([x[0] for x in rows])
83    return billing_reports
84
85class ReportScreenFilter(Component):
86    """Hides TandE reports even when you just go to the url"""
87    implements(ITemplateStreamFilter)
88    def __init__(self):
89        self.billing_reports = get_billing_reports(self)
90        self.log.debug('ReportScreenFilter: self.billing_reports= %r' % self.billing_reports)
91
92    def filter_stream(self, req, method, filename, stream, data):
93        if not filename in ('report_view.html', 'report_list.html'):
94            return stream
95        reportid = [None]
96
97        def idhelper(strm):
98            header = strm[0][1]
99            if not reportid[0]:
100                self.log.debug("ReportScreenFilter: helper: %s %s %s"%(strm,header,report_id_from_text(header)))
101                reportid[0] = report_id_from_text(header)
102            for kind, data, pos in strm:
103                yield kind, data, pos       
104               
105        def permhelper(strm):
106            id = reportid[0]
107            self.log.debug("ReportScreenFilter: id:%s, in bill: %s   has perm:%s" % (id, id in self.billing_reports, req.perm.has_permission("TIME_VIEW")))
108            if id and id in self.billing_reports and not req.perm.has_permission("TIME_VIEW"):
109                self.log.debug("ReportScreenFilter: No time view, prevent render")
110                msg = "YOU MUST HAVE TIME_VIEW PERMSSIONS TO VIEW THIS REPORT"
111                for kind, data, pos in tag.span(msg).generate():
112                    yield kind, data, pos
113            else:
114                for kind, data, pos in strm:
115                    yield kind, data, pos
116
117        self.log.debug("ReportScreenFilter: About to begin filtering of billing reports without permissions")
118        stream = stream | Transformer('//div[@id="content"]/h1/text()').apply(FilterTransformation(idhelper))
119        stream = stream | Transformer('//div[@id="content"]').apply(FilterTransformation(permhelper))
120        return stream
121
122## ENFORCE PERMISSIONS ON report exports
123
124billing_report_fname_regex = re.compile("report_(?P<reportid>\d*)")
125def report_id_from_filename(text):
126    if text:
127        m = billing_report_fname_regex.match(text)
128        if m:
129            return int(m.groupdict()["reportid"])
130    return -1;
131
[8262]132unwrapped_send_csv = ReportModule._send_csv
[8141]133def _send_csv(self, req, cols, rows, sep=',', mimetype='text/plain',
134              filename=None):
[8262]135    self.env.log.debug("T&E: In Wrapped _send_csv")
[8141]136    id = report_id_from_filename(filename)
137    reports = get_billing_reports(self)
138    if id in reports and not req.perm.has_permission("TIME_VIEW"):
[8262]139        raise PermissionError("You must have TIME_VIEW permission in order to view this report")
140    unwrapped_send_csv(self, req, cols, rows, sep, mimetype, filename)
[8141]141   
142ReportModule._send_csv = _send_csv
Note: See TracBrowser for help on using the repository browser.