diff --git a/app/controllers/my_profile/cms_controller.rb b/app/controllers/my_profile/cms_controller.rb index 0bfa632..c508387 100644 --- a/app/controllers/my_profile/cms_controller.rb +++ b/app/controllers/my_profile/cms_controller.rb @@ -267,7 +267,10 @@ class CmsController < MyProfileController @back_to = params[:back_to] || request.referer || url_for(profile.public_profile_url) @task = SuggestArticle.new(params[:task]) if request.post? - @task.target = profile + @task.target = profile + @task.ip_address = request.remote_ip + @task.user_agent = request.user_agent + @task.referrer = request.referrer if verify_recaptcha(:model => @task, :message => _('Please type the words correctly')) && @task.save session[:notice] = _('Thanks for your suggestion. The community administrators were notified.') redirect_to @back_to diff --git a/app/controllers/my_profile/profile_editor_controller.rb b/app/controllers/my_profile/profile_editor_controller.rb index d42024f..9d26ec2 100644 --- a/app/controllers/my_profile/profile_editor_controller.rb +++ b/app/controllers/my_profile/profile_editor_controller.rb @@ -4,7 +4,7 @@ class ProfileEditorController < MyProfileController protect 'destroy_profile', :profile, :only => [:destroy_profile] def index - @pending_tasks = Task.to(profile).pending.select{|i| user.has_permission?(i.permission, profile)} + @pending_tasks = Task.to(profile).pending.without_spam.select{|i| user.has_permission?(i.permission, profile)} end helper :profile diff --git a/app/controllers/my_profile/spam_controller.rb b/app/controllers/my_profile/spam_controller.rb index 16818c5..0a8aa51 100644 --- a/app/controllers/my_profile/spam_controller.rb +++ b/app/controllers/my_profile/spam_controller.rb @@ -14,9 +14,15 @@ class SpamController < MyProfileController if params[:remove_comment] profile.comments_received.find(params[:remove_comment]).destroy end + if params[:remove_task] + Task.to(profile).find_by_id(params[:remove_task]).destroy + end if params[:mark_comment_as_ham] profile.comments_received.find(params[:mark_comment_as_ham]).ham! end + if params[:mark_task_as_ham] && (t = Task.to(profile).find_by_id(params[:mark_task_as_ham])) + t.ham! + end if request.xhr? json_response(true) else @@ -28,7 +34,8 @@ class SpamController < MyProfileController return end - @spam = profile.comments_received.spam.paginate({:page => params[:page]}) + @comment_spam = profile.comments_received.spam.paginate({:page => params[:comments_page]}) + @task_spam = Task.to(profile).spam.paginate({:page => params[:tasks_page]}) end protected diff --git a/app/controllers/my_profile/tasks_controller.rb b/app/controllers/my_profile/tasks_controller.rb index f257ecf..c52dd97 100644 --- a/app/controllers/my_profile/tasks_controller.rb +++ b/app/controllers/my_profile/tasks_controller.rb @@ -4,12 +4,12 @@ class TasksController < MyProfileController def index @filter = params[:filter_type].blank? ? nil : params[:filter_type] - @tasks = Task.to(profile).pending.of(@filter).order_by('created_at', 'asc').paginate(:per_page => Task.per_page, :page => params[:page]) + @tasks = Task.to(profile).without_spam.pending.of(@filter).order_by('created_at', 'asc').paginate(:per_page => Task.per_page, :page => params[:page]) @failed = params ? params[:failed] : {} end def processed - @tasks = Task.to(profile).closed.sort_by(&:created_at) + @tasks = Task.to(profile).without_spam.closed.sort_by(&:created_at) end VALID_DECISIONS = [ 'finish', 'cancel', 'skip' ] @@ -57,7 +57,7 @@ class TasksController < MyProfileController end def list_requested - @tasks = Task.find_all_by_requestor_id(profile.id) + @tasks = Task.without_spam.find_all_by_requestor_id(profile.id) end def ticket_details diff --git a/app/models/spammer_logger.rb b/app/models/spammer_logger.rb index 5ab87e4..69aaa9f 100644 --- a/app/models/spammer_logger.rb +++ b/app/models/spammer_logger.rb @@ -6,6 +6,8 @@ class SpammerLogger < Logger if object if object.kind_of?(Comment) @logger << "[#{Time.now.strftime('%F %T %z')}] Comment-id: #{object.id} IP: #{spammer_ip}\n" + elsif object.kind_of?(SuggestArticle) + @logger << "[#{Time.now.strftime('%F %T %z')}] SuggestArticle-id: #{object.id} IP: #{spammer_ip}\n" end else @logger << "[#{Time.now.strftime('%F %T %z')}] IP: #{spammer_ip}\n" diff --git a/app/models/suggest_article.rb b/app/models/suggest_article.rb index b9ce5fe..d486323 100644 --- a/app/models/suggest_article.rb +++ b/app/models/suggest_article.rb @@ -11,6 +11,21 @@ class SuggestArticle < Task settings_items :source, :type => String settings_items :source_name, :type => String settings_items :highlighted, :type => :boolean, :default => false + settings_items :ip_address, :type => String + settings_items :user_agent, :type => String + settings_items :referrer, :type => String + + after_create :schedule_spam_checking + + def schedule_spam_checking + self.delay.check_for_spam + end + + include Noosfero::Plugin::HotSpot + + def check_for_spam + plugins.dispatch(:check_suggest_article_for_spam, self) + end def sender "#{name} (#{email})" @@ -61,4 +76,25 @@ class SuggestArticle < Task _('You need to login on %{system} in order to approve or reject this article.') % { :system => target.environment.name } end + def spam! + super + SpammerLogger.log(ip_address, self) + self.delay.marked_as_spam + self + end + + def ham! + super + self.delay.marked_as_ham + self + end + + def marked_as_spam + plugins.dispatch(:suggest_article_marked_as_spam, self) + end + + def marked_as_ham + plugins.dispatch(:suggest_article_marked_as_ham, self) + end + end diff --git a/app/models/task.rb b/app/models/task.rb index b3656c5..cb282db 100644 --- a/app/models/task.rb +++ b/app/models/task.rb @@ -235,6 +235,26 @@ class Task < ActiveRecord::Base end end + def spam? + !spam.nil? && spam + end + + def ham? + !spam.nil? && !spam + end + + def spam! + self.spam = true + self.save! + self + end + + def ham! + self.spam = false + self.save! + self + end + protected # This method must be overrided in subclasses, and its implementation must do @@ -274,6 +294,9 @@ class Task < ActiveRecord::Base named_scope :opened, :conditions => { :status => [Task::Status::ACTIVE, Task::Status::HIDDEN] } named_scope :of, lambda { |type| conditions = type ? "type LIKE '#{type}'" : "1=1"; {:conditions => [conditions]} } named_scope :order_by, lambda { |attribute, ord| {:order => "#{attribute} #{ord}"} } + named_scope :without_spam, :conditions => ['spam IS NULL OR spam = ?', false] + named_scope :spam, :conditions => ['spam = ?', true] + named_scope :to, lambda { |profile| environment_condition = nil diff --git a/app/views/spam/_comment_spam.rhtml b/app/views/spam/_comment_spam.rhtml new file mode 100644 index 0000000..99d33d4 --- /dev/null +++ b/app/views/spam/_comment_spam.rhtml @@ -0,0 +1,11 @@ +<%# FIXME should not need to replicate the article structure like this to be able to use the same formatting as the comments listing %> +
+
+ +
+
+ +<%= pagination_links @comment_spam, :param_name => :comments_page %> + diff --git a/app/views/spam/_suggest_article.html.erb b/app/views/spam/_suggest_article.html.erb new file mode 100644 index 0000000..a414f55 --- /dev/null +++ b/app/views/spam/_suggest_article.html.erb @@ -0,0 +1,21 @@ +<% render :layout => 'task', :locals => { :task => task } do %> + <% content_for :extra_buttons do %> + <%= button_to_function('down', _('Show details'), "toggleDetails(this, '#{_('Hide details')}', '#{_('Show details')}')" ) %> + <% end %> + + <% content_for :extra_content do %> + + <% end %> +<% end %> diff --git a/app/views/spam/_task.rhtml b/app/views/spam/_task.rhtml new file mode 100644 index 0000000..e1ca894 --- /dev/null +++ b/app/views/spam/_task.rhtml @@ -0,0 +1,18 @@ +
+ <%= render :partial => 'tasks/task_icon', :locals => {:task => task} %> + <%= render :partial => 'tasks/task_title', :locals => {:task => task} %> +
+ <%= task_information(task) %> +
+ + <%= yield %> <% # ??? %> + + <% button_bar do %> + <%= 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}"]) %> + <%= yield :extra_buttons %> + <%= 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]) %> + + <% end %> + + <%= yield :extra_content %> +
diff --git a/app/views/spam/_task_spam.rhtml b/app/views/spam/_task_spam.rhtml new file mode 100644 index 0000000..c019218 --- /dev/null +++ b/app/views/spam/_task_spam.rhtml @@ -0,0 +1,4 @@ +<% @task_spam.each do |t| %> + <%= render :partial => partial_for_class(t.class), :locals => { :task => t } %> +<% end %> +<%= pagination_links @task_spam, :param_name => :tasks_page %> diff --git a/app/views/spam/index.rhtml b/app/views/spam/index.rhtml index 26d6a5d..38431a4 100644 --- a/app/views/spam/index.rhtml +++ b/app/views/spam/index.rhtml @@ -1,3 +1,5 @@ +<%= stylesheet('tasks') %> +

<%= _('Manage SPAM') %>

<% button_bar do %> @@ -5,16 +7,21 @@ <% end %> <%# FIXME should not need to replicate the article structure like this to be able to use the same formatting as the comments listing %> -
-
- -
-
-<%= pagination_links @spam %> +<% if @task_spam.length > 0 %> + <% tabs = [] %> + <% tabs << {:title => _('Comment Spam'), :id => 'comment-spam', + :content => (render :partial => 'comment_spam')} %> + <% tabs << {:title => _('Task Spam'), :id => 'task-spam', + :content => (render :partial => 'task_spam') } %> + <%= render_tabs(tabs) %> +<% else %> + <%= render :partial => 'comment_spam' %> +<% end %> + <% button_bar do %> <%= button :back, _('Back to control panel'), :controller => :profile_editor %> <% end %> + +<%= javascript_include_tag 'spam' %> diff --git a/app/views/tasks/_task.rhtml b/app/views/tasks/_task.rhtml index 2d5f611..6c15fe5 100644 --- a/app/views/tasks/_task.rhtml +++ b/app/views/tasks/_task.rhtml @@ -1,23 +1,6 @@
-
- <% - icon_info = task.icon - if icon_info[:type] == :profile_image - icon = profile_image(icon_info[:profile], :minor) - elsif icon_info[:type] == :defined_image - icon = "#{icon_info[:name]}" - end - %> - <%= - if icon_info[:url] - link_to(icon, icon_info[:url]) - else - icon - end - %> - -
+ <%= render :partial => 'task_icon', :locals => {:task => task} %>
<%= @@ -39,9 +22,7 @@ %>
- - <%= task.title %> - + <%= render :partial => 'task_title', :locals => {:task => task} %>
<%= task_information(task) %> diff --git a/app/views/tasks/_task_icon.rhtml b/app/views/tasks/_task_icon.rhtml new file mode 100644 index 0000000..be67daf --- /dev/null +++ b/app/views/tasks/_task_icon.rhtml @@ -0,0 +1,16 @@ +<% + icon_info = task.icon + if icon_info[:type] == :profile_image + icon = profile_image(icon_info[:profile], :minor) + elsif icon_info[:type] == :defined_image + icon = "#{icon_info[:name]}" + end + + if icon_info[:url] + icon = link_to(icon, icon_info[:url]) + end +%> + +
+ <%= icon %> +
diff --git a/app/views/tasks/_task_title.rhtml b/app/views/tasks/_task_title.rhtml new file mode 100644 index 0000000..3ec1f41 --- /dev/null +++ b/app/views/tasks/_task_title.rhtml @@ -0,0 +1,3 @@ + + <%= task.title %> + diff --git a/db/migrate/20131011164400_add_spam_to_task.rb b/db/migrate/20131011164400_add_spam_to_task.rb new file mode 100644 index 0000000..fe19894 --- /dev/null +++ b/db/migrate/20131011164400_add_spam_to_task.rb @@ -0,0 +1,13 @@ +class AddSpamToTask < ActiveRecord::Migration + def self.up + change_table :tasks do |t| + t.boolean :spam, :default => false + end + Task.update_all ["spam = ?", false] + add_index :tasks, [:spam] + end + + def self.down + remove_column :tasks, :spam + end +end diff --git a/db/schema.rb b/db/schema.rb index 2265a57..f1bdd67 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -9,7 +9,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20130711213046) do +ActiveRecord::Schema.define(:version => 20131011164400) do create_table "abuse_reports", :force => true do |t| t.integer "reporter_id" @@ -233,6 +233,50 @@ ActiveRecord::Schema.define(:version => 20130711213046) do t.datetime "updated_at" end + create_table "custom_forms_plugin_answers", :force => true do |t| + t.text "value" + t.integer "field_id" + t.integer "submission_id" + end + + create_table "custom_forms_plugin_fields", :force => true do |t| + t.string "name" + t.string "slug" + t.string "type" + t.string "default_value" + t.string "choices" + t.float "minimum" + t.float "maximum" + t.integer "form_id" + t.boolean "mandatory", :default => false + t.boolean "multiple" + t.boolean "list" + t.integer "position", :default => 0 + end + + create_table "custom_forms_plugin_forms", :force => true do |t| + t.string "name" + t.string "slug" + t.text "description" + t.integer "profile_id" + t.datetime "begining" + t.datetime "ending" + t.boolean "report_submissions", :default => false + t.boolean "on_membership", :default => false + t.string "access" + t.datetime "created_at" + t.datetime "updated_at" + end + + create_table "custom_forms_plugin_submissions", :force => true do |t| + t.string "author_name" + t.string "author_email" + t.integer "profile_id" + t.integer "form_id" + t.datetime "created_at" + t.datetime "updated_at" + end + create_table "delayed_jobs", :force => true do |t| t.integer "priority", :default => 0 t.integer "attempts", :default => 0 @@ -547,8 +591,11 @@ ActiveRecord::Schema.define(:version => 20130711213046) do t.datetime "created_at" t.string "target_type" t.integer "image_id" + t.boolean "spam", :default => false end + add_index "tasks", ["spam"], :name => "index_tasks_on_spam" + create_table "thumbnails", :force => true do |t| t.integer "size" t.string "content_type" diff --git a/plugins/anti_spam/lib/anti_spam_plugin.rb b/plugins/anti_spam/lib/anti_spam_plugin.rb index 5371ca9..fbb370c 100644 --- a/plugins/anti_spam/lib/anti_spam_plugin.rb +++ b/plugins/anti_spam/lib/anti_spam_plugin.rb @@ -5,7 +5,7 @@ class AntiSpamPlugin < Noosfero::Plugin end def self.plugin_description - _("Checks comments against a spam checking service compatible with the Akismet API") + _("Tests comments and suggested articles against a spam checking service compatible with the Akismet API") end def self.host_default_setting @@ -13,30 +13,44 @@ class AntiSpamPlugin < Noosfero::Plugin end def check_comment_for_spam(comment) - if rakismet_call(comment, :spam?) + if rakismet_call AntiSpamPlugin::CommentWrapper.new(comment), comment.environment, :spam? comment.spam = true comment.save! end end def comment_marked_as_spam(comment) - rakismet_call(comment, :spam!) + rakismet_call AntiSpamPlugin::CommentWrapper.new(comment), comment.environment, :spam! end def comment_marked_as_ham(comment) - rakismet_call(comment, :ham!) + rakismet_call AntiSpamPlugin::CommentWrapper.new(comment), comment.environment, :ham! + end + + def check_suggest_article_for_spam(suggest_article) + if rakismet_call AntiSpamPlugin::SuggestArticleWrapper.new(suggest_article), suggest_article.environment, :spam? + suggest_article.spam = true + suggest_article.save! + end + end + + def suggest_article_marked_as_spam(suggest_article) + rakismet_call AntiSpamPlugin::SuggestArticleWrapper.new(suggest_article), suggest_article.environment, :spam! + end + + def suggest_article_marked_as_ham(suggest_article) + rakismet_call AntiSpamPlugin::SuggestArticleWrapper.new(suggest_article), suggest_article.environment, :ham! end protected - def rakismet_call(comment, op) - settings = Noosfero::Plugin::Settings.new(comment.environment, self.class) + def rakismet_call(submission, environment, op) + settings = Noosfero::Plugin::Settings.new(environment, self.class) Rakismet.host = settings.host Rakismet.key = settings.api_key - Rakismet.url = comment.environment.top_url + Rakismet.url = environment.top_url - submission = AntiSpamPlugin::CommentWrapper.new(comment) submission.send(op) end diff --git a/plugins/anti_spam/lib/anti_spam_plugin/suggest_article_wrapper.rb b/plugins/anti_spam/lib/anti_spam_plugin/suggest_article_wrapper.rb new file mode 100644 index 0000000..5bb01e2 --- /dev/null +++ b/plugins/anti_spam/lib/anti_spam_plugin/suggest_article_wrapper.rb @@ -0,0 +1,12 @@ +class AntiSpamPlugin::SuggestArticleWrapper < Struct.new(:suggest_article) + + delegate :name, :email, :article_body, :ip_address, :user_agent, :referrer, :to => :suggest_article + + include Rakismet::Model + + alias :author :name + alias :author_email :email + alias :user_ip :ip_address + alias :content :article_body + +end diff --git a/plugins/anti_spam/test/unit/anti_spam_plugin/suggest_article_wrapper_test.rb b/plugins/anti_spam/test/unit/anti_spam_plugin/suggest_article_wrapper_test.rb new file mode 100644 index 0000000..6b0b68c --- /dev/null +++ b/plugins/anti_spam/test/unit/anti_spam_plugin/suggest_article_wrapper_test.rb @@ -0,0 +1,45 @@ +require 'test_helper' + +class AntiSpamPluginCommentWrapperTest < ActiveSupport::TestCase + + def setup + @suggest_article = SuggestArticle.new( + :article_body => 'comment body', + :name => 'author', + :email => 'foo@example.com', + :ip_address => '1.2.3.4', + :user_agent => 'Some Good Browser (I hope)', + :referrer => 'http://noosfero.org/' + ) + @wrapper = AntiSpamPlugin::SuggestArticleWrapper.new(@suggest_article) + end + + should 'use Rakismet::Model' do + assert_includes @wrapper.class.included_modules, Rakismet::Model + end + + should 'get contents' do + assert_equal @suggest_article.article_body, @wrapper.content + end + + should 'get author name' do + assert_equal @suggest_article.name, @wrapper.author + end + + should 'get author email' do + assert_equal @suggest_article.email, @wrapper.author_email + end + + should 'get IP address' do + assert_equal @suggest_article.ip_address, @wrapper.user_ip + end + + should 'get User-Agent' do + assert_equal @suggest_article.user_agent, @wrapper.user_agent + end + + should 'get get Referrer' do + assert_equal @suggest_article.referrer, @wrapper.referrer + end + +end diff --git a/plugins/anti_spam/test/unit/anti_spam_plugin_test.rb b/plugins/anti_spam/test/unit/anti_spam_plugin_test.rb index 74629ee..22ce6d5 100644 --- a/plugins/anti_spam/test/unit/anti_spam_plugin_test.rb +++ b/plugins/anti_spam/test/unit/anti_spam_plugin_test.rb @@ -7,6 +7,11 @@ class AntiSpamPluginTest < ActiveSupport::TestCase article = fast_create(TextileArticle, :profile_id => profile.id) @comment = fast_create(Comment, :source_id => article.id, :source_type => 'Article') + + @suggest_article = SuggestArticle.new(:target_id => profile.id, :target_type => 'Profile', :article_name => 'article', :article_body => 'lorem ipsum', :email => 'invalid@example.com', :name => 'article') + + @suggest_article.save! + @settings = Noosfero::Plugin::Settings.new(@comment.environment, AntiSpamPlugin) @settings.api_key = 'b8b80ddb8084062d0c9119c945ce3bc3' @settings.save! @@ -23,14 +28,32 @@ class AntiSpamPluginTest < ActiveSupport::TestCase assert @comment.spam end - should 'report spam' do + should 'report comment spam' do AntiSpamPlugin::CommentWrapper.any_instance.expects(:spam!) @plugin.comment_marked_as_spam(@comment) end - should 'report ham' do + should 'report comment ham' do AntiSpamPlugin::CommentWrapper.any_instance.expects(:ham!) @plugin.comment_marked_as_ham(@comment) end + should 'check for spam and mark suggest_article as spam if server says it is spam' do + AntiSpamPlugin::SuggestArticleWrapper.any_instance.expects(:spam?).returns(true) + @suggest_article.expects(:save!) + + @plugin.check_suggest_article_for_spam(@suggest_article) + assert @suggest_article.spam + end + + should 'report suggest_article spam' do + AntiSpamPlugin::SuggestArticleWrapper.any_instance.expects(:spam!) + @plugin.suggest_article_marked_as_spam(@suggest_article) + end + + should 'report suggest_article ham' do + AntiSpamPlugin::SuggestArticleWrapper.any_instance.expects(:ham!) + @plugin.suggest_article_marked_as_ham(@suggest_article) + end + end diff --git a/public/javascripts/spam.js b/public/javascripts/spam.js new file mode 100644 index 0000000..79bb166 --- /dev/null +++ b/public/javascripts/spam.js @@ -0,0 +1,28 @@ +function removeTaskBox(button, url, task_box_id, msg) { + var $ = jQuery; + if (msg && !confirm(msg)) { + return; + } + button = $(button); + button.addClass('task-button-loading'); + $.post(url, function (data) { + if (data.ok) { + $('#' + task_box_id).slideUp(); + } else { + button.removeClass('task-button-loading'); + button.addClass('task-button-failure'); + } + }); +} + +function toggleDetails(link, msg_hide, msg_show) { + var $ = jQuery; + $(link).toggleClass('icon-up icon-down'); + details = $(link).closest('.task_box').find('.suggest-article-details'); + if (details.css('display') == 'none') { + link.innerHTML = msg_hide; + } else { + link.innerHTML = msg_show; + } + details.slideToggle(); +} diff --git a/test/functional/spam_controller_test.rb b/test/functional/spam_controller_test.rb index 0337dc1..6b19650 100644 --- a/test/functional/spam_controller_test.rb +++ b/test/functional/spam_controller_test.rb @@ -4,37 +4,55 @@ class SpamControllerTest < ActionController::TestCase def setup @profile = create_user.person - @article = fast_create(TextileArticle, :profile_id => @profile.id) - @spam = fast_create(Comment, :source_id => @article.id, :spam => true, :name => 'foo', :email => 'foo@example.com') + @community = fast_create(Community, :name => 'testcommunity') + @community.add_admin(@profile) + @article = fast_create(TextileArticle, :profile_id => @community.id) + @spam_comment = fast_create(Comment, :source_id => @article.id, :spam => true, :name => 'foo', :email => 'foo@example.com') + + @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) login_as @profile.identifier end - test "should only list spammy comments" do + test "should only list spammy comments and spammy suggest articles" do ham = fast_create(Comment, :source_id => @article.id) - get :index, :profile => @profile.identifier + get :index, :profile => @community.identifier - assert_equivalent [@spam], assigns(:spam) + assert_equivalent [@spam_comment], assigns(:comment_spam) + assert_equivalent [@spam_suggest_article], assigns(:task_spam) end test "should mark comments as ham" do - post :index, :profile => @profile.identifier, :mark_comment_as_ham => @spam.id + post :index, :profile => @community.identifier, :mark_comment_as_ham => @spam_comment.id + + @spam_comment.reload + assert @spam_comment.ham? + end + + test "should mark suggest article as ham" do + post :index, :profile => @community.identifier, :mark_task_as_ham => @spam_suggest_article.id - @spam.reload - assert @spam.ham? + @spam_suggest_article.reload + assert @spam_suggest_article.ham? end test "should remove comments" do - post :index, :profile => @profile.identifier, :remove_comment => @spam.id + post :index, :profile => @community.identifier, :remove_comment => @spam_comment.id + + assert !Comment.exists?(@spam_comment.id) + end + + test "should remove suggest articles" do + post :index, :profile => @community.identifier, :remove_task => @spam_suggest_article.id - assert !Comment.exists?(@spam.id) + assert !SuggestArticle.exists?(@spam_suggest_article.id) end should 'properly render spam that have replies' do - reply_spam = fast_create(Comment, :source_id => @article_id, :reply_of_id => @spam.id) + reply_spam = fast_create(Comment, :source_id => @article_id, :reply_of_id => @spam_comment.id) - get :index, :profile => @profile.identifier + get :index, :profile => @community.identifier assert_response :success end diff --git a/test/functional/tasks_controller_test.rb b/test/functional/tasks_controller_test.rb index 590b0d7..f7eb840 100644 --- a/test/functional/tasks_controller_test.rb +++ b/test/functional/tasks_controller_test.rb @@ -38,6 +38,17 @@ class TasksControllerTest < ActionController::TestCase assert_kind_of Array, assigns(:tasks) end + should 'list pending tasks without spam' do + requestor = fast_create(Person) + task_spam = Task.create!(:requestor => requestor, :target => profile, :spam => true) + task_ham = Task.create!(:requestor => requestor, :target => profile, :spam => false) + + get :index + assert_response :success + assert_includes assigns(:tasks), task_ham + assert_not_includes assigns(:tasks), task_spam + end + should 'list processed tasks' do get :processed @@ -46,6 +57,17 @@ class TasksControllerTest < ActionController::TestCase assert_kind_of Array, assigns(:tasks) end + should 'list processed tasks without spam' do + requestor = fast_create(Person) + task_spam = Task.create!(:status => Task::Status::FINISHED, :requestor => requestor, :target => profile, :spam => true) + task_ham = Task.create!(:status => Task::Status::FINISHED, :requestor => requestor, :target => profile, :spam => false) + + get :processed + assert_response :success + assert_includes assigns(:tasks), task_ham + assert_not_includes assigns(:tasks), task_spam + end + should 'be able to finish a task' do t = profile.tasks.build; t.save! @@ -140,6 +162,15 @@ class TasksControllerTest < ActionController::TestCase assert_includes assigns(:tasks), task end + should 'list tasks that this profile created without spam' do + task_spam = Ticket.create!(:name => 'test', :requestor => profile, :spam => true) + task_ham = Ticket.create!(:name => 'test', :requestor => profile, :spam => false) + get :list_requested, :profile => profile.identifier + + assert_includes assigns(:tasks), task_ham + assert_not_includes assigns(:tasks), task_spam + end + should 'set target of ticket when creating it' do f = create_user('friend').person profile.add_friend f diff --git a/test/unit/suggest_article_test.rb b/test/unit/suggest_article_test.rb index 7381687..bddee59 100644 --- a/test/unit/suggest_article_test.rb +++ b/test/unit/suggest_article_test.rb @@ -150,5 +150,79 @@ class SuggestArticleTest < ActiveSupport::TestCase assert_match(/#{task.name}.*suggested the publication of the article: #{task.subject}/, email.subject) end + class EverythingIsSpam < Noosfero::Plugin + def check_suggest_article_for_spam(suggest_article) + suggest_article.spam! + end + end + + should 'delegate spam detection to plugins' do + Environment.default.enable_plugin(EverythingIsSpam) + + t1 = build(SuggestArticle, :target => @profile, :article_name => 'suggested article', :name => 'johndoe', :email => 'johndoe@example.com') + + EverythingIsSpam.any_instance.expects(:check_suggest_article_for_spam) + + t1.check_for_spam + end + + class SpamNotification < Noosfero::Plugin + class << self + attr_accessor :marked_as_spam + attr_accessor :marked_as_ham + end + + def check_suggest_article_for_spam(c) + # do nothing + end + + def suggest_article_marked_as_spam(c) + self.class.marked_as_spam = c + end + + def suggest_article_marked_as_ham(c) + self.class.marked_as_ham = c + end + end + + should 'notify plugins of suggest_articles being marked as spam' do + Environment.default.enable_plugin(SpamNotification) + + t = SuggestArticle.create!(:target => @profile, :article_name => 'suggested article', :name => 'johndoe', :article_body => 'wanna feel my body? my body baaaby', :email => 'johndoe@example.com') + + t.spam! + process_delayed_job_queue + + assert_equal t, SpamNotification.marked_as_spam + end + + should 'notify plugins of suggest_articles being marked as ham' do + Environment.default.enable_plugin(SpamNotification) + + t = SuggestArticle.create!(:target => @profile, :article_name => 'suggested article', :name => 'johndoe', :article_body => 'wanna feel my body? my body baaaby', :email => 'johndoe@example.com') + + t.ham! + process_delayed_job_queue + + assert_equal t, SpamNotification.marked_as_ham + end + + should 'store User-Agent' do + t = SuggestArticle.new(:user_agent => 'foo') + assert_equal 'foo', t.user_agent + end + + should 'store referrer' do + t = SuggestArticle.new(:referrer => 'bar') + assert_equal 'bar', t.referrer + end + + should 'log spammer ip after marking comment as spam' do + 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') + t.spam! + log = File.open('log/test_spammers.log') + assert_match "SuggestArticle-id: #{t.id} IP: 192.168.0.1", log.read + SpammerLogger.clean_log + end end diff --git a/test/unit/task_test.rb b/test/unit/task_test.rb index 80ab1c1..958a440 100644 --- a/test/unit/task_test.rb +++ b/test/unit/task_test.rb @@ -372,6 +372,55 @@ class TaskTest < ActiveSupport::TestCase assert_includes Task.closed, canceled end + should 'be ham by default' do # ham means not spam + assert_equal false, Task.create.spam + end + + should 'be able to mark tasks as spam/ham/unknown' do + t = Task.new + t.spam = true + assert t.spam? + assert !t.ham? + + t.spam = false + assert t.ham? + assert !t.spam? + + t.spam = nil + assert !t.spam? + assert !t.ham? + end + + should 'be able to select non-spam tasks' do + t1 = fast_create(Task) + t2 = fast_create(Task, :spam => false) + t3 = fast_create(Task, :spam => true) + + assert_equivalent [t1,t2], Task.without_spam + end + + should 'be able to select spam tasks' do + t1 = fast_create(Task) + t2 = fast_create(Task, :spam => false) + t3 = fast_create(Task, :spam => true) + + assert_equivalent [t3], Task.spam + end + + should 'be able to mark as spam' do + t1 = fast_create(Task) + t1.spam! + t1.reload + assert t1.spam? + end + + should 'be able to mark as ham' do + t1 = fast_create(Task) + t1.ham! + t1.reload + assert t1.ham? + end + protected def sample_user -- libgit2 0.21.2