Commit ba181565 authored by Chad Woolley's avatar Chad Woolley Committed by Stan Hu

Fix spam detection with Akismet client

Fix referrer option passed to Akismet client, it
was changed to an unsupported spelling in a
previous commit.

See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52385#note_591568296

- It needs 'referrer', not 'referer'
- Improve error handling to no longer ignore ArgumentError
- Give different error messages for Akismet::Error
  vs. StandardError.

Changelog: fixed
parent d7dbbbae
...@@ -20,14 +20,18 @@ module Spam ...@@ -20,14 +20,18 @@ module Spam
created_at: DateTime.current, created_at: DateTime.current,
author: owner_name, author: owner_name,
author_email: owner_email, author_email: owner_email,
referer: options[:referer] referrer: options[:referer]
} }
begin begin
is_spam, is_blatant = akismet_client.check(options[:ip_address], options[:user_agent], params) is_spam, is_blatant = akismet_client.check(options[:ip_address], options[:user_agent], params)
is_spam || is_blatant is_spam || is_blatant
rescue ArgumentError => e
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e)
false
rescue StandardError => e rescue StandardError => e
Gitlab::AppLogger.error("Unable to connect to Akismet: #{e}, skipping check") Gitlab::ErrorTracking.track_exception(e)
Gitlab::AppLogger.error("Error during Akismet spam check, flagging as not spam: #{e}")
false false
end end
end end
......
...@@ -4,12 +4,15 @@ require 'spec_helper' ...@@ -4,12 +4,15 @@ require 'spec_helper'
RSpec.describe Spam::AkismetService do RSpec.describe Spam::AkismetService do
let(:fake_akismet_client) { double(:akismet_client) } let(:fake_akismet_client) { double(:akismet_client) }
let(:ip) { '1.2.3.4' }
let(:user_agent) { 'some user_agent' }
let(:referer) { 'some referer' }
let_it_be(:text) { "Would you like to buy some tinned meat product?" } let_it_be(:text) { "Would you like to buy some tinned meat product?" }
let_it_be(:spam_owner) { create(:user) } let_it_be(:spam_owner) { create(:user) }
subject do subject do
options = { ip_address: '1.2.3.4', user_agent: 'some user_agent', referrer: 'some referrer' } options = { ip_address: ip, user_agent: user_agent, referer: referer }
described_class.new(spam_owner.name, spam_owner.email, text, options) described_class.new(spam_owner.name, spam_owner.email, text, options)
end end
...@@ -56,6 +59,21 @@ RSpec.describe Spam::AkismetService do ...@@ -56,6 +59,21 @@ RSpec.describe Spam::AkismetService do
it_behaves_like 'no activity if Akismet is not enabled', :spam?, :check it_behaves_like 'no activity if Akismet is not enabled', :spam?, :check
context 'if Akismet is enabled' do context 'if Akismet is enabled' do
it 'correctly transforms options for the akismet client' do
expected_check_params = {
type: 'comment',
text: text,
created_at: anything,
author: spam_owner.name,
author_email: spam_owner.email,
# NOTE: The akismet_client needs the option to be named `:referrer`, not `:referer`
referrer: referer
}
expect(fake_akismet_client).to receive(:check).with(ip, user_agent, expected_check_params)
subject.spam?
end
context 'the text is spam' do context 'the text is spam' do
before do before do
allow(fake_akismet_client).to receive(:check).and_return([true, false]) allow(fake_akismet_client).to receive(:check).and_return([true, false])
...@@ -86,19 +104,31 @@ RSpec.describe Spam::AkismetService do ...@@ -86,19 +104,31 @@ RSpec.describe Spam::AkismetService do
end end
end end
context 'if Akismet is not available' do describe 'error handling' do
before do before do
allow(fake_akismet_client).to receive(:check).and_raise(StandardError.new("oh noes!")) allow(fake_akismet_client).to receive(:check).and_raise(error)
end end
specify do context 'StandardError other than ArgumentError is raised' do
expect(subject.spam?).to be_falsey let(:error) { Akismet::Error.new("Lovely spam! Wonderful spam!") }
specify do
expect(subject.spam?).to be_falsey
end
it 'logs an error' do
expect(Gitlab::AppLogger).to receive(:error).with(/Error during Akismet.*flagging as not spam.*Lovely spam/)
subject.spam?
end
end end
it 'logs an error' do context 'ArgumentError is raised in dev' do
expect(Gitlab::AppLogger).to receive(:error).with(/skipping check/) let(:error) { ArgumentError }
subject.spam? it 'raises original error' do
expect { subject.spam? }.to raise_error(error)
end
end end
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment