You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by br...@apache.org on 2019/03/12 21:45:30 UTC

[allura] 01/02: [#8270] rel=nofollow on any menu items going external; include current domain as exempt from nofollow

This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8270
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 253b4a6cafc67a3cd02ab0d8a09a6df9d2e46b45
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Tue Mar 12 17:14:51 2019 -0400

    [#8270] rel=nofollow on any menu items going external; include current domain as exempt from nofollow
---
 .../ext/user_profile/templates/sections/tools.html       |  4 ++--
 Allura/allura/lib/markdown_extensions.py                 |  8 +++-----
 Allura/allura/lib/utils.py                               |  9 ++++++++-
 Allura/allura/model/project.py                           |  5 ++++-
 Allura/allura/templates/jinja_master/top_nav.html        |  4 ++--
 Allura/allura/tests/test_utils.py                        | 16 ++++++++++++++++
 6 files changed, 35 insertions(+), 11 deletions(-)

diff --git a/Allura/allura/ext/user_profile/templates/sections/tools.html b/Allura/allura/ext/user_profile/templates/sections/tools.html
index 1a39e91..55aad35 100644
--- a/Allura/allura/ext/user_profile/templates/sections/tools.html
+++ b/Allura/allura/ext/user_profile/templates/sections/tools.html
@@ -28,11 +28,11 @@
     <ul>
     {% for tool in c.project.grouped_navbar_entries() %}
         <li>
-            <a href="{{tool.url}}">{{ tool.label }}</a>
+            <a href="{{tool.url}}" {{ tool.extra_html_attrs|xmlattr }}>{{ tool.label }}</a>
             {% if tool.children %}
             <ul>
             {% for child in tool.children %}
-                <li><a href="{{child.url}}">{{ child.label }}</a></li>
+                <li><a href="{{child.url}}" {{ child.extra_html_attrs|xmlattr }}>{{ child.label }}</a></li>
             {% endfor %}
             </ul>
             {% endif %}
diff --git a/Allura/allura/lib/markdown_extensions.py b/Allura/allura/lib/markdown_extensions.py
index d025590..09ff02a 100644
--- a/Allura/allura/lib/markdown_extensions.py
+++ b/Allura/allura/lib/markdown_extensions.py
@@ -32,7 +32,7 @@ import emoji
 from . import macro
 from . import helpers as h
 from allura import model as M
-from allura.lib.utils import ForgeHTMLSanitizerFilter
+from allura.lib.utils import ForgeHTMLSanitizerFilter, is_nofollow_url
 
 log = logging.getLogger(__name__)
 
@@ -473,10 +473,8 @@ class RelativeLinkRewriter(markdown.postprocessors.Postprocessor):
             val = val.replace(' ', '%20')
             tag[attr] = val
         if '://' in val:
-            for domain in re.split(r'\s*,\s*', config.get('nofollow_exempt_domains', '')):
-                if domain and domain in val:
-                    return
-            tag['rel'] = 'nofollow'
+            if is_nofollow_url(val):
+                tag['rel'] = 'nofollow'
             return
         if val.startswith('/'):
             return
diff --git a/Allura/allura/lib/utils.py b/Allura/allura/lib/utils.py
index e07323c..7198386 100644
--- a/Allura/allura/lib/utils.py
+++ b/Allura/allura/lib/utils.py
@@ -30,6 +30,7 @@ import magic
 from itertools import groupby
 import operator as op
 import collections
+from urlparse import urlparse
 
 import tg
 import emoji
@@ -792,4 +793,10 @@ def get_key_from_value(d, val):
     for k, v in d.items():
         if val in v:
             return k
-    return ''
\ No newline at end of file
+    return ''
+
+
+def is_nofollow_url(url):
+    url_domain = urlparse(url).hostname
+    ok_domains = re.split(r'\s*,\s*', tg.config.get('nofollow_exempt_domains', '')) + [tg.config['domain']]
+    return url_domain and url_domain not in ok_domains
diff --git a/Allura/allura/model/project.py b/Allura/allura/model/project.py
index 1a70914..8fa6167 100644
--- a/Allura/allura/model/project.py
+++ b/Allura/allura/model/project.py
@@ -33,7 +33,6 @@ import formencode as fe
 from webob import exc
 import PIL
 
-from allura.lib.decorators import memoize
 from ming import schema as S
 from ming.utils import LazyProperty
 from ming.orm import ThreadLocalORMSession
@@ -46,8 +45,10 @@ from allura.lib import plugin
 from allura.lib import exceptions
 from allura.lib import security
 from allura.lib import validators as v
+from allura.lib.decorators import memoize
 from allura.lib.security import has_access
 from allura.lib.search import SearchIndexable
+from allura.lib.utils import is_nofollow_url
 from allura.model.types import MarkdownCache
 
 from .session import main_orm_session
@@ -626,6 +627,8 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
                     entry = sm.bind_app(app)
                     entry.tool_name = ac.tool_name
                     entry.ui_icon = 'tool-%s' % entry.tool_name.lower()
+                    if is_nofollow_url(entry.url):
+                        entry.extra_html_attrs = {'rel': 'nofollow'}
                     if not self.is_nbhd_project and (entry.tool_name.lower() in anchored_tools.keys()):
                         ordinal = anchored_tools.keys().index(
                             entry.tool_name.lower())
diff --git a/Allura/allura/templates/jinja_master/top_nav.html b/Allura/allura/templates/jinja_master/top_nav.html
index ae8fefe..ac3727d 100644
--- a/Allura/allura/templates/jinja_master/top_nav.html
+++ b/Allura/allura/templates/jinja_master/top_nav.html
@@ -21,14 +21,14 @@
 <ul class="dropdown">
   {% for s in c.project.grouped_navbar_entries() %}
     <li class="{% if s.matches_url(request) %}selected{% endif %}">
-        <a href="{{s.url}}" class="tool-{{(s.tool_name or 'admin').lower()}}-32">
+        <a href="{{s.url}}" class="tool-{{(s.tool_name or 'admin').lower()}}-32" {{ s.extra_html_attrs|xmlattr }}>
             {{s.label}}
         </a>
         {% set grouped_tool_count = s.matching_urls|length %}
         {% if grouped_tool_count %}
             <ul>
                 {%for tool in s.children%}
-                    <li class="{% if tool.matches_url(request) %}selected{% endif %}"><a href="{{tool.url}}">{{tool.label}}</a></li>
+                    <li class="{% if tool.matches_url(request) %}selected{% endif %}"><a href="{{tool.url}}" {{ tool.extra_html_attrs|xmlattr }}>{{tool.label}}</a></li>
                 {%endfor%}
             </ul>
         {% endif %}
diff --git a/Allura/allura/tests/test_utils.py b/Allura/allura/tests/test_utils.py
index 0afc937..5f642a7 100644
--- a/Allura/allura/tests/test_utils.py
+++ b/Allura/allura/tests/test_utils.py
@@ -382,3 +382,19 @@ def unique_attachments():
     attachments = [pic1, file1, pic2, file2, pic2, other]
     expected = [file2, other, pic2]
     assert_equal(expected, ua(attachments))
+
+
+def test_is_nofollow_url():
+    with patch.dict(config, {'domain': 'localhost'}):
+        assert not utils.is_nofollow_url('relative/path')
+        assert not utils.is_nofollow_url('http://localhost/path')
+        assert utils.is_nofollow_url('http://google.com/')
+        assert utils.is_nofollow_url('https://google.com/')
+
+    with patch.dict(config, {'domain': 'localhost',
+                             'nofollow_exempt_domains': 'foo.com, bar.io'}):
+        assert utils.is_nofollow_url('http://google.com/')
+        assert utils.is_nofollow_url('http://xfoo.com/')
+        assert not utils.is_nofollow_url('http://foo.com/')
+        assert not utils.is_nofollow_url('http://bar.io/')
+        assert utils.is_nofollow_url('http://bar.iot/')