Return-Path: X-Original-To: apmail-incubator-allura-commits-archive@minotaur.apache.org Delivered-To: apmail-incubator-allura-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id A485ADDEB for ; Fri, 14 Dec 2012 15:03:36 +0000 (UTC) Received: (qmail 52016 invoked by uid 500); 14 Dec 2012 15:03:36 -0000 Delivered-To: apmail-incubator-allura-commits-archive@incubator.apache.org Received: (qmail 51863 invoked by uid 500); 14 Dec 2012 15:03:36 -0000 Mailing-List: contact allura-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: allura-dev@incubator.apache.org Delivered-To: mailing list allura-commits@incubator.apache.org Received: (qmail 50763 invoked by uid 99); 14 Dec 2012 15:03:30 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 14 Dec 2012 15:03:30 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 4498281C8A1; Fri, 14 Dec 2012 15:03:30 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: tvansteenburgh@apache.org To: allura-commits@incubator.apache.org X-Mailer: ASF-Git Admin Mailer Subject: [44/50] git commit: [#5382] Enable Akismet spam-checking on discussion posts, logging result. Message-Id: <20121214150330.4498281C8A1@tyr.zones.apache.org> Date: Fri, 14 Dec 2012 15:03:30 +0000 (UTC) [#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/d4c9a4e5 Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/d4c9a4e5 Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/d4c9a4e5 Branch: refs/heads/ph/4655 Commit: d4c9a4e5ff67b0f07f9115fa1c31d2fc13853c7b Parents: 1f77144 Author: Tim Van Steenburgh Authored: Fri Nov 30 23:20:26 2012 +0000 Committer: Cory Johns Committed: Tue Dec 11 21:43:25 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/d4c9a4e5/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/d4c9a4e5/Allura/allura/lib/app_globals.py ---------------------------------------------------------------------- diff --git a/Allura/allura/lib/app_globals.py b/Allura/allura/lib/app_globals.py index ac46d90..8ae87f3 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/d4c9a4e5/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/d4c9a4e5/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/d4c9a4e5/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/d4c9a4e5/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/d4c9a4e5/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