You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by tv...@apache.org on 2012/12/05 21:01:50 UTC

[3/12] git commit: [#5382] Enable Akismet spam-checking on discussion posts, logging result.

[#5382] Enable Akismet spam-checking on discussion posts, logging result.


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/a2cb16ab
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/a2cb16ab
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/a2cb16ab

Branch: refs/heads/tv/5382
Commit: a2cb16ab264dcc1c69428c85bd9a73ecc0f1ae86
Parents: 1cb7c1d
Author: Tim Van Steenburgh <tv...@gmail.com>
Authored: Fri Nov 30 23:20:26 2012 +0000
Committer: Tim Van Steenburgh <tv...@gmail.com>
Committed: Wed Dec 5 18:44:37 2012 +0000

----------------------------------------------------------------------
 Allura/allura/controllers/discuss.py     |    2 +
 Allura/allura/lib/app_globals.py         |   17 +++++
 Allura/allura/lib/spam/__init__.py       |    4 +
 Allura/allura/lib/spam/akismetservice.py |   26 ++++++++
 Allura/allura/tests/test_globals.py      |    1 +
 Allura/allura/tests/unit/test_spam.py    |   80 +++++++++++++++++++++++++
 requirements-sf.txt                      |    1 +
 7 files changed, 131 insertions(+), 0 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/a2cb16ab/Allura/allura/controllers/discuss.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/discuss.py b/Allura/allura/controllers/discuss.py
index 005169e..0faaeea 100644
--- a/Allura/allura/controllers/discuss.py
+++ b/Allura/allura/controllers/discuss.py
@@ -183,8 +183,10 @@ class ThreadController(BaseController):
         if not kw['text']:
             flash('Your post was not saved. You must provide content.', 'error')
             redirect(request.referer)
+
         file_info = kw.get('file_info', None)
         p = self.thread.add_post(**kw)
+        is_spam = g.spam_checker.check(kw['text'], artifact=p, user=c.user)
         if hasattr(file_info, 'file'):
             p.attach(
                 file_info.filename, file_info.file, content_type=file_info.type,

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/a2cb16ab/Allura/allura/lib/app_globals.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/app_globals.py b/Allura/allura/lib/app_globals.py
index a263177..bb8a94e 100644
--- a/Allura/allura/lib/app_globals.py
+++ b/Allura/allura/lib/app_globals.py
@@ -33,6 +33,7 @@ from allura.lib.markdown_extensions import ForgeExtension
 
 from allura.lib import gravatar, plugin, utils
 from allura.lib import helpers as h
+from allura.lib import spam
 from allura.lib.widgets import analytics
 from allura.lib.security import Credentials
 from allura.lib.async import Connection, MockAMQ
@@ -167,6 +168,22 @@ class Globals(object):
         self._zarkov = None
 
     @LazyProperty
+    def spam_checker(self):
+        """Return an Akismet spam checker if config defines an Akismet API key.
+        Otherwise, return a no-op spam checker.
+
+        Eventually we may support checkers for other services like Mollom and
+        Defensio.
+        """
+        akismet_key = config.get('spam.akismet_key')
+        if akismet_key:
+            checker = spam.akismetservice.Akismet(akismet_key, config.get('base_url'))
+            checker.verify_key()
+        else:
+            checker = spam.FakeSpamChecker()
+        return checker
+
+    @LazyProperty
     def director(self):
         """Return activitystream director"""
         if asbool(config.get('activitystream.recording.enabled', False)):

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/a2cb16ab/Allura/allura/lib/spam/__init__.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/spam/__init__.py b/Allura/allura/lib/spam/__init__.py
new file mode 100644
index 0000000..954cda1
--- /dev/null
+++ b/Allura/allura/lib/spam/__init__.py
@@ -0,0 +1,4 @@
+class FakeSpamChecker(object):
+    """No-op spam checker"""
+    def check(self, *args, **kw):
+        return False

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/a2cb16ab/Allura/allura/lib/spam/akismetservice.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/spam/akismetservice.py b/Allura/allura/lib/spam/akismetservice.py
new file mode 100644
index 0000000..d5768a0
--- /dev/null
+++ b/Allura/allura/lib/spam/akismetservice.py
@@ -0,0 +1,26 @@
+import logging
+
+from pylons import request
+from pylons import tmpl_context as c
+
+import akismet
+
+log = logging.getLogger(__name__)
+
+class Akismet(akismet.Akismet):
+    def check(self, text, artifact=None, user=None, content_type='comment', **kw):
+        log_msg = text
+        kw['comment_type'] = content_type
+        if artifact:
+            kw['permalink'] = artifact.url()
+            log_msg = artifact.url()
+        user = user or c.user
+        if user:
+            kw['comment_author'] = user.display_name or user.username
+            kw['comment_author_email'] = user.email_addresses[0] if user.email_addresses else ''
+        kw['user_ip'] = request.environ['REMOTE_ADDR']
+        kw['user_agent'] = request.environ['HTTP_USER_AGENT']
+        kw['referrer'] = request.environ['HTTP_REFERER']
+        res = self.comment_check(text, data=kw, build_data=False)
+        log.info("spam=%s (akismet): %s" % (str(res), log_msg))
+        return res

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/a2cb16ab/Allura/allura/tests/test_globals.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/test_globals.py b/Allura/allura/tests/test_globals.py
index 57f65d8..dbd9b06 100644
--- a/Allura/allura/tests/test_globals.py
+++ b/Allura/allura/tests/test_globals.py
@@ -1,5 +1,6 @@
 import re
 import os, allura
+from mock import patch
 from urllib import quote
 
 from bson import ObjectId

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/a2cb16ab/Allura/allura/tests/unit/test_spam.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/unit/test_spam.py b/Allura/allura/tests/unit/test_spam.py
new file mode 100644
index 0000000..1b169a9
--- /dev/null
+++ b/Allura/allura/tests/unit/test_spam.py
@@ -0,0 +1,80 @@
+import mock
+import unittest
+
+try:
+    from allura.lib.spam.akismetservice import Akismet
+except ImportError:
+    Akismet = None
+
+
+@unittest.skipIf(Akismet is None, "Can't import Akismet")
+class TestAkismet(unittest.TestCase):
+    def setUp(self):
+        self.akismet = Akismet()
+        self.akismet.comment_check = mock.Mock()
+        self.fake_artifact = mock.Mock(**{'url.return_value': 'artifact url'})
+        self.fake_user = mock.Mock(display_name='Some User',
+                email_addresses=['user@domain'])
+        self.fake_environ = dict(
+            REMOTE_ADDR='some ip',
+            HTTP_USER_AGENT='some browser',
+            HTTP_REFERER='some url')
+        self.expected_data = dict(
+            comment_type='comment',
+            user_ip='some ip',
+            user_agent='some browser',
+            referrer='some url')
+
+    @mock.patch('allura.lib.spam.akismetservice.c')
+    @mock.patch('allura.lib.spam.akismetservice.request')
+    def test_check(self, request, c):
+        request.environ = self.fake_environ
+        c.user = None
+        self.akismet.check('spam text')
+        self.akismet.comment_check.assert_called_once_with('spam text',
+                data=self.expected_data, build_data=False)
+
+    @mock.patch('allura.lib.spam.akismetservice.c')
+    @mock.patch('allura.lib.spam.akismetservice.request')
+    def test_check_with_explicit_content_type(self, request, c):
+        request.environ = self.fake_environ
+        c.user = None
+        self.akismet.check('spam text', content_type='some content type')
+        self.expected_data['comment_type'] = 'some content type'
+        self.akismet.comment_check.assert_called_once_with('spam text',
+                data=self.expected_data, build_data=False)
+
+    @mock.patch('allura.lib.spam.akismetservice.c')
+    @mock.patch('allura.lib.spam.akismetservice.request')
+    def test_check_with_artifact(self, request, c):
+        request.environ = self.fake_environ
+        c.user = None
+        self.akismet.check('spam text', artifact=self.fake_artifact)
+        expected_data = self.expected_data
+        expected_data['permalink'] = 'artifact url'
+        self.akismet.comment_check.assert_called_once_with('spam text',
+                data=expected_data, build_data=False)
+
+    @mock.patch('allura.lib.spam.akismetservice.c')
+    @mock.patch('allura.lib.spam.akismetservice.request')
+    def test_check_with_user(self, request, c):
+        request.environ = self.fake_environ
+        c.user = None
+        self.akismet.check('spam text', user=self.fake_user)
+        expected_data = self.expected_data
+        expected_data.update(comment_author='Some User',
+                comment_author_email='user@domain')
+        self.akismet.comment_check.assert_called_once_with('spam text',
+                data=expected_data, build_data=False)
+
+    @mock.patch('allura.lib.spam.akismetservice.c')
+    @mock.patch('allura.lib.spam.akismetservice.request')
+    def test_check_with_implicit_user(self, request, c):
+        request.environ = self.fake_environ
+        c.user = self.fake_user
+        self.akismet.check('spam text')
+        expected_data = self.expected_data
+        expected_data.update(comment_author='Some User',
+                comment_author_email='user@domain')
+        self.akismet.comment_check.assert_called_once_with('spam text',
+                data=expected_data, build_data=False)

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/a2cb16ab/requirements-sf.txt
----------------------------------------------------------------------
diff --git a/requirements-sf.txt b/requirements-sf.txt
index 79ac3bd..4305dde 100644
--- a/requirements-sf.txt
+++ b/requirements-sf.txt
@@ -1,5 +1,6 @@
 # requirements for the SF instance
 
+akismet==0.2.0
 amqplib==0.6.1
 kombu==1.0.4
 coverage==3.5a1-20110413