Commit 44627b4a898e59f5a5082404e65bc09a19b65a88
1 parent
688b3512
Exists in
master
and in
22 other branches
use anti_spam plugin in suggest_articles
ActionItem2691
Showing
26 changed files
with
544 additions
and
58 deletions
Show diff stats
app/controllers/my_profile/cms_controller.rb
| ... | ... | @@ -267,7 +267,10 @@ class CmsController < MyProfileController |
| 267 | 267 | @back_to = params[:back_to] || request.referer || url_for(profile.public_profile_url) |
| 268 | 268 | @task = SuggestArticle.new(params[:task]) |
| 269 | 269 | if request.post? |
| 270 | - @task.target = profile | |
| 270 | + @task.target = profile | |
| 271 | + @task.ip_address = request.remote_ip | |
| 272 | + @task.user_agent = request.user_agent | |
| 273 | + @task.referrer = request.referrer | |
| 271 | 274 | if verify_recaptcha(:model => @task, :message => _('Please type the words correctly')) && @task.save |
| 272 | 275 | session[:notice] = _('Thanks for your suggestion. The community administrators were notified.') |
| 273 | 276 | redirect_to @back_to | ... | ... |
app/controllers/my_profile/profile_editor_controller.rb
| ... | ... | @@ -4,7 +4,7 @@ class ProfileEditorController < MyProfileController |
| 4 | 4 | protect 'destroy_profile', :profile, :only => [:destroy_profile] |
| 5 | 5 | |
| 6 | 6 | def index |
| 7 | - @pending_tasks = Task.to(profile).pending.select{|i| user.has_permission?(i.permission, profile)} | |
| 7 | + @pending_tasks = Task.to(profile).pending.without_spam.select{|i| user.has_permission?(i.permission, profile)} | |
| 8 | 8 | end |
| 9 | 9 | |
| 10 | 10 | helper :profile | ... | ... |
app/controllers/my_profile/spam_controller.rb
| ... | ... | @@ -14,9 +14,15 @@ class SpamController < MyProfileController |
| 14 | 14 | if params[:remove_comment] |
| 15 | 15 | profile.comments_received.find(params[:remove_comment]).destroy |
| 16 | 16 | end |
| 17 | + if params[:remove_task] | |
| 18 | + Task.to(profile).find_by_id(params[:remove_task]).destroy | |
| 19 | + end | |
| 17 | 20 | if params[:mark_comment_as_ham] |
| 18 | 21 | profile.comments_received.find(params[:mark_comment_as_ham]).ham! |
| 19 | 22 | end |
| 23 | + if params[:mark_task_as_ham] && (t = Task.to(profile).find_by_id(params[:mark_task_as_ham])) | |
| 24 | + t.ham! | |
| 25 | + end | |
| 20 | 26 | if request.xhr? |
| 21 | 27 | json_response(true) |
| 22 | 28 | else |
| ... | ... | @@ -28,7 +34,8 @@ class SpamController < MyProfileController |
| 28 | 34 | return |
| 29 | 35 | end |
| 30 | 36 | |
| 31 | - @spam = profile.comments_received.spam.paginate({:page => params[:page]}) | |
| 37 | + @comment_spam = profile.comments_received.spam.paginate({:page => params[:comments_page]}) | |
| 38 | + @task_spam = Task.to(profile).spam.paginate({:page => params[:tasks_page]}) | |
| 32 | 39 | end |
| 33 | 40 | |
| 34 | 41 | protected | ... | ... |
app/controllers/my_profile/tasks_controller.rb
| ... | ... | @@ -4,12 +4,12 @@ class TasksController < MyProfileController |
| 4 | 4 | |
| 5 | 5 | def index |
| 6 | 6 | @filter = params[:filter_type].blank? ? nil : params[:filter_type] |
| 7 | - @tasks = Task.to(profile).pending.of(@filter).order_by('created_at', 'asc').paginate(:per_page => Task.per_page, :page => params[:page]) | |
| 7 | + @tasks = Task.to(profile).without_spam.pending.of(@filter).order_by('created_at', 'asc').paginate(:per_page => Task.per_page, :page => params[:page]) | |
| 8 | 8 | @failed = params ? params[:failed] : {} |
| 9 | 9 | end |
| 10 | 10 | |
| 11 | 11 | def processed |
| 12 | - @tasks = Task.to(profile).closed.sort_by(&:created_at) | |
| 12 | + @tasks = Task.to(profile).without_spam.closed.sort_by(&:created_at) | |
| 13 | 13 | end |
| 14 | 14 | |
| 15 | 15 | VALID_DECISIONS = [ 'finish', 'cancel', 'skip' ] |
| ... | ... | @@ -57,7 +57,7 @@ class TasksController < MyProfileController |
| 57 | 57 | end |
| 58 | 58 | |
| 59 | 59 | def list_requested |
| 60 | - @tasks = Task.find_all_by_requestor_id(profile.id) | |
| 60 | + @tasks = Task.without_spam.find_all_by_requestor_id(profile.id) | |
| 61 | 61 | end |
| 62 | 62 | |
| 63 | 63 | def ticket_details | ... | ... |
app/models/spammer_logger.rb
| ... | ... | @@ -6,6 +6,8 @@ class SpammerLogger < Logger |
| 6 | 6 | if object |
| 7 | 7 | if object.kind_of?(Comment) |
| 8 | 8 | @logger << "[#{Time.now.strftime('%F %T %z')}] Comment-id: #{object.id} IP: #{spammer_ip}\n" |
| 9 | + elsif object.kind_of?(SuggestArticle) | |
| 10 | + @logger << "[#{Time.now.strftime('%F %T %z')}] SuggestArticle-id: #{object.id} IP: #{spammer_ip}\n" | |
| 9 | 11 | end |
| 10 | 12 | else |
| 11 | 13 | @logger << "[#{Time.now.strftime('%F %T %z')}] IP: #{spammer_ip}\n" | ... | ... |
app/models/suggest_article.rb
| ... | ... | @@ -11,6 +11,21 @@ class SuggestArticle < Task |
| 11 | 11 | settings_items :source, :type => String |
| 12 | 12 | settings_items :source_name, :type => String |
| 13 | 13 | settings_items :highlighted, :type => :boolean, :default => false |
| 14 | + settings_items :ip_address, :type => String | |
| 15 | + settings_items :user_agent, :type => String | |
| 16 | + settings_items :referrer, :type => String | |
| 17 | + | |
| 18 | + after_create :schedule_spam_checking | |
| 19 | + | |
| 20 | + def schedule_spam_checking | |
| 21 | + self.delay.check_for_spam | |
| 22 | + end | |
| 23 | + | |
| 24 | + include Noosfero::Plugin::HotSpot | |
| 25 | + | |
| 26 | + def check_for_spam | |
| 27 | + plugins.dispatch(:check_suggest_article_for_spam, self) | |
| 28 | + end | |
| 14 | 29 | |
| 15 | 30 | def sender |
| 16 | 31 | "#{name} (#{email})" |
| ... | ... | @@ -61,4 +76,25 @@ class SuggestArticle < Task |
| 61 | 76 | _('You need to login on %{system} in order to approve or reject this article.') % { :system => target.environment.name } |
| 62 | 77 | end |
| 63 | 78 | |
| 79 | + def spam! | |
| 80 | + super | |
| 81 | + SpammerLogger.log(ip_address, self) | |
| 82 | + self.delay.marked_as_spam | |
| 83 | + self | |
| 84 | + end | |
| 85 | + | |
| 86 | + def ham! | |
| 87 | + super | |
| 88 | + self.delay.marked_as_ham | |
| 89 | + self | |
| 90 | + end | |
| 91 | + | |
| 92 | + def marked_as_spam | |
| 93 | + plugins.dispatch(:suggest_article_marked_as_spam, self) | |
| 94 | + end | |
| 95 | + | |
| 96 | + def marked_as_ham | |
| 97 | + plugins.dispatch(:suggest_article_marked_as_ham, self) | |
| 98 | + end | |
| 99 | + | |
| 64 | 100 | end | ... | ... |
app/models/task.rb
| ... | ... | @@ -235,6 +235,26 @@ class Task < ActiveRecord::Base |
| 235 | 235 | end |
| 236 | 236 | end |
| 237 | 237 | |
| 238 | + def spam? | |
| 239 | + !spam.nil? && spam | |
| 240 | + end | |
| 241 | + | |
| 242 | + def ham? | |
| 243 | + !spam.nil? && !spam | |
| 244 | + end | |
| 245 | + | |
| 246 | + def spam! | |
| 247 | + self.spam = true | |
| 248 | + self.save! | |
| 249 | + self | |
| 250 | + end | |
| 251 | + | |
| 252 | + def ham! | |
| 253 | + self.spam = false | |
| 254 | + self.save! | |
| 255 | + self | |
| 256 | + end | |
| 257 | + | |
| 238 | 258 | protected |
| 239 | 259 | |
| 240 | 260 | # This method must be overrided in subclasses, and its implementation must do |
| ... | ... | @@ -274,6 +294,9 @@ class Task < ActiveRecord::Base |
| 274 | 294 | named_scope :opened, :conditions => { :status => [Task::Status::ACTIVE, Task::Status::HIDDEN] } |
| 275 | 295 | named_scope :of, lambda { |type| conditions = type ? "type LIKE '#{type}'" : "1=1"; {:conditions => [conditions]} } |
| 276 | 296 | named_scope :order_by, lambda { |attribute, ord| {:order => "#{attribute} #{ord}"} } |
| 297 | + named_scope :without_spam, :conditions => ['spam IS NULL OR spam = ?', false] | |
| 298 | + named_scope :spam, :conditions => ['spam = ?', true] | |
| 299 | + | |
| 277 | 300 | |
| 278 | 301 | named_scope :to, lambda { |profile| |
| 279 | 302 | environment_condition = nil | ... | ... |
| ... | ... | @@ -0,0 +1,11 @@ |
| 1 | +<%# FIXME should not need to replicate the article structure like this to be able to use the same formatting as the comments listing %> | |
| 2 | +<div id='article'> | |
| 3 | + <div class="comments" id="comments_list"> | |
| 4 | + <ul class="article-comments-list"> | |
| 5 | + <%= render :partial => 'comment/comment', :collection => @comment_spam %> | |
| 6 | + </ul> | |
| 7 | + </div> | |
| 8 | +</div> | |
| 9 | + | |
| 10 | +<%= pagination_links @comment_spam, :param_name => :comments_page %> | |
| 11 | + | ... | ... |
| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | +<% render :layout => 'task', :locals => { :task => task } do %> | |
| 2 | + <% content_for :extra_buttons do %> | |
| 3 | + <%= button_to_function('down', _('Show details'), "toggleDetails(this, '#{_('Hide details')}', '#{_('Show details')}')" ) %> | |
| 4 | + <% end %> | |
| 5 | + | |
| 6 | + <% content_for :extra_content do %> | |
| 7 | + <ul class="suggest-article-details" style="display: none"> | |
| 8 | + <li><strong><%=_('Sent by')%></strong>: <%=task.name%> </li> | |
| 9 | + <li><strong><%=_('Email')%></strong>: <%=task.email%> </li> | |
| 10 | + <li><strong><%=_('Source')%></strong>: <%=task.source_name%> </li> | |
| 11 | + <li><strong><%=_('Source URL')%></strong>: <%=task.source%> </li> | |
| 12 | + <li><strong><%=_('Folder')%></strong>: <%=(a = Article.find_by_id(task.article_parent_id))?a.name : '<em>' + s_('Folder|none') + '</em>'%> </li> | |
| 13 | + <li><strong><%=_('Lead')%></strong>: <%=task.article_abstract.blank? ? '<em>' + s_('Abstract|empty') + '</em>' : task.article_abstract%> </li> | |
| 14 | + <li><strong><%=_('Body')%></strong>: | |
| 15 | + <div class='suggest-article-body'> | |
| 16 | + <%= task.article_body %> | |
| 17 | + </div> | |
| 18 | + </li> | |
| 19 | + </ul> | |
| 20 | + <% end %> | |
| 21 | +<% end %> | ... | ... |
| ... | ... | @@ -0,0 +1,18 @@ |
| 1 | +<div class="task_box" id="task-<%= task.id %>"> | |
| 2 | + <%= render :partial => 'tasks/task_icon', :locals => {:task => task} %> | |
| 3 | + <%= render :partial => 'tasks/task_title', :locals => {:task => task} %> | |
| 4 | + <div class="task-information"> | |
| 5 | + <%= task_information(task) %> | |
| 6 | + </div> | |
| 7 | + | |
| 8 | + <%= yield %> <% # ??? %> | |
| 9 | + | |
| 10 | + <% button_bar do %> | |
| 11 | + <%= button_to_function('new', _('Mark as NOT SPAM'), 'removeTaskBox(this, %s, "%s", "")' % [url_for(:mark_task_as_ham => task.id).to_json, "task-#{task.id}"]) %> | |
| 12 | + <%= yield :extra_buttons %> | |
| 13 | + <%= button_to_function('delete', _('Remove'), 'removeTaskBox(this, %s, "%s", %s)' % [url_for(:profile => params[:profile], :remove_task => task.id).to_json, "task-#{task.id}", _('Are you sure you want to remove this article suggestion?').to_json]) %> | |
| 14 | + | |
| 15 | + <% end %> | |
| 16 | + | |
| 17 | + <%= yield :extra_content %> | |
| 18 | +</div> | ... | ... |
app/views/spam/index.rhtml
| 1 | +<%= stylesheet('tasks') %> | |
| 2 | + | |
| 1 | 3 | <h1><%= _('Manage SPAM') %></h1> |
| 2 | 4 | |
| 3 | 5 | <% button_bar do %> |
| ... | ... | @@ -5,16 +7,21 @@ |
| 5 | 7 | <% end %> |
| 6 | 8 | |
| 7 | 9 | <%# FIXME should not need to replicate the article structure like this to be able to use the same formatting as the comments listing %> |
| 8 | -<div id='article'> | |
| 9 | - <div class="comments" id="comments_list"> | |
| 10 | - <ul class="article-comments-list"> | |
| 11 | - <%= render :partial => 'comment/comment', :collection => @spam %> | |
| 12 | - </ul> | |
| 13 | - </div> | |
| 14 | -</div> | |
| 15 | 10 | |
| 16 | -<%= pagination_links @spam %> | |
| 11 | +<% if @task_spam.length > 0 %> | |
| 12 | + <% tabs = [] %> | |
| 13 | + <% tabs << {:title => _('Comment Spam'), :id => 'comment-spam', | |
| 14 | + :content => (render :partial => 'comment_spam')} %> | |
| 15 | + <% tabs << {:title => _('Task Spam'), :id => 'task-spam', | |
| 16 | + :content => (render :partial => 'task_spam') } %> | |
| 17 | + <%= render_tabs(tabs) %> | |
| 18 | +<% else %> | |
| 19 | + <%= render :partial => 'comment_spam' %> | |
| 20 | +<% end %> | |
| 21 | + | |
| 17 | 22 | |
| 18 | 23 | <% button_bar do %> |
| 19 | 24 | <%= button :back, _('Back to control panel'), :controller => :profile_editor %> |
| 20 | 25 | <% end %> |
| 26 | + | |
| 27 | +<%= javascript_include_tag 'spam' %> | ... | ... |
app/views/tasks/_task.rhtml
| 1 | 1 | <div class="task_box" id="task-<%= task.id %>"> |
| 2 | 2 | |
| 3 | - <div class="task_icon"> | |
| 4 | - <% | |
| 5 | - icon_info = task.icon | |
| 6 | - if icon_info[:type] == :profile_image | |
| 7 | - icon = profile_image(icon_info[:profile], :minor) | |
| 8 | - elsif icon_info[:type] == :defined_image | |
| 9 | - icon = "<img src='#{icon_info[:src]}' alt='#{icon_info[:name]}' />" | |
| 10 | - end | |
| 11 | - %> | |
| 12 | - <%= | |
| 13 | - if icon_info[:url] | |
| 14 | - link_to(icon, icon_info[:url]) | |
| 15 | - else | |
| 16 | - icon | |
| 17 | - end | |
| 18 | - %> | |
| 19 | - | |
| 20 | - </div> | |
| 3 | + <%= render :partial => 'task_icon', :locals => {:task => task} %> | |
| 21 | 4 | |
| 22 | 5 | <div class="task_decisions"> |
| 23 | 6 | <%= |
| ... | ... | @@ -39,9 +22,7 @@ |
| 39 | 22 | %> |
| 40 | 23 | </div><!-- class="task_decisions" --> |
| 41 | 24 | |
| 42 | - <strong class="task_title"> | |
| 43 | - <%= task.title %> | |
| 44 | - </strong> | |
| 25 | + <%= render :partial => 'task_title', :locals => {:task => task} %> | |
| 45 | 26 | |
| 46 | 27 | <div class="task_information"> |
| 47 | 28 | <%= task_information(task) %> | ... | ... |
| ... | ... | @@ -0,0 +1,16 @@ |
| 1 | +<% | |
| 2 | + icon_info = task.icon | |
| 3 | + if icon_info[:type] == :profile_image | |
| 4 | + icon = profile_image(icon_info[:profile], :minor) | |
| 5 | + elsif icon_info[:type] == :defined_image | |
| 6 | + icon = "<img src='#{icon_info[:src]}' alt='#{icon_info[:name]}' />" | |
| 7 | + end | |
| 8 | + | |
| 9 | + if icon_info[:url] | |
| 10 | + icon = link_to(icon, icon_info[:url]) | |
| 11 | + end | |
| 12 | +%> | |
| 13 | + | |
| 14 | +<div class="task_icon"> | |
| 15 | + <%= icon %> | |
| 16 | +</div> | ... | ... |
| ... | ... | @@ -0,0 +1,13 @@ |
| 1 | +class AddSpamToTask < ActiveRecord::Migration | |
| 2 | + def self.up | |
| 3 | + change_table :tasks do |t| | |
| 4 | + t.boolean :spam, :default => false | |
| 5 | + end | |
| 6 | + Task.update_all ["spam = ?", false] | |
| 7 | + add_index :tasks, [:spam] | |
| 8 | + end | |
| 9 | + | |
| 10 | + def self.down | |
| 11 | + remove_column :tasks, :spam | |
| 12 | + end | |
| 13 | +end | ... | ... |
db/schema.rb
| ... | ... | @@ -9,7 +9,7 @@ |
| 9 | 9 | # |
| 10 | 10 | # It's strongly recommended to check this file into your version control system. |
| 11 | 11 | |
| 12 | -ActiveRecord::Schema.define(:version => 20130711213046) do | |
| 12 | +ActiveRecord::Schema.define(:version => 20131011164400) do | |
| 13 | 13 | |
| 14 | 14 | create_table "abuse_reports", :force => true do |t| |
| 15 | 15 | t.integer "reporter_id" |
| ... | ... | @@ -233,6 +233,50 @@ ActiveRecord::Schema.define(:version => 20130711213046) do |
| 233 | 233 | t.datetime "updated_at" |
| 234 | 234 | end |
| 235 | 235 | |
| 236 | + create_table "custom_forms_plugin_answers", :force => true do |t| | |
| 237 | + t.text "value" | |
| 238 | + t.integer "field_id" | |
| 239 | + t.integer "submission_id" | |
| 240 | + end | |
| 241 | + | |
| 242 | + create_table "custom_forms_plugin_fields", :force => true do |t| | |
| 243 | + t.string "name" | |
| 244 | + t.string "slug" | |
| 245 | + t.string "type" | |
| 246 | + t.string "default_value" | |
| 247 | + t.string "choices" | |
| 248 | + t.float "minimum" | |
| 249 | + t.float "maximum" | |
| 250 | + t.integer "form_id" | |
| 251 | + t.boolean "mandatory", :default => false | |
| 252 | + t.boolean "multiple" | |
| 253 | + t.boolean "list" | |
| 254 | + t.integer "position", :default => 0 | |
| 255 | + end | |
| 256 | + | |
| 257 | + create_table "custom_forms_plugin_forms", :force => true do |t| | |
| 258 | + t.string "name" | |
| 259 | + t.string "slug" | |
| 260 | + t.text "description" | |
| 261 | + t.integer "profile_id" | |
| 262 | + t.datetime "begining" | |
| 263 | + t.datetime "ending" | |
| 264 | + t.boolean "report_submissions", :default => false | |
| 265 | + t.boolean "on_membership", :default => false | |
| 266 | + t.string "access" | |
| 267 | + t.datetime "created_at" | |
| 268 | + t.datetime "updated_at" | |
| 269 | + end | |
| 270 | + | |
| 271 | + create_table "custom_forms_plugin_submissions", :force => true do |t| | |
| 272 | + t.string "author_name" | |
| 273 | + t.string "author_email" | |
| 274 | + t.integer "profile_id" | |
| 275 | + t.integer "form_id" | |
| 276 | + t.datetime "created_at" | |
| 277 | + t.datetime "updated_at" | |
| 278 | + end | |
| 279 | + | |
| 236 | 280 | create_table "delayed_jobs", :force => true do |t| |
| 237 | 281 | t.integer "priority", :default => 0 |
| 238 | 282 | t.integer "attempts", :default => 0 |
| ... | ... | @@ -547,8 +591,11 @@ ActiveRecord::Schema.define(:version => 20130711213046) do |
| 547 | 591 | t.datetime "created_at" |
| 548 | 592 | t.string "target_type" |
| 549 | 593 | t.integer "image_id" |
| 594 | + t.boolean "spam", :default => false | |
| 550 | 595 | end |
| 551 | 596 | |
| 597 | + add_index "tasks", ["spam"], :name => "index_tasks_on_spam" | |
| 598 | + | |
| 552 | 599 | create_table "thumbnails", :force => true do |t| |
| 553 | 600 | t.integer "size" |
| 554 | 601 | t.string "content_type" | ... | ... |
plugins/anti_spam/lib/anti_spam_plugin.rb
| ... | ... | @@ -5,7 +5,7 @@ class AntiSpamPlugin < Noosfero::Plugin |
| 5 | 5 | end |
| 6 | 6 | |
| 7 | 7 | def self.plugin_description |
| 8 | - _("Checks comments against a spam checking service compatible with the Akismet API") | |
| 8 | + _("Tests comments and suggested articles against a spam checking service compatible with the Akismet API") | |
| 9 | 9 | end |
| 10 | 10 | |
| 11 | 11 | def self.host_default_setting |
| ... | ... | @@ -13,30 +13,44 @@ class AntiSpamPlugin < Noosfero::Plugin |
| 13 | 13 | end |
| 14 | 14 | |
| 15 | 15 | def check_comment_for_spam(comment) |
| 16 | - if rakismet_call(comment, :spam?) | |
| 16 | + if rakismet_call AntiSpamPlugin::CommentWrapper.new(comment), comment.environment, :spam? | |
| 17 | 17 | comment.spam = true |
| 18 | 18 | comment.save! |
| 19 | 19 | end |
| 20 | 20 | end |
| 21 | 21 | |
| 22 | 22 | def comment_marked_as_spam(comment) |
| 23 | - rakismet_call(comment, :spam!) | |
| 23 | + rakismet_call AntiSpamPlugin::CommentWrapper.new(comment), comment.environment, :spam! | |
| 24 | 24 | end |
| 25 | 25 | |
| 26 | 26 | def comment_marked_as_ham(comment) |
| 27 | - rakismet_call(comment, :ham!) | |
| 27 | + rakismet_call AntiSpamPlugin::CommentWrapper.new(comment), comment.environment, :ham! | |
| 28 | + end | |
| 29 | + | |
| 30 | + def check_suggest_article_for_spam(suggest_article) | |
| 31 | + if rakismet_call AntiSpamPlugin::SuggestArticleWrapper.new(suggest_article), suggest_article.environment, :spam? | |
| 32 | + suggest_article.spam = true | |
| 33 | + suggest_article.save! | |
| 34 | + end | |
| 35 | + end | |
| 36 | + | |
| 37 | + def suggest_article_marked_as_spam(suggest_article) | |
| 38 | + rakismet_call AntiSpamPlugin::SuggestArticleWrapper.new(suggest_article), suggest_article.environment, :spam! | |
| 39 | + end | |
| 40 | + | |
| 41 | + def suggest_article_marked_as_ham(suggest_article) | |
| 42 | + rakismet_call AntiSpamPlugin::SuggestArticleWrapper.new(suggest_article), suggest_article.environment, :ham! | |
| 28 | 43 | end |
| 29 | 44 | |
| 30 | 45 | protected |
| 31 | 46 | |
| 32 | - def rakismet_call(comment, op) | |
| 33 | - settings = Noosfero::Plugin::Settings.new(comment.environment, self.class) | |
| 47 | + def rakismet_call(submission, environment, op) | |
| 48 | + settings = Noosfero::Plugin::Settings.new(environment, self.class) | |
| 34 | 49 | |
| 35 | 50 | Rakismet.host = settings.host |
| 36 | 51 | Rakismet.key = settings.api_key |
| 37 | - Rakismet.url = comment.environment.top_url | |
| 52 | + Rakismet.url = environment.top_url | |
| 38 | 53 | |
| 39 | - submission = AntiSpamPlugin::CommentWrapper.new(comment) | |
| 40 | 54 | submission.send(op) |
| 41 | 55 | end |
| 42 | 56 | ... | ... |
plugins/anti_spam/lib/anti_spam_plugin/suggest_article_wrapper.rb
0 → 100644
| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | +class AntiSpamPlugin::SuggestArticleWrapper < Struct.new(:suggest_article) | |
| 2 | + | |
| 3 | + delegate :name, :email, :article_body, :ip_address, :user_agent, :referrer, :to => :suggest_article | |
| 4 | + | |
| 5 | + include Rakismet::Model | |
| 6 | + | |
| 7 | + alias :author :name | |
| 8 | + alias :author_email :email | |
| 9 | + alias :user_ip :ip_address | |
| 10 | + alias :content :article_body | |
| 11 | + | |
| 12 | +end | ... | ... |
plugins/anti_spam/test/unit/anti_spam_plugin/suggest_article_wrapper_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,45 @@ |
| 1 | +require 'test_helper' | |
| 2 | + | |
| 3 | +class AntiSpamPluginCommentWrapperTest < ActiveSupport::TestCase | |
| 4 | + | |
| 5 | + def setup | |
| 6 | + @suggest_article = SuggestArticle.new( | |
| 7 | + :article_body => 'comment body', | |
| 8 | + :name => 'author', | |
| 9 | + :email => 'foo@example.com', | |
| 10 | + :ip_address => '1.2.3.4', | |
| 11 | + :user_agent => 'Some Good Browser (I hope)', | |
| 12 | + :referrer => 'http://noosfero.org/' | |
| 13 | + ) | |
| 14 | + @wrapper = AntiSpamPlugin::SuggestArticleWrapper.new(@suggest_article) | |
| 15 | + end | |
| 16 | + | |
| 17 | + should 'use Rakismet::Model' do | |
| 18 | + assert_includes @wrapper.class.included_modules, Rakismet::Model | |
| 19 | + end | |
| 20 | + | |
| 21 | + should 'get contents' do | |
| 22 | + assert_equal @suggest_article.article_body, @wrapper.content | |
| 23 | + end | |
| 24 | + | |
| 25 | + should 'get author name' do | |
| 26 | + assert_equal @suggest_article.name, @wrapper.author | |
| 27 | + end | |
| 28 | + | |
| 29 | + should 'get author email' do | |
| 30 | + assert_equal @suggest_article.email, @wrapper.author_email | |
| 31 | + end | |
| 32 | + | |
| 33 | + should 'get IP address' do | |
| 34 | + assert_equal @suggest_article.ip_address, @wrapper.user_ip | |
| 35 | + end | |
| 36 | + | |
| 37 | + should 'get User-Agent' do | |
| 38 | + assert_equal @suggest_article.user_agent, @wrapper.user_agent | |
| 39 | + end | |
| 40 | + | |
| 41 | + should 'get get Referrer' do | |
| 42 | + assert_equal @suggest_article.referrer, @wrapper.referrer | |
| 43 | + end | |
| 44 | + | |
| 45 | +end | ... | ... |
plugins/anti_spam/test/unit/anti_spam_plugin_test.rb
| ... | ... | @@ -7,6 +7,11 @@ class AntiSpamPluginTest < ActiveSupport::TestCase |
| 7 | 7 | article = fast_create(TextileArticle, :profile_id => profile.id) |
| 8 | 8 | @comment = fast_create(Comment, :source_id => article.id, :source_type => 'Article') |
| 9 | 9 | |
| 10 | + | |
| 11 | + @suggest_article = SuggestArticle.new(:target_id => profile.id, :target_type => 'Profile', :article_name => 'article', :article_body => 'lorem ipsum', :email => 'invalid@example.com', :name => 'article') | |
| 12 | + | |
| 13 | + @suggest_article.save! | |
| 14 | + | |
| 10 | 15 | @settings = Noosfero::Plugin::Settings.new(@comment.environment, AntiSpamPlugin) |
| 11 | 16 | @settings.api_key = 'b8b80ddb8084062d0c9119c945ce3bc3' |
| 12 | 17 | @settings.save! |
| ... | ... | @@ -23,14 +28,32 @@ class AntiSpamPluginTest < ActiveSupport::TestCase |
| 23 | 28 | assert @comment.spam |
| 24 | 29 | end |
| 25 | 30 | |
| 26 | - should 'report spam' do | |
| 31 | + should 'report comment spam' do | |
| 27 | 32 | AntiSpamPlugin::CommentWrapper.any_instance.expects(:spam!) |
| 28 | 33 | @plugin.comment_marked_as_spam(@comment) |
| 29 | 34 | end |
| 30 | 35 | |
| 31 | - should 'report ham' do | |
| 36 | + should 'report comment ham' do | |
| 32 | 37 | AntiSpamPlugin::CommentWrapper.any_instance.expects(:ham!) |
| 33 | 38 | @plugin.comment_marked_as_ham(@comment) |
| 34 | 39 | end |
| 35 | 40 | |
| 41 | + should 'check for spam and mark suggest_article as spam if server says it is spam' do | |
| 42 | + AntiSpamPlugin::SuggestArticleWrapper.any_instance.expects(:spam?).returns(true) | |
| 43 | + @suggest_article.expects(:save!) | |
| 44 | + | |
| 45 | + @plugin.check_suggest_article_for_spam(@suggest_article) | |
| 46 | + assert @suggest_article.spam | |
| 47 | + end | |
| 48 | + | |
| 49 | + should 'report suggest_article spam' do | |
| 50 | + AntiSpamPlugin::SuggestArticleWrapper.any_instance.expects(:spam!) | |
| 51 | + @plugin.suggest_article_marked_as_spam(@suggest_article) | |
| 52 | + end | |
| 53 | + | |
| 54 | + should 'report suggest_article ham' do | |
| 55 | + AntiSpamPlugin::SuggestArticleWrapper.any_instance.expects(:ham!) | |
| 56 | + @plugin.suggest_article_marked_as_ham(@suggest_article) | |
| 57 | + end | |
| 58 | + | |
| 36 | 59 | end | ... | ... |
| ... | ... | @@ -0,0 +1,28 @@ |
| 1 | +function removeTaskBox(button, url, task_box_id, msg) { | |
| 2 | + var $ = jQuery; | |
| 3 | + if (msg && !confirm(msg)) { | |
| 4 | + return; | |
| 5 | + } | |
| 6 | + button = $(button); | |
| 7 | + button.addClass('task-button-loading'); | |
| 8 | + $.post(url, function (data) { | |
| 9 | + if (data.ok) { | |
| 10 | + $('#' + task_box_id).slideUp(); | |
| 11 | + } else { | |
| 12 | + button.removeClass('task-button-loading'); | |
| 13 | + button.addClass('task-button-failure'); | |
| 14 | + } | |
| 15 | + }); | |
| 16 | +} | |
| 17 | + | |
| 18 | +function toggleDetails(link, msg_hide, msg_show) { | |
| 19 | + var $ = jQuery; | |
| 20 | + $(link).toggleClass('icon-up icon-down'); | |
| 21 | + details = $(link).closest('.task_box').find('.suggest-article-details'); | |
| 22 | + if (details.css('display') == 'none') { | |
| 23 | + link.innerHTML = msg_hide; | |
| 24 | + } else { | |
| 25 | + link.innerHTML = msg_show; | |
| 26 | + } | |
| 27 | + details.slideToggle(); | |
| 28 | +} | ... | ... |
test/functional/spam_controller_test.rb
| ... | ... | @@ -4,37 +4,55 @@ class SpamControllerTest < ActionController::TestCase |
| 4 | 4 | |
| 5 | 5 | def setup |
| 6 | 6 | @profile = create_user.person |
| 7 | - @article = fast_create(TextileArticle, :profile_id => @profile.id) | |
| 8 | - @spam = fast_create(Comment, :source_id => @article.id, :spam => true, :name => 'foo', :email => 'foo@example.com') | |
| 9 | 7 | |
| 8 | + @community = fast_create(Community, :name => 'testcommunity') | |
| 9 | + @community.add_admin(@profile) | |
| 10 | + @article = fast_create(TextileArticle, :profile_id => @community.id) | |
| 11 | + @spam_comment = fast_create(Comment, :source_id => @article.id, :spam => true, :name => 'foo', :email => 'foo@example.com') | |
| 12 | + | |
| 13 | + @spam_suggest_article = SuggestArticle.create!(:name => 'spammer', :article_name => 'Spam article', :email => 'spammer@shady.place', :article_body => "Something you don't need", :target => @community, :spam => true) | |
| 10 | 14 | login_as @profile.identifier |
| 11 | 15 | end |
| 12 | 16 | |
| 13 | - test "should only list spammy comments" do | |
| 17 | + test "should only list spammy comments and spammy suggest articles" do | |
| 14 | 18 | ham = fast_create(Comment, :source_id => @article.id) |
| 15 | 19 | |
| 16 | - get :index, :profile => @profile.identifier | |
| 20 | + get :index, :profile => @community.identifier | |
| 17 | 21 | |
| 18 | - assert_equivalent [@spam], assigns(:spam) | |
| 22 | + assert_equivalent [@spam_comment], assigns(:comment_spam) | |
| 23 | + assert_equivalent [@spam_suggest_article], assigns(:task_spam) | |
| 19 | 24 | end |
| 20 | 25 | |
| 21 | 26 | test "should mark comments as ham" do |
| 22 | - post :index, :profile => @profile.identifier, :mark_comment_as_ham => @spam.id | |
| 27 | + post :index, :profile => @community.identifier, :mark_comment_as_ham => @spam_comment.id | |
| 28 | + | |
| 29 | + @spam_comment.reload | |
| 30 | + assert @spam_comment.ham? | |
| 31 | + end | |
| 32 | + | |
| 33 | + test "should mark suggest article as ham" do | |
| 34 | + post :index, :profile => @community.identifier, :mark_task_as_ham => @spam_suggest_article.id | |
| 23 | 35 | |
| 24 | - @spam.reload | |
| 25 | - assert @spam.ham? | |
| 36 | + @spam_suggest_article.reload | |
| 37 | + assert @spam_suggest_article.ham? | |
| 26 | 38 | end |
| 27 | 39 | |
| 28 | 40 | test "should remove comments" do |
| 29 | - post :index, :profile => @profile.identifier, :remove_comment => @spam.id | |
| 41 | + post :index, :profile => @community.identifier, :remove_comment => @spam_comment.id | |
| 42 | + | |
| 43 | + assert !Comment.exists?(@spam_comment.id) | |
| 44 | + end | |
| 45 | + | |
| 46 | + test "should remove suggest articles" do | |
| 47 | + post :index, :profile => @community.identifier, :remove_task => @spam_suggest_article.id | |
| 30 | 48 | |
| 31 | - assert !Comment.exists?(@spam.id) | |
| 49 | + assert !SuggestArticle.exists?(@spam_suggest_article.id) | |
| 32 | 50 | end |
| 33 | 51 | |
| 34 | 52 | should 'properly render spam that have replies' do |
| 35 | - reply_spam = fast_create(Comment, :source_id => @article_id, :reply_of_id => @spam.id) | |
| 53 | + reply_spam = fast_create(Comment, :source_id => @article_id, :reply_of_id => @spam_comment.id) | |
| 36 | 54 | |
| 37 | - get :index, :profile => @profile.identifier | |
| 55 | + get :index, :profile => @community.identifier | |
| 38 | 56 | assert_response :success |
| 39 | 57 | end |
| 40 | 58 | ... | ... |
test/functional/tasks_controller_test.rb
| ... | ... | @@ -38,6 +38,17 @@ class TasksControllerTest < ActionController::TestCase |
| 38 | 38 | assert_kind_of Array, assigns(:tasks) |
| 39 | 39 | end |
| 40 | 40 | |
| 41 | + should 'list pending tasks without spam' do | |
| 42 | + requestor = fast_create(Person) | |
| 43 | + task_spam = Task.create!(:requestor => requestor, :target => profile, :spam => true) | |
| 44 | + task_ham = Task.create!(:requestor => requestor, :target => profile, :spam => false) | |
| 45 | + | |
| 46 | + get :index | |
| 47 | + assert_response :success | |
| 48 | + assert_includes assigns(:tasks), task_ham | |
| 49 | + assert_not_includes assigns(:tasks), task_spam | |
| 50 | + end | |
| 51 | + | |
| 41 | 52 | should 'list processed tasks' do |
| 42 | 53 | get :processed |
| 43 | 54 | |
| ... | ... | @@ -46,6 +57,17 @@ class TasksControllerTest < ActionController::TestCase |
| 46 | 57 | assert_kind_of Array, assigns(:tasks) |
| 47 | 58 | end |
| 48 | 59 | |
| 60 | + should 'list processed tasks without spam' do | |
| 61 | + requestor = fast_create(Person) | |
| 62 | + task_spam = Task.create!(:status => Task::Status::FINISHED, :requestor => requestor, :target => profile, :spam => true) | |
| 63 | + task_ham = Task.create!(:status => Task::Status::FINISHED, :requestor => requestor, :target => profile, :spam => false) | |
| 64 | + | |
| 65 | + get :processed | |
| 66 | + assert_response :success | |
| 67 | + assert_includes assigns(:tasks), task_ham | |
| 68 | + assert_not_includes assigns(:tasks), task_spam | |
| 69 | + end | |
| 70 | + | |
| 49 | 71 | should 'be able to finish a task' do |
| 50 | 72 | t = profile.tasks.build; t.save! |
| 51 | 73 | |
| ... | ... | @@ -140,6 +162,15 @@ class TasksControllerTest < ActionController::TestCase |
| 140 | 162 | assert_includes assigns(:tasks), task |
| 141 | 163 | end |
| 142 | 164 | |
| 165 | + should 'list tasks that this profile created without spam' do | |
| 166 | + task_spam = Ticket.create!(:name => 'test', :requestor => profile, :spam => true) | |
| 167 | + task_ham = Ticket.create!(:name => 'test', :requestor => profile, :spam => false) | |
| 168 | + get :list_requested, :profile => profile.identifier | |
| 169 | + | |
| 170 | + assert_includes assigns(:tasks), task_ham | |
| 171 | + assert_not_includes assigns(:tasks), task_spam | |
| 172 | + end | |
| 173 | + | |
| 143 | 174 | should 'set target of ticket when creating it' do |
| 144 | 175 | f = create_user('friend').person |
| 145 | 176 | profile.add_friend f | ... | ... |
test/unit/suggest_article_test.rb
| ... | ... | @@ -150,5 +150,79 @@ class SuggestArticleTest < ActiveSupport::TestCase |
| 150 | 150 | assert_match(/#{task.name}.*suggested the publication of the article: #{task.subject}/, email.subject) |
| 151 | 151 | end |
| 152 | 152 | |
| 153 | + class EverythingIsSpam < Noosfero::Plugin | |
| 154 | + def check_suggest_article_for_spam(suggest_article) | |
| 155 | + suggest_article.spam! | |
| 156 | + end | |
| 157 | + end | |
| 158 | + | |
| 159 | + should 'delegate spam detection to plugins' do | |
| 160 | + Environment.default.enable_plugin(EverythingIsSpam) | |
| 161 | + | |
| 162 | + t1 = build(SuggestArticle, :target => @profile, :article_name => 'suggested article', :name => 'johndoe', :email => 'johndoe@example.com') | |
| 163 | + | |
| 164 | + EverythingIsSpam.any_instance.expects(:check_suggest_article_for_spam) | |
| 165 | + | |
| 166 | + t1.check_for_spam | |
| 167 | + end | |
| 168 | + | |
| 169 | + class SpamNotification < Noosfero::Plugin | |
| 170 | + class << self | |
| 171 | + attr_accessor :marked_as_spam | |
| 172 | + attr_accessor :marked_as_ham | |
| 173 | + end | |
| 174 | + | |
| 175 | + def check_suggest_article_for_spam(c) | |
| 176 | + # do nothing | |
| 177 | + end | |
| 178 | + | |
| 179 | + def suggest_article_marked_as_spam(c) | |
| 180 | + self.class.marked_as_spam = c | |
| 181 | + end | |
| 182 | + | |
| 183 | + def suggest_article_marked_as_ham(c) | |
| 184 | + self.class.marked_as_ham = c | |
| 185 | + end | |
| 186 | + end | |
| 187 | + | |
| 188 | + should 'notify plugins of suggest_articles being marked as spam' do | |
| 189 | + Environment.default.enable_plugin(SpamNotification) | |
| 190 | + | |
| 191 | + t = SuggestArticle.create!(:target => @profile, :article_name => 'suggested article', :name => 'johndoe', :article_body => 'wanna feel my body? my body baaaby', :email => 'johndoe@example.com') | |
| 192 | + | |
| 193 | + t.spam! | |
| 194 | + process_delayed_job_queue | |
| 195 | + | |
| 196 | + assert_equal t, SpamNotification.marked_as_spam | |
| 197 | + end | |
| 198 | + | |
| 199 | + should 'notify plugins of suggest_articles being marked as ham' do | |
| 200 | + Environment.default.enable_plugin(SpamNotification) | |
| 201 | + | |
| 202 | + t = SuggestArticle.create!(:target => @profile, :article_name => 'suggested article', :name => 'johndoe', :article_body => 'wanna feel my body? my body baaaby', :email => 'johndoe@example.com') | |
| 203 | + | |
| 204 | + t.ham! | |
| 205 | + process_delayed_job_queue | |
| 206 | + | |
| 207 | + assert_equal t, SpamNotification.marked_as_ham | |
| 208 | + end | |
| 209 | + | |
| 210 | + should 'store User-Agent' do | |
| 211 | + t = SuggestArticle.new(:user_agent => 'foo') | |
| 212 | + assert_equal 'foo', t.user_agent | |
| 213 | + end | |
| 214 | + | |
| 215 | + should 'store referrer' do | |
| 216 | + t = SuggestArticle.new(:referrer => 'bar') | |
| 217 | + assert_equal 'bar', t.referrer | |
| 218 | + end | |
| 219 | + | |
| 220 | + should 'log spammer ip after marking comment as spam' do | |
| 221 | + t = SuggestArticle.create!(:target => @profile, :article_name => 'suggested article', :name => 'johndoe', :article_body => 'wanna feel my body? my body baaaby', :email => 'johndoe@example.com', :ip_address => '192.168.0.1') | |
| 222 | + t.spam! | |
| 223 | + log = File.open('log/test_spammers.log') | |
| 224 | + assert_match "SuggestArticle-id: #{t.id} IP: 192.168.0.1", log.read | |
| 225 | + SpammerLogger.clean_log | |
| 226 | + end | |
| 153 | 227 | |
| 154 | 228 | end | ... | ... |
test/unit/task_test.rb
| ... | ... | @@ -372,6 +372,55 @@ class TaskTest < ActiveSupport::TestCase |
| 372 | 372 | assert_includes Task.closed, canceled |
| 373 | 373 | end |
| 374 | 374 | |
| 375 | + should 'be ham by default' do # ham means not spam | |
| 376 | + assert_equal false, Task.create.spam | |
| 377 | + end | |
| 378 | + | |
| 379 | + should 'be able to mark tasks as spam/ham/unknown' do | |
| 380 | + t = Task.new | |
| 381 | + t.spam = true | |
| 382 | + assert t.spam? | |
| 383 | + assert !t.ham? | |
| 384 | + | |
| 385 | + t.spam = false | |
| 386 | + assert t.ham? | |
| 387 | + assert !t.spam? | |
| 388 | + | |
| 389 | + t.spam = nil | |
| 390 | + assert !t.spam? | |
| 391 | + assert !t.ham? | |
| 392 | + end | |
| 393 | + | |
| 394 | + should 'be able to select non-spam tasks' do | |
| 395 | + t1 = fast_create(Task) | |
| 396 | + t2 = fast_create(Task, :spam => false) | |
| 397 | + t3 = fast_create(Task, :spam => true) | |
| 398 | + | |
| 399 | + assert_equivalent [t1,t2], Task.without_spam | |
| 400 | + end | |
| 401 | + | |
| 402 | + should 'be able to select spam tasks' do | |
| 403 | + t1 = fast_create(Task) | |
| 404 | + t2 = fast_create(Task, :spam => false) | |
| 405 | + t3 = fast_create(Task, :spam => true) | |
| 406 | + | |
| 407 | + assert_equivalent [t3], Task.spam | |
| 408 | + end | |
| 409 | + | |
| 410 | + should 'be able to mark as spam' do | |
| 411 | + t1 = fast_create(Task) | |
| 412 | + t1.spam! | |
| 413 | + t1.reload | |
| 414 | + assert t1.spam? | |
| 415 | + end | |
| 416 | + | |
| 417 | + should 'be able to mark as ham' do | |
| 418 | + t1 = fast_create(Task) | |
| 419 | + t1.ham! | |
| 420 | + t1.reload | |
| 421 | + assert t1.ham? | |
| 422 | + end | |
| 423 | + | |
| 375 | 424 | protected |
| 376 | 425 | |
| 377 | 426 | def sample_user | ... | ... |