From b9b030fff193e2d3e0a8f538f868fbf493fa3e9f Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Thu, 1 Nov 2012 17:14:46 -0700 Subject: [PATCH] Refactoring anti-spam feature in comments --HG-- branch : 1.x extra : rebase_source : c24f16db4b03f676c261aa7a959f85ac2ac0a09c --- CREDITS.txt | 6 -- lib/joel.net.akismet/Joel.Net.Akismet.dll | Bin 7168 -> 0 bytes lib/joel.net.akismet/LICENSE.txt | 12 ---- .../Comments/Services/CommentServiceTests.cs | 14 ---- .../DefaultCheckSpamEventHandler.cs | 28 ++++++++ .../EventHandlers/ICheckSpamEventHandler.cs | 7 ++ .../Orchard.AntiSpam/Models/SpamStatus.cs | 7 +- .../Modules/Orchard.AntiSpam/Module.txt | 2 +- .../Orchard.AntiSpam/Orchard.AntiSpam.csproj | 6 ++ .../Services/DefaultSpamService.cs | 9 +++ .../Controllers/AdminController.cs | 1 - .../Controllers/CommentController.cs | 3 +- .../Drivers/CommentPartDriver.cs | 17 +++-- .../Drivers/MissingFilterBanner.cs | 39 ++++++++++ .../Models/CommentSettingsPart.cs | 10 --- .../Orchard.Comments/Orchard.Comments.csproj | 4 +- .../Services/CommentService.cs | 19 ++--- .../Services/CommentValidator.cs | 67 +++++------------- .../Services/ICheckSpamEventHandler.cs | 10 +++ .../Services/ICommentService.cs | 1 + .../Parts.Comments.SiteSettings.cshtml | 12 +--- 21 files changed, 142 insertions(+), 132 deletions(-) delete mode 100644 lib/joel.net.akismet/Joel.Net.Akismet.dll delete mode 100644 lib/joel.net.akismet/LICENSE.txt create mode 100644 src/Orchard.Web/Modules/Orchard.AntiSpam/EventHandlers/DefaultCheckSpamEventHandler.cs create mode 100644 src/Orchard.Web/Modules/Orchard.AntiSpam/EventHandlers/ICheckSpamEventHandler.cs create mode 100644 src/Orchard.Web/Modules/Orchard.Comments/Drivers/MissingFilterBanner.cs create mode 100644 src/Orchard.Web/Modules/Orchard.Comments/Services/ICheckSpamEventHandler.cs diff --git a/CREDITS.txt b/CREDITS.txt index b99ec8e31..208dd03da 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -7,12 +7,6 @@ The Outercurve Foundation (http://www.outercurve.org/). Orchard includes works distributed under the licenses listed below. The full text for most of the licenses listed below can be found in the LICENSE.txt file accompanying each work. The original copyright notices have been preserved within the respective files and or packages. Please refer to the specific files and/or packages for more detailed information about the authors, copyright notices, and licenses. -Akismet.Net ------ -Website: http://www.codeplex.com/wikipage?ProjectName=AkismetApi -Copyright: Copyright (c) 2006, Joel Thoms -License: New BSD - Antlr ----- Website: http://www.antlr.org/ diff --git a/lib/joel.net.akismet/Joel.Net.Akismet.dll b/lib/joel.net.akismet/Joel.Net.Akismet.dll deleted file mode 100644 index c6982d9807e61e9d5d7b991df779bd1b836d5ebe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7168 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.Id; - - Assert.That(_commentService.GetComment(commentId).Record.Author, Is.Null.Or.Empty); - - _commentService.UpdateComment(commentId, "test", "", "", "new text", CommentStatus.Pending); - - Assert.That(_commentService.GetComment(commentId).Record.Author, Is.EqualTo("test")); - } - [Test] public void CommentsShouldBePendingByDefault() { var commentedItem = _contentManager.New("commentedItem"); diff --git a/src/Orchard.Web/Modules/Orchard.AntiSpam/EventHandlers/DefaultCheckSpamEventHandler.cs b/src/Orchard.Web/Modules/Orchard.AntiSpam/EventHandlers/DefaultCheckSpamEventHandler.cs new file mode 100644 index 000000000..0518e0426 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.AntiSpam/EventHandlers/DefaultCheckSpamEventHandler.cs @@ -0,0 +1,28 @@ +using System.Linq; +using Orchard.AntiSpam.Models; +using Orchard.AntiSpam.Services; +using Orchard.AntiSpam.Settings; + +namespace Orchard.AntiSpam.EventHandlers { + public class DefaultCheckSpamEventHandler : ICheckSpamEventHandler { + private readonly ISpamService _spamService; + + public DefaultCheckSpamEventHandler(ISpamService spamService) { + _spamService = spamService; + } + + public void CheckSpam(dynamic context) { + if(!_spamService.GetSpamFilters().Any()) { + return; + } + + context.Checked = true; + + if(string.IsNullOrWhiteSpace(context.Text)) { + return; + } + + context.IsSpam = _spamService.CheckForSpam(context.Text, SpamFilterAction.One) == SpamStatus.Spam; + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.AntiSpam/EventHandlers/ICheckSpamEventHandler.cs b/src/Orchard.Web/Modules/Orchard.AntiSpam/EventHandlers/ICheckSpamEventHandler.cs new file mode 100644 index 000000000..18c64a131 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.AntiSpam/EventHandlers/ICheckSpamEventHandler.cs @@ -0,0 +1,7 @@ +using Orchard.Events; + +namespace Orchard.AntiSpam.EventHandlers { + public interface ICheckSpamEventHandler : IEventHandler { + void CheckSpam(dynamic context); + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.AntiSpam/Models/SpamStatus.cs b/src/Orchard.Web/Modules/Orchard.AntiSpam/Models/SpamStatus.cs index 881a65231..cb5ab4ac4 100644 --- a/src/Orchard.Web/Modules/Orchard.AntiSpam/Models/SpamStatus.cs +++ b/src/Orchard.Web/Modules/Orchard.AntiSpam/Models/SpamStatus.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; - -namespace Orchard.AntiSpam.Models { +namespace Orchard.AntiSpam.Models { public enum SpamStatus { Spam, Ham diff --git a/src/Orchard.Web/Modules/Orchard.AntiSpam/Module.txt b/src/Orchard.Web/Modules/Orchard.AntiSpam/Module.txt index 12443e9e4..7e0f680b5 100644 --- a/src/Orchard.Web/Modules/Orchard.AntiSpam/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.AntiSpam/Module.txt @@ -2,7 +2,7 @@ Name: AntiSpam AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net -Version: 1.6 +Version: 1.6.1 OrchardVersion: 1.0 Description: Provides anti-spam services to protect your content from malicious submissions. Features: diff --git a/src/Orchard.Web/Modules/Orchard.AntiSpam/Orchard.AntiSpam.csproj b/src/Orchard.Web/Modules/Orchard.AntiSpam/Orchard.AntiSpam.csproj index ede0a6a41..fd4892e2e 100644 --- a/src/Orchard.Web/Modules/Orchard.AntiSpam/Orchard.AntiSpam.csproj +++ b/src/Orchard.Web/Modules/Orchard.AntiSpam/Orchard.AntiSpam.csproj @@ -21,6 +21,10 @@ false + + + + true @@ -89,6 +93,8 @@ + + diff --git a/src/Orchard.Web/Modules/Orchard.AntiSpam/Services/DefaultSpamService.cs b/src/Orchard.Web/Modules/Orchard.AntiSpam/Services/DefaultSpamService.cs index 4c7eccd73..f41ed2ac2 100644 --- a/src/Orchard.Web/Modules/Orchard.AntiSpam/Services/DefaultSpamService.cs +++ b/src/Orchard.Web/Modules/Orchard.AntiSpam/Services/DefaultSpamService.cs @@ -26,6 +26,11 @@ namespace Orchard.AntiSpam.Services { } public SpamStatus CheckForSpam(string text, SpamFilterAction action) { + + if (string.IsNullOrWhiteSpace(text)) { + return SpamStatus.Ham; + } + var spamFilters = GetSpamFilters().ToList(); switch (action) { @@ -53,6 +58,10 @@ namespace Orchard.AntiSpam.Services { // evaluate the text to submit to the spam filters var text = _tokenizer.Replace(settings.Pattern, new Dictionary { { "Content", part.ContentItem } }); + if (string.IsNullOrWhiteSpace(text)) { + return SpamStatus.Ham; + } + var result = CheckForSpam(text, settings.Action); // trigger events and rules diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.Comments/Controllers/AdminController.cs index c31cf6563..53fc365ac 100644 --- a/src/Orchard.Web/Modules/Orchard.Comments/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Comments/Controllers/AdminController.cs @@ -13,7 +13,6 @@ using Orchard.UI.Navigation; using Orchard.UI.Notify; using Orchard.Comments.ViewModels; using Orchard.Comments.Services; -using Orchard.Utility.Extensions; namespace Orchard.Comments.Controllers { using Orchard.Settings; diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Controllers/CommentController.cs b/src/Orchard.Web/Modules/Orchard.Comments/Controllers/CommentController.cs index d0683ce64..092f3595d 100644 --- a/src/Orchard.Web/Modules/Orchard.Comments/Controllers/CommentController.cs +++ b/src/Orchard.Web/Modules/Orchard.Comments/Controllers/CommentController.cs @@ -1,5 +1,4 @@ -using System; -using System.Linq; +using System.Linq; using System.Web.Mvc; using Orchard.Comments.Models; using Orchard.Comments.Services; diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Drivers/CommentPartDriver.cs b/src/Orchard.Web/Modules/Orchard.Comments/Drivers/CommentPartDriver.cs index 4f2d381dd..7636cf75e 100644 --- a/src/Orchard.Web/Modules/Orchard.Comments/Drivers/CommentPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Comments/Drivers/CommentPartDriver.cs @@ -15,7 +15,7 @@ namespace Orchard.Comments.Drivers { private readonly IContentManager _contentManager; private readonly IWorkContextAccessor _workContextAccessor; private readonly IClock _clock; - private readonly ICommentService _commentService; + private readonly ICommentValidator _commentValidator; protected override string Prefix { get { return "Comments"; } } @@ -25,11 +25,12 @@ namespace Orchard.Comments.Drivers { IContentManager contentManager, IWorkContextAccessor workContextAccessor, IClock clock, - ICommentService commentService) { + ICommentService commentService, + ICommentValidator commentValidator) { _contentManager = contentManager; _workContextAccessor = workContextAccessor; _clock = clock; - _commentService = commentService; + _commentValidator = commentValidator; T = NullLocalizer.Instance; } @@ -43,7 +44,7 @@ namespace Orchard.Comments.Drivers { // GET protected override DriverResult Editor(CommentPart part, dynamic shapeHelper) { - if (Orchard.UI.Admin.AdminFilter.IsApplied(_workContextAccessor.GetContext().HttpContext.Request.RequestContext)) { + if (UI.Admin.AdminFilter.IsApplied(_workContextAccessor.GetContext().HttpContext.Request.RequestContext)) { return ContentShape("Parts_Comment_AdminEdit", () => shapeHelper.EditorTemplate(TemplateName: "Parts.Comment.AdminEdit", Model: part, Prefix: Prefix)); } @@ -64,7 +65,6 @@ namespace Orchard.Comments.Drivers { part.SiteName = "http://" + part.SiteName; } - // TODO: it's very bad how the corresponding user is stored. Needs revision. var currentUser = workContext.CurrentUser; part.UserName = (currentUser != null ? currentUser.UserName : null); @@ -72,8 +72,11 @@ namespace Orchard.Comments.Drivers { if (String.IsNullOrEmpty(part.Author)) updater.AddModelError("NameMissing", T("You didn't specify your name.")); - // TODO: needs spam handling - part.Status = workContext.CurrentSite.As().ModerateComments ? CommentStatus.Pending : CommentStatus.Approved; + // applying anti-spam filters + var moderateComments = workContext.CurrentSite.As().Record.ModerateComments; + part.Status = _commentValidator.ValidateComment(part) + ? moderateComments ? CommentStatus.Pending : CommentStatus.Approved + : CommentStatus.Spam; var commentedOn = _contentManager.Get(part.CommentedOn); if (commentedOn != null && commentedOn.Container != null) { diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Drivers/MissingFilterBanner.cs b/src/Orchard.Web/Modules/Orchard.Comments/Drivers/MissingFilterBanner.cs new file mode 100644 index 000000000..1366fa307 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Comments/Drivers/MissingFilterBanner.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; +using System.Dynamic; +using Orchard.Comments.Models; +using Orchard.Comments.Services; +using Orchard.ContentManagement; +using Orchard.Localization; +using Orchard.UI.Admin.Notification; +using Orchard.UI.Notify; + +namespace Orchard.Comments.Drivers { + public class MissingFilterBanner : INotificationProvider { + private readonly IOrchardServices _orchardServices; + private readonly ICheckSpamEventHandler _spamEventHandler; + + public MissingFilterBanner(IOrchardServices orchardServices, ICheckSpamEventHandler spamEventHandler) { + _orchardServices = orchardServices; + _spamEventHandler = spamEventHandler; + T = NullLocalizer.Instance; + } + + public Localizer T { get; set; } + + public IEnumerable GetNotifications() { + + var commentSettings = _orchardServices.WorkContext.CurrentSite.As(); + + dynamic context = new ExpandoObject(); + context.Checked = false; + context.IsSpam = false; + context.Text = string.Empty; + + _spamEventHandler.CheckSpam(context); + + if (commentSettings != null && commentSettings.EnableSpamProtection && !context.Checked) { + yield return new NotifyEntry {Message = T("Comments anti-spam protection requires at least one anti-spam filter to be enabled and configured."), Type = NotifyType.Warning}; + } + } + } +} diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Models/CommentSettingsPart.cs b/src/Orchard.Web/Modules/Orchard.Comments/Models/CommentSettingsPart.cs index 131fdf260..0940509d6 100644 --- a/src/Orchard.Web/Modules/Orchard.Comments/Models/CommentSettingsPart.cs +++ b/src/Orchard.Web/Modules/Orchard.Comments/Models/CommentSettingsPart.cs @@ -11,15 +11,5 @@ namespace Orchard.Comments.Models { get { return Record.EnableSpamProtection; } set { Record.EnableSpamProtection = value; } } - - public string AkismetKey { - get { return Record.AkismetKey; } - set { Record.AkismetKey = value; } - } - - public string AkismetUrl { - get { return Record.AkismetUrl; } - set { Record.AkismetUrl = value; } - } } } diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Orchard.Comments.csproj b/src/Orchard.Web/Modules/Orchard.Comments/Orchard.Comments.csproj index 2fcdebf17..64c2b448c 100644 --- a/src/Orchard.Web/Modules/Orchard.Comments/Orchard.Comments.csproj +++ b/src/Orchard.Web/Modules/Orchard.Comments/Orchard.Comments.csproj @@ -63,6 +63,7 @@ + @@ -72,6 +73,8 @@ + + @@ -94,7 +97,6 @@ - diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Services/CommentService.cs b/src/Orchard.Web/Modules/Orchard.Comments/Services/CommentService.cs index 0d161406f..997e8a057 100644 --- a/src/Orchard.Web/Modules/Orchard.Comments/Services/CommentService.cs +++ b/src/Orchard.Web/Modules/Orchard.Comments/Services/CommentService.cs @@ -1,31 +1,24 @@ -using System; -using System.Linq; -using JetBrains.Annotations; +using JetBrains.Annotations; using Orchard.Comments.Models; -using Orchard.ContentManagement.Aspects; -using Orchard.Data; using Orchard.Logging; using Orchard.ContentManagement; -using Orchard.Services; namespace Orchard.Comments.Services { [UsedImplicitly] public class CommentService : ICommentService { - private readonly IClock _clock; - private readonly ICommentValidator _commentValidator; private readonly IOrchardServices _orchardServices; - public CommentService(IClock clock, - ICommentValidator commentValidator, - IOrchardServices orchardServices) { - _clock = clock; - _commentValidator = commentValidator; + public CommentService(IOrchardServices orchardServices) { _orchardServices = orchardServices; Logger = NullLogger.Instance; } public ILogger Logger { get; set; } + public CommentPart GetComment(int id) { + return _orchardServices.ContentManager.Get(id); + } + public IContentQuery GetComments() { return _orchardServices.ContentManager .Query(); diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Services/CommentValidator.cs b/src/Orchard.Web/Modules/Orchard.Comments/Services/CommentValidator.cs index a76fc18d5..92128aa67 100644 --- a/src/Orchard.Web/Modules/Orchard.Comments/Services/CommentValidator.cs +++ b/src/Orchard.Web/Modules/Orchard.Comments/Services/CommentValidator.cs @@ -1,61 +1,30 @@ -using System; -using System.Web; -using JetBrains.Annotations; +using System.Dynamic; using Orchard.Comments.Models; -using Orchard.ContentManagement; -using Orchard.Localization; -using Orchard.Logging; -using Orchard.UI.Notify; -using Joel.Net; namespace Orchard.Comments.Services { - //This uses an akismet api implementation from http://akismetapi.codeplex.com/ - //Since the implementation is trivial, it may make sense to implement it to reduce dependencies. - [UsedImplicitly] - public class AkismetCommentValidator : ICommentValidator { - private readonly INotifier _notifer; - private readonly IOrchardServices _orchardServices; + public class AntiSpamFilterValidator : ICommentValidator { + private readonly ICheckSpamEventHandler _spamEventHandler; - public AkismetCommentValidator(INotifier notifier, IOrchardServices orchardServices) { - _notifer = notifier; - _orchardServices = orchardServices; - Logger = NullLogger.Instance; - T = NullLocalizer.Instance; + public AntiSpamFilterValidator(ICheckSpamEventHandler spamEventHandler) { + _spamEventHandler = spamEventHandler; } - public ILogger Logger { get; set; } - public Localizer T { get; set; } - public bool ValidateComment(CommentPart commentPart) { - CommentSettingsPartRecord commentSettingsPartRecord = _orchardServices.WorkContext.CurrentSite.As().Record; - string akismetKey = commentSettingsPartRecord.AkismetKey; - string akismetUrl = commentSettingsPartRecord.AkismetUrl; - bool enableSpamProtection = commentSettingsPartRecord.EnableSpamProtection; - if (enableSpamProtection == false) { - return true; - } - if (String.IsNullOrEmpty(akismetKey)) { - _notifer.Information(T("Please configure your Akismet key for spam protection")); - return true; - } - if (String.IsNullOrEmpty(akismetUrl)) { - akismetUrl = "http://www.orchardproject.net"; - } - Akismet akismetApi = new Akismet(akismetKey, akismetUrl, null); - AkismetComment akismetComment = new AkismetComment { - CommentAuthor = commentPart.Record.Author, - CommentAuthorEmail = commentPart.Record.Email, - Blog = akismetUrl, - CommentAuthorUrl = commentPart.Record.SiteName, - CommentContent = commentPart.Record.CommentText, - UserAgent = HttpContext.Current.Request.UserAgent, - }; + // true == spam - if (akismetApi.VerifyKey()) { - return !akismetApi.CommentCheck(akismetComment); // CommentCheck returning true == spam - } + var text = commentPart.Author + System.Environment.NewLine + + commentPart.CommentText + System.Environment.NewLine + + commentPart.Email + System.Environment.NewLine + + commentPart.SiteName + System.Environment.NewLine; - return false; + dynamic context = new ExpandoObject(); + context.Checked = false; + context.IsSpam = false; + context.Text = text; + + _spamEventHandler.CheckSpam(context); + + return context.IsSpam; } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Services/ICheckSpamEventHandler.cs b/src/Orchard.Web/Modules/Orchard.Comments/Services/ICheckSpamEventHandler.cs new file mode 100644 index 000000000..3d2731940 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Comments/Services/ICheckSpamEventHandler.cs @@ -0,0 +1,10 @@ +using Orchard.Events; + +namespace Orchard.Comments.Services { + /// + /// Stub interface for Orchard.AntiSpam.EventHandlers.ISpamEventHandler + /// + public interface ICheckSpamEventHandler : IEventHandler { + void CheckSpam(dynamic context); + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Services/ICommentService.cs b/src/Orchard.Web/Modules/Orchard.Comments/Services/ICommentService.cs index 540babe99..50b1d04f8 100644 --- a/src/Orchard.Web/Modules/Orchard.Comments/Services/ICommentService.cs +++ b/src/Orchard.Web/Modules/Orchard.Comments/Services/ICommentService.cs @@ -7,6 +7,7 @@ namespace Orchard.Comments.Services { IContentQuery GetComments(CommentStatus status); IContentQuery GetCommentsForCommentedContent(int id); IContentQuery GetCommentsForCommentedContent(int id, CommentStatus status); + CommentPart GetComment(int id); ContentItemMetadata GetDisplayForCommentedContent(int id); ContentItem GetCommentedContent(int id); void ApproveComment(int commentId); diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Views/EditorTemplates/Parts.Comments.SiteSettings.cshtml b/src/Orchard.Web/Modules/Orchard.Comments/Views/EditorTemplates/Parts.Comments.SiteSettings.cshtml index 8241a99c8..a31b2fb97 100644 --- a/src/Orchard.Web/Modules/Orchard.Comments/Views/EditorTemplates/Parts.Comments.SiteSettings.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Comments/Views/EditorTemplates/Parts.Comments.SiteSettings.cshtml @@ -6,20 +6,12 @@ @Html.EditorFor(m => m.ModerateComments) @Html.ValidationMessage("ModerateComments", "*") + @T("Check if you want to manually approve comments before they can be displayed.")
@Html.EditorFor(m => m.EnableSpamProtection) @Html.ValidationMessage("EnableSpamProtection", "*") -
-
- - @Html.EditorFor(m => m.AkismetKey) - @Html.ValidationMessage("AkismetKey", "*") -
-
- - @Html.EditorFor(m => m.AkismetUrl) - @Html.ValidationMessage("AkismetUrl", "*") + @T("Check to use an anti-spam filter on incoming comments. This requires that you have also enabled an actual filter like Akismet or Typepad.")
\ No newline at end of file