Edgewall Software

Ticket #153: privacy.3.diff

File privacy.3.diff, 23.8 KB (added by Waldemar Kornewald <wkornewald>, 5 years ago)

patch against trunk (r4475). tested, seems to work

  • trac/ticket/api.py

     
    102102        field = {'name': 'owner', 'label': 'Owner'} 
    103103        if self.restrict_owner: 
    104104            field['type'] = 'select' 
    105             users = [''] # for clearing assignment 
    106105            perm = PermissionSystem(self.env) 
    107             for username, name, email in self.env.get_known_users(db): 
    108                 if perm.get_user_permissions(username).get('TICKET_MODIFY'): 
    109                     users.append(username) 
    110             field['options'] = users 
     106            def valid_owner(username): 
     107                return perm.get_user_permissions(username).get('TICKET_MODIFY') 
     108            field['options'] = [username for username, name, email 
     109                                in self.env.get_known_users() 
     110                                if valid_owner(username)] 
    111111            field['optional'] = True 
    112112        else: 
    113113            field['type'] = 'text' 
  • trac/ticket/web_ui.py

     
    602602        data = { 
    603603            'ticket': ticket, 
    604604            'context': Context(self.env, req, 'ticket', ticket.id, db=db), 
    605             'changes': changes, 
     605            'changes': changes 
    606606        } 
    607607 
    608608        output = Chrome(self.env).render_template(req, 'ticket.rss', data, 
  • trac/ticket/report.py

     
    2323from trac.db import get_column_names 
    2424from trac.perm import IPermissionRequestor 
    2525from trac.util import sorted 
    26 from trac.util.text import to_unicode, unicode_urlencode 
     26from trac.util.text import obfuscate_email_address, to_unicode, unicode_urlencode 
    2727from trac.util.html import html 
    2828from trac.web.api import IRequestHandler, RequestDone 
    2929from trac.web.chrome import add_link, add_stylesheet, INavigationContributor 
     
    278278 
    279279        # Get the email addresses of all known users 
    280280        email_map = {} 
    281         for username, name, email in self.env.get_known_users(): 
    282             if email: 
    283                 email_map[username] = email 
     281        show_email_addresses = self.config.getbool('trac', 
     282                'show_email_addresses') 
     283        if show_email_addresses: 
     284            for username, name, email in self.env.get_known_users(): 
     285                if email: 
     286                    email_map[username] = email 
    284287 
    285288        # Structure the rows and cells: 
    286289        #  - group rows according to __group__ value, if defined 
     
    313316                    # Special casing based on column name 
    314317                    col = col.strip('_') 
    315318                    if col == 'reporter': 
    316                         if '@' in value: 
     319                        if show_email_addresses: 
     320                            if '@' in value: 
     321                                cell['author'] = value 
     322                            elif value in email_map: 
     323                                cell['author'] = email_map[value] 
     324                        else: 
    317325                            cell['author'] = value 
    318                         elif value in email_map: 
    319                             cell['author'] = email_map[value] 
    320326                    elif col == 'resource': 
    321327                        resource = value 
    322328                    cell_group.append(cell) 
  • trac/ticket/query.py

     
    684684        query.verbose = True 
    685685        db = self.env.get_db_cnx() 
    686686        results = query.execute(req, db) 
    687         for result in results: 
    688             if result['reporter'].find('@') == -1: 
    689                 result['reporter'] = '' 
     687        if self.config.getbool('trac', 'show_email_addresses'): 
     688            for result in results: 
     689                if result['reporter'].find('@') == -1: 
     690                    result['reporter'] = '' 
    690691        query_href = req.abs_href.query(group=query.group, 
    691692                                        groupdesc=query.groupdesc and 1 or None, 
    692693                                        verbose=query.verbose and 1 or None, 
  • trac/versioncontrol/web_ui/log.py

     
    179179        changes = get_changes(repos, revs) 
    180180        extra_changes = {} 
    181181        email_map = {} 
     182        show_email_addresses = self.config.getbool('trac', 
     183                                                   'show_email_addresses') 
    182184        if format == 'rss': 
    183185            # Get the email addresses of all known users 
    184             email_map = {} 
    185             for username,name,email in self.env.get_known_users(): 
    186                 if email: 
    187                     email_map[username] = email 
     186            if show_email_addresses: 
     187                for username,name,email in self.env.get_known_users(): 
     188                    if email: 
     189                        email_map[username] = email 
    188190        elif format == 'changelog': 
    189191            for rev in revs: 
    190192                changeset = changes[rev] 
  • trac/perm.py

     
    246246    # IPermissionRequestor methods 
    247247 
    248248    def get_permission_actions(self): 
    249         """Implement the global `TRAC_ADMIN` meta permission.""" 
    250         actions = [] 
     249        """Implement the global `TRAC_ADMIN` meta permission and the 
     250        `EMAIL_VIEW` permission which allows for showing email addresses 
     251        when "show_email_addresses" is "false".""" 
     252        actions = ['EMAIL_VIEW'] 
    251253        for requestor in [r for r in self.requestors if r is not self]: 
    252254            for action in requestor.get_permission_actions(): 
    253255                if isinstance(action, tuple): 
    254256                    actions.append(action[0]) 
    255257                else: 
    256258                    actions.append(action) 
    257         return [('TRAC_ADMIN', actions)] 
     259        return [('TRAC_ADMIN', actions), 'EMAIL_VIEW'] 
    258260 
    259261 
    260262class PermissionCache(object): 
  • trac/timeline/web_ui.py

     
    139139        if format == 'rss': 
    140140            # Get the email addresses of all known users 
    141141            email_map = {} 
    142             for username, name, email in self.env.get_known_users(): 
    143                 if email: 
    144                     email_map[username] = email 
     142            if self.config.getbool('trac', 'show_email_addresses'): 
     143                for username, name, email in self.env.get_known_users(): 
     144                    if email: 
     145                        email_map[username] = email 
    145146            data['email_map'] = email_map 
    146147            return 'timeline.rss', data, 'application/rss+xml' 
    147148 
  • trac/web/chrome.py

     
    3434                      get_module_path 
    3535from trac.util.compat import partial, set 
    3636from trac.util.html import plaintext 
    37 from trac.util.text import pretty_size, shorten_line, unicode_quote_plus, \ 
    38                            to_unicode 
     37from trac.util.text import pretty_size, obfuscate_email_address, \ 
     38                           shorten_line, unicode_quote_plus, to_unicode 
    3939from trac.util.datefmt import pretty_timedelta, format_datetime, format_date, \ 
    4040                              format_time, http_date 
    4141from trac.web.api import IRequestHandler, HTTPNotFound 
     
    194194    logo_height = IntOption('header_logo', 'height', -1, 
    195195        """Height of the header logo image in pixels.""") 
    196196 
     197    show_email_addresses = BoolOption('trac', 'show_email_addresses', 'false', 
     198        """Show email addresses instead of usernames. If false, we obfuscate 
     199        email addresses (''since 0.11'').""") 
     200 
    197201    templates = None 
    198202 
    199203    # A dictionary of default context data for templates 
     
    209213        'groupby': compat.groupby, 
    210214        'http_date': http_date, 
    211215        'itemgetter': compat.itemgetter, 
     216        'obfuscate_email_address': obfuscate_email_address, 
    212217        'paginate': presentation.paginate, 
    213218        'partial': partial, 
    214219        'plaintext': plaintext, 
     
    468473        if req: 
    469474            tzinfo = req.tz 
    470475 
     476        d['show_email_addresses'] = self.show_email_addresses or \ 
     477                'EMAIL_VIEW' in req.perm 
    471478        d.update({ 
    472479            'req': req, 
    473480            'abs_href': req and req.abs_href or self.env.abs_href, 
  • trac/util/text.py

     
    170170    except ImportError: 
    171171        return t 
    172172 
     173def obfuscate_email_address(address): 
     174    if address: 
     175        at = address.find('@') 
     176        if at != -1: 
     177            return address[:at] + "@..." + ((address[-1] == '>' and '>') or '') 
     178    return address 
    173179 
    174180# -- Conversion 
    175181 
  • templates/ticket_view.html

     
    5454               py:with="fields = [f for f in fields if not f.skip]"> 
    5555          <tr> 
    5656            <th id="h_reporter">Reported by:</th> 
    57             <td headers="h_reporter" class="searchable">${ticket.reporter}</td> 
     57            <td headers="h_reporter" class="searchable" py:with="r=ticket.reporter">${show_email_addresses and r or obfuscate_email_address(r)}</td> 
    5858            <th id="h_owner">Assigned to:</th> 
    59             <td headers="h_owner">${ticket.owner} 
     59            <td headers="h_owner" py:with="o=ticket.owner">${show_email_addresses and o or obfuscate_email_address(o)} 
    6060              <py:if test="ticket.status == 'assigned'">(accepted)</py:if> 
    6161            </td> 
    6262          </tr> 
     
    8484              </span> 
    8585              Description 
    8686              <span py:if="description_change" class="lastmod" 
    87                 title="$description_change.date"> 
    88                 (last modified by ${description_change.author}) 
     87                title="$description_change.date" py:with="a=description_change.author"> 
     88                (last modified by ${show_email_addresses and a or obfuscate_email_address(a)}) 
    8989                (<a href="${href.ticket(ticket.id, action='diff', version=description_change.cnum)}">diff</a>) 
    9090              </span> 
    9191            </h3> 
     
    127127                  </py:if> 
    128128                  &nbsp; 
    129129                </span> 
    130                 ${change.date} changed by ${change.author} 
     130                ${change.date} changed by ${show_email_addresses and change.author or obfuscate_email_address(change.author)} 
    131131              </h3> 
    132132              <ul py:if="change.fields" class="changes"> 
    133133                <li py:for="field_name, field in change.fields.items()" 
  • templates/report.rss

     
    11<?xml version="1.0"?> 
    2 <rss version="2.0" xmlns:py="http://genshi.edgewall.org/"> 
     2<rss version="2.0" xmlns:py="http://genshi.edgewall.org/" 
     3                   xmlns:dc="http://purl.org/dc/elements/1.1/"> 
    34  <channel> 
    45    <title>$project.name: $report.title</title> 
    56    <link>${abs_href.report(report.id)}</link> 
     
    1718        <py:with vars="col = cell.header.col.strip('_')"> 
    1819          <py:choose> 
    1920            <py:when test="col == 'reporter'"> 
    20               <author py:if="cell.author">$cell.author</author> 
     21              <py:if test="cell.author"> 
     22                <py:choose> 
     23                  <author py:when="show_email_addresses">$cell.author</author> 
     24                  <dc:creator py:otherwise="">${obfuscate_email_address(cell.author)}</dc:creator> 
     25                </py:choose> 
     26              </py:if> 
    2127            </py:when> 
    2228            <py:when test="col in ('time', 'changetime', 'created', 'modified')"> 
    2329              <!-- FIXME: we end up with multiple pubDate --> 
  • templates/macros.html

     
    151151    <py:def function="show_one_attachment(attachment)"> 
    152152      <a href="${context.href('attachment', context.resource, context.id, attachment.filename)}" 
    153153         title="View attachment">$attachment.filename</a> 
    154         (${sizeinfo(attachment.size)}) - added by <em>$attachment.author</em> 
     154       (${sizeinfo(attachment.size)}) - added by <em>${show_email_addresses and attachment.author or obfuscate_email_address(attachment.author)}</em> 
    155155        ${dateinfo(attachment.date)} ago. 
    156156    </py:def> 
    157157    <py:choose test=""> 
  • templates/wiki_history.html

     
    4747                <a href="${href.wiki(page.name, version=item.version)}" title="View this version">$item.version</a> 
    4848              </td> 
    4949              <td class="date">${format_datetime(item.date)}</td> 
    50               <td class="author" title="${item.ipnr and 'IP-Address: ' + item.ipnr or None">$item.author</td> 
     50              <td class="author" title="${item.ipnr and 'IP-Address: ' + item.ipnr or None">${show_email_addresses and item.author or obfuscate_email_address(item.author)}</td> 
    5151              <td class="comment">${context.wiki_to_oneliner(item.comment, shorten=True)}</td> 
    5252            </tr> 
    5353          </tbody> 
  • templates/revisionlog.rss

     
    11<?xml version="1.0"?> 
    2 <rss version="2.0" xmlns:py="http://genshi.edgewall.org/"> 
     2<rss version="2.0" xmlns:py="http://genshi.edgewall.org/" 
     3                   xmlns:dc="http://purl.org/dc/elements/1.1/"> 
    34  <channel py:with="log_href = abs_href.log(path, rev=rev)"> 
    45    <title>Revisions of $path</title> 
    56    <link>$log_href</link> 
     
    1314    </image> 
    1415 
    1516    <item py:for="item in items" py:with="change = changes[item.rev]; item_context = context('changeset', change.rev, abs_urls=True)"> 
    16       <author py:if="change.author" py:with="a = change.author">${a and '@' in a and a or email_map.get(a)}</author> 
     17      <py:if test="change.author"> 
     18        <py:choose> 
     19          <author py:when="show_email_addresses" py:with="a = change.author">${a and '@' in a and a or email_map.get(a) or a}</author> 
     20          <dc:creator py:otherwise="">${change.author}</dc:creator> 
     21        </py:choose> 
     22      </py:if> 
    1723      <pubDate>${http_date(change.date)}</pubDate> 
    1824      <title>Revision $item.rev: ${shorten_line(change.message)}</title> 
    1925      <link>${abs_href.changeset(rev, path)}</link> 
  • templates/timeline.html

     
    3838          <py:for each="event in events"> 
    3939            <dt class="${event.kind}"><a href="${event.href}"> 
    4040              <span class="time">${format_time(event.date, str('%H:%M'))}</span> ${event.title} 
    41                 <py:if test="event.author">by ${event.author}</py:if> 
     41                <py:if test="event.author" py:with="a=event.author">by ${show_email_addresses and a or obfuscate_email_address(a)}</py:if> 
    4242            </a></dt> 
    4343            <dd class="${event.kind}" py:with="wikify = event.use_oneliner and partial(event.context.wiki_to_oneliner, shorten=event.shorten_oneliner) or event.context.wiki_to_html"> 
    4444              ${event.markup} 
  • templates/timeline.rss

     
    11<?xml version="1.0"?> 
    2 <rss version="2.0" xmlns:py="http://genshi.edgewall.org/"> 
     2<rss version="2.0" xmlns:py="http://genshi.edgewall.org/" 
     3                   xmlns:dc="http://purl.org/dc/elements/1.1/"> 
    34  <channel> 
    45    <title>${project.name}</title> 
    56    <link>${abs_href.timeline()}</link> 
     
    1415 
    1516    <item py:for="event in events"> 
    1617      <title>${plaintext(event.title, keeplinebreaks=False)}</title> 
    17       <py:with vars="author=event.author; author = author and '@' in author and author or email_map.get(author)"> 
    18         <author py:if="author">$author</author> 
    19       </py:with> 
     18      <py:choose> 
     19        <py:when test="show_email_addresses"> 
     20          <py:with vars="author=event.author; author = author and '@' in author and author or email_map.get(author)"> 
     21            <author py:if="author">$author</author> 
     22          </py:with> 
     23        </py:when> 
     24        <py:otherwise> 
     25          <dc:creator py:if="event.author" py:with="a=event.author">${show_email_addresses and a or obfuscate_email_address(a)}</dc:creator> 
     26        </py:otherwise> 
     27      </py:choose> 
    2028      <pubDate>${http_date(event.date)}</pubDate> 
    2129      <link>${event.abs_href}</link> 
    2230      <guid isPermaLink="false">${event.abs_href}/${event.dateuid()}</guid> 
  • templates/ticket.rss

     
    11<?xml version="1.0"?> 
    2 <rss version="2.0" xmlns:py="http://genshi.edgewall.org/"> 
     2<rss version="2.0" xmlns:py="http://genshi.edgewall.org/" 
     3                   xmlns:dc="http://purl.org/dc/elements/1.1/"> 
    34  <channel py:with="abs_context = context(abs_urls=True)"> 
    45    <title>${project.name}: Ticket $title</title> 
    56    <link>${abs_href.ticket(ticket.id)}</link> 
     
    1314    <generator>Trac $trac.version</generator> 
    1415 
    1516    <item py:for="change in changes"> 
    16       <author py:if="change.author">$change.author</author> 
     17      <py:if test="change.author"> 
     18        <py:choose> 
     19          <author py:when="show_email_addresses">$change.author</author> 
     20          <dc:creator py:otherwise="">${obfuscate_email_address(change.author)}</dc:creator> 
     21        </py:choose> 
     22      </py:if> 
    1723      <pubDate>${http_date(change.date)}</pubDate> 
    1824      <title>$change.title</title> 
    1925      <link>${abs_href.ticket(ticket.id)}<py:if test="change.cnum">#comment:$change.cnum</py:if></link> 
     
    3844          </py:for> 
    3945          &lt;/ul&gt; 
    4046        </py:if> 
    41         ${unicode(abs_context.wiki_to_html(change.comment, absurls=True))} 
     47        ${unicode(abs_context.wiki_to_html(change.comment))} 
    4248      </description> 
    4349      <category>Ticket</category> 
    4450    </item> 
  • templates/attachment.html

     
    7676        <table id="info" summary="Description"> 
    7777          <tbody> 
    7878            <tr> 
    79               <th scope="col"> 
     79              <th scope="col" py:with="a=attachment.author"> 
    8080                File $attachment.filename, ${sizeinfo(attachment.size)} 
    81                 (added by $attachment.author,  ${dateinfo(attachment.date)} ago) 
     81                (added by ${show_email_addresses and a or obfuscate_email_address(a)},  ${dateinfo(attachment.date)} ago) 
    8282              </th> 
    8383            </tr> 
    8484            <tr> 
  • templates/wiki_diff.html

     
    4646        <dt class="property author">Author:</dt> 
    4747        <dd class="author" py:choose=""> 
    4848          <em py:when="multi" class="multi">(multiple changes)</em> 
    49           <py:otherwise>$change.author <span py:if="change.ipnr" class="ipnr">(IP: $change.ipnr)</span></py:otherwise> 
     49          <py:otherwise>${show_email_addresses and change.author or obfuscate_email_address(change.author)} <span py:if="change.ipnr" class="ipnr">(IP: $change.ipnr)</span></py:otherwise> 
    5050        </dd> 
    5151        <dt class="property message">Comment:</dt> 
    5252        <dd class="message" py:choose=""> 
  • templates/wiki_view.html

     
    4141        <table id="info" summary="Revision info"> 
    4242          <tbody> 
    4343            <tr><th scope="row"> 
    44               Version $page.version (modified by $page.author, ${dateinfo(page.time)} ago) 
     44                Version $page.version (modified by ${show_email_addresses and page.author or obfuscate_email_address(page.author)}, ${dateinfo(page.time)} ago) 
    4545            </th></tr> 
    4646            <tr><td class="message"> 
    4747              ${context.wiki_to_html(page.comment or '--')} 
  • templates/query_div.html

     
    5050                <td py:otherwise="" class="$name" py:choose=""> 
    5151                  <a py:when="name == 'summary'" href="$result.href" title="View ticket">$value</a> 
    5252                  <span py:when="isinstance(value, datetime)">${format_datetime(value)}</span> 
     53                  <span py:when="name in ('owner', 'reporter')">${show_email_addresses and value or obfuscate_email_address(value)}</span> 
    5354                  <span py:otherwise="">$value</span> 
    5455                </td> 
    5556              </py:with> 
  • templates/query.rss

     
    11<?xml version="1.0"?> 
    2 <rss version="2.0" xmlns:py="http://genshi.edgewall.org/"> 
     2<rss version="2.0" xmlns:py="http://genshi.edgewall.org/" 
     3                   xmlns:dc="http://purl.org/dc/elements/1.1/"> 
    34  <channel> 
    45    <title>$project.name: Ticket Query</title> 
    56    <link>$query_href</link> 
     
    1617      <guid isPermaLink="false">$href</guid> 
    1718      <title>#$result.id: $result.summary</title> 
    1819      <pubDate py:if="result.time">${http_date(result.time)}</pubDate> 
    19       <author py:if="result.reporter">$result.reporter</author> 
     20      <py:if test="result.reporter"> 
     21        <py:choose> 
     22          <author py:when="show_email_addresses">$result.reporter</author> 
     23          <dc:creator py:otherwise="">${obfuscate_email_address(result.reporter)}</dc:creator> 
     24        </py:choose> 
     25      </py:if> 
    2026      <description>${unicode(context('ticket', result.id, abs_urls=True).wiki_to_html(result.description))}</description> 
    2127      <category>Results</category> 
    2228      <comments>$href#changelog</comments> 
  • templates/ticket_diff.html

     
    5050        <dt class="property author">Author:</dt> 
    5151        <dd class="author" py:choose=""> 
    5252          <em py:when="multi" class="multi">(multiple changes)</em> 
    53           <py:otherwise>$change.author <span py:if="change.ipnr" class="ipnr">(IP: $change.ipnr)</span></py:otherwise> 
     53          <py:otherwise py:with="a=change.author">${show_email_addressses and a or obfuscate_email_address(a)} <span py:if="change.ipnr" class="ipnr">(IP: $change.ipnr)</span></py:otherwise> 
    5454        </dd> 
    5555        <dt class="property message">Comment:</dt> 
    5656        <dd class="message" py:choose="">