def _link_tickets(self, req, tickets): items = [] for i, word in enumerate(re.split(r'([;,\s]+)', tickets)): if i % 2: items.append(word) elif word: tid = word word = '#%s' % word try: ticket = Ticket(self.env, tid) if 'TICKET_VIEW' in req.perm(ticket.resource): word = \ html.a( '#%s' % ticket.id, href=req.href.ticket(ticket.id), class_=classes(ticket['status'], 'ticket'), title=get_resource_summary(self.env, ticket.resource) ) except ResourceNotFound: pass items.append(word) if items: return html(items) else: return None
def post_process_request(self, req, template, data, content_type): if template is not None: if req.path_info.startswith('/ticket/'): # In case of an invalid ticket, the data is invalid if not data: return template, data, content_type tkt = data['ticket'] links = TicketLinks(self.env, tkt) for i in links.blocked_by: if Ticket(self.env, i)['status'] != 'closed': add_script(req, 'mastertickets/js/disable_resolve.js') break # Add link to depgraph if needed. if links: add_ctxtnav(req, 'Depgraph', req.href.depgraph('ticket', tkt.id)) for change in data.get('changes', {}): if 'fields' not in change: continue for field, field_data in change['fields'].iteritems(): if field in self.fields: if field_data['new'].strip(): new = to_int_set(field_data['new']) else: new = set() if field_data['old'].strip(): old = to_int_set(field_data['old']) else: old = set() add = new - old sub = old - new elms = html() if add: elms.append( html.em(u', '.join( unicode(n) for n in sorted(add)))) elms.append(u' added') if add and sub: elms.append(u'; ') if sub: elms.append( html.em(u', '.join( unicode(n) for n in sorted(sub)))) elms.append(u' removed') field_data['rendered'] = elms # Add a link to generate a dependency graph for all the tickets # in the milestone if req.path_info.startswith('/milestone/'): if not data: return template, data, content_type milestone = data['milestone'] add_ctxtnav(req, 'Depgraph', req.href.depgraph('milestone', milestone.name)) return template, data, content_type
def render_ticket_action_control(self, req, ticket, action): """Returns the action control""" actions = ConfigurableTicketWorkflow(self.env).actions label = actions[action]['label'] hint = _("The '%(field)s' field will be set to '%(username)s'.", field=self._field_name(action, ticket), username=req.authname) control = html('') return (label, control, hint)
def render_ticket_action_control(self, req, ticket, action): """Returns the action control""" actions = ConfigurableTicketWorkflow(self.env).actions label = actions[action]['label'] fields = ["'%s'" % x for x in self._field_names(action, ticket)] hint = ngettext("The %(fields)s field will be cleared.", "The %(fields)s fields will be cleared.", len(fields), fields=', '.join(fields)) control = html('') return (label, control, hint)
def render_timeline_event(self, context, field, event): # Decompose event data. id = event[3] # Return appropriate content. resource = Resource('downloads', id) if field == 'url': if 'DOWNLOADS_VIEW' in context.req.perm(resource): return get_resource_url(self.env, resource, context.req.href) else: return '#' elif field == 'title': return html('New download ', html.em(get_resource_name(self.env, resource)), ' created') elif field == 'description': return get_resource_description(self.env, resource, 'summary')
def process_request(self, req): if req.path_info.startswith('/xlogin') and req.authname == 'anonymous': raise TracError(html("Authentication information not available.")) if req.path_info.startswith('/xlogin'): if not req.remote_user: req.redirect(self.env.abs_href()) return if req.args.get('goto'): req.redirect(self.env.abs_href() + "/" + req.args.get('goto')) else: req.redirect(self.env.abs_href()) pass pass elif req.path_info.startswith('/logout'): auth.LoginModule._do_logout(self, req) self._redirect_back(req) pass
def filter_stream(self, req, method, filename, stream, data): if filename == 'wiki_edit.html' and 'section' in req.args and 'merge' not in req.args: if 'section_text' in req.args: section_pre, section_text, section_post = req.args.get('section_pre'), req.args.get('section_text'), req.args.get('section_post') else: section_pre, section_text, section_post = self._split_page_text(data['page'].text, req.args['section']) section_text = ''.join(section_text) section_element = html.input(type='hidden', name='section', id='section', value=req.args.get('section')) pre_element = html.input(type='hidden', name='section_pre', id='section_pre', value=''.join(section_pre)) post_element = html.input(type='hidden', name='section_post', id='section_post', value=''.join(section_post)) section_html = html(section_element, pre_element, post_element) stream = stream | Transformer('//textarea[@name="text"]').empty().append(section_text).before(section_html) stream = stream | Transformer('//div[@id="content"]//h1').append("/%s (section %s)"%(section_text[:section_text.find('\n')].strip(" = \r\n"), req.args['section'])) if not self.preview_whole_page: stream = stream | Transformer('//div[@class="wikipage"]').empty().append(HTML(wiki_to_html(section_text, self.env, req))) return stream
def _do_login(self, req): """Log the remote user in. This function expects to be called when the remote user name is available. The user name is inserted into the `auth_cookie` table and a cookie identifying the user on subsequent requests is sent back to the client. If the Authenticator was created with `ignore_case` set to true, then the authentication name passed from the web server in req.remote_user will be converted to lower case before being used. This is to avoid problems on installations authenticating against Windows which is not case sensitive regarding user names and domain names """ if not req.remote_user: raise TracError( html( u"Pas d'information d'authentification disponible. " u"Merci de vous référer à la ", html.a(u"documentation d'installation", title="Configuration de l'authentification", href=req.href.wiki('TracInstall') + "#ConfiguringAuthentication"), ".")) remote_user = req.remote_user if self.ignore_case: remote_user = remote_user.lower() assert req.authname in ('anonymous', remote_user), \ u'Déjà connecté sous %s.' % req.authname cookie = hex_entropy() db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute( "INSERT INTO auth_cookie (cookie,name,ipnr,time) " "VALUES (%s, %s, %s, %s)", (cookie, remote_user, req.remote_addr, int(time.time()))) db.commit() req.authname = remote_user req.outcookie['trac_auth'] = cookie req.outcookie['trac_auth']['path'] = req.href()
def _do_login(self, req): """Log the remote user in. This function expects to be called when the remote user name is available. The user name is inserted into the `auth_cookie` table and a cookie identifying the user on subsequent requests is sent back to the client. If the Authenticator was created with `ignore_case` set to true, then the authentication name passed from the web server in req.remote_user will be converted to lower case before being used. This is to avoid problems on installations authenticating against Windows which is not case sensitive regarding user names and domain names """ if not req.remote_user: raise TracError(html("Authentication information not available. " "Please refer to the ", html.a('installation documentation', title="Configuring Authentication", href=req.href.wiki('TracInstall') + "#ConfiguringAuthentication"), ".")) remote_user = req.remote_user if self.ignore_case: remote_user = remote_user.lower() assert req.authname in ('anonymous', remote_user), \ 'Already logged in as %s.' % req.authname cookie = hex_entropy() db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute("INSERT INTO auth_cookie (cookie,name,ipnr,time) " "VALUES (%s, %s, %s, %s)", (cookie, remote_user, req.remote_addr, int(time.time()))) db.commit() req.authname = remote_user req.outcookie['trac_auth'] = cookie req.outcookie['trac_auth']['path'] = req.href()
def filter_stream(self, req, method, filename, stream, data): if filename == 'wiki_edit.html' and 'section' in req.args and 'merge' not in req.args: if 'section_text' in req.args: section_pre, section_text, section_post = req.args.get( 'section_pre'), req.args.get('section_text'), req.args.get( 'section_post') else: section_pre, section_text, section_post = self._split_page_text( data['page'].text, req.args['section']) section_text = ''.join(section_text) section_element = html.input(type='hidden', name='section', id='section', value=req.args.get('section')) pre_element = html.input(type='hidden', name='section_pre', id='section_pre', value=''.join(section_pre)) post_element = html.input(type='hidden', name='section_post', id='section_post', value=''.join(section_post)) section_html = html(section_element, pre_element, post_element) stream = stream | Transformer('//textarea[@name="text"]').empty( ).append(section_text).before(section_html) stream = stream | Transformer('//div[@id="content"]//h1').append( "/%s (section %s)" % (section_text[:section_text.find('\n')].strip(" = \r\n"), req.args['section'])) if not self.preview_whole_page: stream = stream | Transformer( '//div[@class="wikipage"]').empty().append( HTML(wiki_to_html(section_text, self.env, req))) return stream
def _get_menu(self, req, menu_name, nav_orig): config_menu, config_options = self._get_config_menus(req, menu_name) menu_orig = nav_orig.get(menu_name, []) hide_if_no_children = [] menu_result = [] if 'inherit' in config_options: menu_orig += nav_orig.get(config_options['inherit'], []) tree_menu = {} for option in sorted( menu_orig + [{ 'name': key } for key in config_menu.keys()], key=lambda x: int( config_menu.get(x['name'], {}).get('order', 999))): name = option['name'] if 'visited' in tree_menu.get(name, []) \ or (config_menu.get(name, {}).get('enabled', True)==False and not 'active' in option)\ or config_menu.get(name, {}).get('if_path_info', True)==False \ or False in [req.perm.has_permission(perm) for perm in config_menu.get(name, {}).get('perm', [])]: continue tree_node = tree_menu.setdefault(name, {}) tree_node.update(option.copy()) if 'label' in option and 'label' in config_menu.get(name, []): del config_menu[name]['label'] tree_node.update( config_menu.get(name, {'parent_name': 'unassigned'})) if tree_node.get('hide_if_no_children'): hide_if_no_children.append(tree_node) tree_node['label'] = html( tree_node.setdefault('label', html.a(name))) tree_node['visited'] = True if tree_node.get('href'): tree_node_href = urlsplit(tree_node['href']) tree_node.setdefault( 'active', tree_node_href[2] == req.path_info and tree_node_href[3] in req.environ['QUERY_STRING']) if '_tmp_children' in tree_node: tree_node['children'] = html.ul() tree_node['label'].append(tree_node['children']) tree_node['children'].children.extend( tree_node['_tmp_children']) del tree_node['_tmp_children'] if (tree_node['parent_name']=='unassigned' and not 'unassigned' in config_menu) \ or tree_node['parent_name']=='top': menu_result.append(tree_node) continue tree_node['parent'] = tree_menu.setdefault( tree_node['parent_name'], {}) child_node = html.li( class_=tree_node.get('active') == True and 'active' or None) tree_node['outter_html'] = child_node child_node.children = [tree_node['label']] if 'label' in tree_node['parent']: if not 'children' in tree_node['parent']: tree_node['parent']['children'] = html.ul() tree_node['parent']['label'].append( tree_node['parent']['children']) tree_node['parent']['children'].append(child_node) else: tree_node['parent'].setdefault('_tmp_children', []).append(child_node) for hide_node in hide_if_no_children: if not hide_node.get('children'): if hide_node['parent_name'] == 'top': pos = menu_result.index(hide_node) del menu_result[pos] else: pos = hide_node['parent']['children'].children.index( hide_node['outter_html']) del hide_node['parent']['children'].children[pos] return menu_result
def _get_menu(self, req, menu_name, nav_orig): config_menu, config_options = self._get_config_menus(req, menu_name) menu_orig = nav_orig.get(menu_name, []) hide_if_no_children = [] menu_result = [] if 'inherit' in config_options: menu_orig += nav_orig.get(config_options['inherit'], []) order = 900 menu_items = config_menu for item in menu_orig: order += 1 name = item['name'] item.update({ 'has_original': True, 'order': order, }) if name in menu_items: # update original with configured item.update(menu_items[name]) menu_items[name] = item tree_menu={} active_subitem = None active_top = None href_path = req.href(req.path_info) for name in sorted(menu_items.keys(), key=lambda n: int(menu_items[n].get('order', 999))): item = menu_items[name] if (item.get('enabled', True)==False and not 'active' in item)\ or item.get('if_path_info', True)==False \ or ( item.get('hide_if_no_original', False) and not item.get('has_original') )\ or False in [req.perm.has_permission(perm) for perm in item.get('perm', [])]: continue tree_node = tree_menu.setdefault(name, {}) tree_node.update(item.copy()) tree_node.setdefault('parent_name', 'unassigned') if tree_node.get('hide_if_no_children'): hide_if_no_children.append(tree_node) if tree_node.get('href'): tree_node_href = urlsplit(tree_node['href']) tree_node.setdefault('active', tree_node_href[2].rstrip('/') == href_path and \ tree_node_href[3] == req.query_string) if not tree_node.get('has_original'): if tree_node.get('href'): label_href = tree_node['href'] else: label_href = '#' label_text = tree_node.get('label_text', name) tree_node['label'] = html.a(label_text, href=label_href) tree_node['label'] = html(tree_node['label']) if '_tmp_children' in tree_node: tree_node['children'] = html.ul() tree_node['label'].append(tree_node['children']) tree_node['children'].children.extend(tree_node['_tmp_children']) del tree_node['_tmp_children'] if (tree_node['parent_name']=='unassigned' and not 'unassigned' in config_menu) \ or tree_node['parent_name']=='top': if not active_top and tree_node.get('active'): active_top = tree_node else: tree_node['active'] = False menu_result.append(tree_node) continue # else working with subitems tree_node['parent'] = tree_menu.setdefault(tree_node['parent_name'], {}) if not active_subitem and tree_node.get('active'): active_subitem = tree_node active_top = tree_node['parent'] child_node = html.li() tree_node['outter_html'] = child_node child_node.children=[tree_node['label']] if 'label' in tree_node['parent']: if not 'children' in tree_node['parent']: tree_node['parent']['children'] = html.ul() tree_node['parent']['label'].append(tree_node['parent']['children']) tree_node['parent']['children'].append(child_node) else: tree_node['parent'].setdefault('_tmp_children',[]).append(child_node) for hide_node in hide_if_no_children: if not hide_node.get('children'): if hide_node['parent_name']=='top': pos = menu_result.index(hide_node) del menu_result[pos] else: pos = hide_node['parent']['children'].children.index(hide_node['outter_html']) del hide_node['parent']['children'].children[pos] if active_top: active_name = active_top['name'] for item in menu_result: if item['name'] == active_name: item['active'] = True break return menu_result
def _get_menu(self, req, menu_name, nav_orig): config_menu, config_options = self._get_config_menus(req, menu_name) menu_orig = nav_orig.get(menu_name, []) hide_if_no_children = [] menu_result = [] if "inherit" in config_options: menu_orig += nav_orig.get(config_options["inherit"], []) tree_menu = {} for option in sorted( menu_orig + [{"name": key} for key in config_menu.keys()], key=lambda x: int(config_menu.get(x["name"], {}).get("order", 999)), ): name = option["name"] if ( "visited" in tree_menu.get(name, []) or (config_menu.get(name, {}).get("enabled", True) == False and not "active" in option) or config_menu.get(name, {}).get("if_path_info", True) == False or False in [req.perm.has_permission(perm) for perm in config_menu.get(name, {}).get("perm", [])] ): continue tree_node = tree_menu.setdefault(name, {}) tree_node.update(option.copy()) if "label" in option and "label" in config_menu.get(name, []): del config_menu[name]["label"] tree_node.update(config_menu.get(name, {"parent_name": "unassigned"})) if tree_node.get("hide_if_no_children"): hide_if_no_children.append(tree_node) tree_node["label"] = html(tree_node.setdefault("label", html.a(name))) tree_node["visited"] = True if tree_node.get("href"): tree_node_href = urlsplit(tree_node["href"]) tree_node.setdefault( "active", tree_node_href[2] == req.path_info and tree_node_href[3] in req.environ["QUERY_STRING"] ) if "_tmp_children" in tree_node: tree_node["children"] = html.ul() tree_node["label"].append(tree_node["children"]) tree_node["children"].children.extend(tree_node["_tmp_children"]) del tree_node["_tmp_children"] if (tree_node["parent_name"] == "unassigned" and not "unassigned" in config_menu) or tree_node[ "parent_name" ] == "top": menu_result.append(tree_node) continue tree_node["parent"] = tree_menu.setdefault(tree_node["parent_name"], {}) child_node = html.li(class_=tree_node.get("active") == True and "active" or None) tree_node["outter_html"] = child_node child_node.children = [tree_node["label"]] if "label" in tree_node["parent"]: if not "children" in tree_node["parent"]: tree_node["parent"]["children"] = html.ul() tree_node["parent"]["label"].append(tree_node["parent"]["children"]) tree_node["parent"]["children"].append(child_node) else: tree_node["parent"].setdefault("_tmp_children", []).append(child_node) for hide_node in hide_if_no_children: if not hide_node.get("children"): if hide_node["parent_name"] == "top": pos = menu_result.index(hide_node) del menu_result[pos] else: pos = hide_node["parent"]["children"].children.index(hide_node["outter_html"]) del hide_node["parent"]["children"].children[pos] return menu_result
def post_process_request(self, req, template, data, content_type): if template is not None: if req.path_info.startswith('/ticket/'): # In case of an invalid ticket, the data is invalid if not data: return template, data, content_type tkt = data['ticket'] links = TicketLinks(self.env, tkt) for i in links.blocked_by: if Ticket(self.env, i)['status'] != 'closed': add_script(req, 'mastertickets/js/disable_resolve.js') break # Add link to depgraph if needed. if links: add_ctxtnav(req, 'Depgraph', req.href.depgraph('ticket', tkt.id)) for change in data.get('changes', {}): if 'fields' not in change: continue for field, field_data in change['fields'].iteritems(): if field in self.fields: if field_data['new'].strip(): new = to_int_set(field_data['new']) else: new = set() if field_data['old'].strip(): old = to_int_set(field_data['old']) else: old = set() add = new - old sub = old - new elms = html() if add: elms.append( html.em(u', '.join(unicode(n) for n in sorted(add))) ) elms.append(u' added') if add and sub: elms.append(u'; ') if sub: elms.append( html.em(u', '.join(unicode(n) for n in sorted(sub))) ) elms.append(u' removed') field_data['rendered'] = elms # Add a link to generate a dependency graph for all the tickets # in the milestone if req.path_info.startswith('/milestone/'): if not data: return template, data, content_type milestone = data['milestone'] add_ctxtnav(req, 'Depgraph', req.href.depgraph('milestone', milestone.name)) return template, data, content_type