Commit db8dc95f authored by Kerri Miller's avatar Kerri Miller

Merge branch 'jwanjohi-spamcheck-monitor-mode' into 'master'

Get extra attributes from Spamcheck response and determine verdict [RUN ALL RSPEC][RUN AS-IF-FOSS]

See merge request gitlab-org/gitlab!60915
parents e1277411 fd501ec4
...@@ -15,11 +15,17 @@ module Spam ...@@ -15,11 +15,17 @@ module Spam
def execute def execute
spamcheck_result = nil spamcheck_result = nil
spamcheck_attribs = {}
external_spam_check_round_trip_time = Benchmark.realtime do external_spam_check_round_trip_time = Benchmark.realtime do
spamcheck_result = spamcheck_verdict spamcheck_result, spamcheck_attribs = spamcheck_verdict
end end
# assign result to a var and log it before reassigning to nil when monitorMode is true
original_spamcheck_result = spamcheck_result
spamcheck_result = nil if spamcheck_attribs&.fetch("monitorMode", "false") == "true"
akismet_result = akismet_verdict akismet_result = akismet_verdict
# filter out anything we don't recognise, including nils. # filter out anything we don't recognise, including nils.
...@@ -33,7 +39,8 @@ module Spam ...@@ -33,7 +39,8 @@ module Spam
logger.info(class: self.class.name, logger.info(class: self.class.name,
akismet_verdict: akismet_verdict, akismet_verdict: akismet_verdict,
spam_check_verdict: spamcheck_result, spam_check_verdict: original_spamcheck_result,
extra_attributes: spamcheck_attribs,
spam_check_rtt: external_spam_check_round_trip_time.real, spam_check_rtt: external_spam_check_round_trip_time.real,
final_verdict: final_verdict, final_verdict: final_verdict,
username: user.username, username: user.username,
...@@ -61,21 +68,23 @@ module Spam ...@@ -61,21 +68,23 @@ module Spam
return unless Gitlab::CurrentSettings.spam_check_endpoint_enabled return unless Gitlab::CurrentSettings.spam_check_endpoint_enabled
begin begin
result, _error = spamcheck_client.issue_spam?(spam_issue: target, user: user, context: context) result, attribs, _error = spamcheck_client.issue_spam?(spam_issue: target, user: user, context: context)
return unless result return [nil, attribs] unless result
# @TODO log if error is not nil https://gitlab.com/gitlab-org/gitlab/-/issues/329545 # @TODO log if error is not nil https://gitlab.com/gitlab-org/gitlab/-/issues/329545
return [result, attribs] if result == NOOP || attribs["monitorMode"] == "true"
# Duplicate logic with Akismet logic in #akismet_verdict # Duplicate logic with Akismet logic in #akismet_verdict
if Gitlab::Recaptcha.enabled? && result != ALLOW if Gitlab::Recaptcha.enabled? && result != ALLOW
CONDITIONAL_ALLOW [CONDITIONAL_ALLOW, attribs]
else else
result [result, attribs]
end end
rescue StandardError => e rescue StandardError => e
Gitlab::ErrorTracking.log_exception(e) Gitlab::ErrorTracking.log_exception(e)
# Default to ALLOW if any errors occur # Default to ALLOW if any errors occur
ALLOW [ALLOW, attribs]
end end
end end
......
...@@ -45,7 +45,7 @@ module Gitlab ...@@ -45,7 +45,7 @@ module Gitlab
metadata: { 'authorization' => metadata: { 'authorization' =>
Gitlab::CurrentSettings.spam_check_api_key }) Gitlab::CurrentSettings.spam_check_api_key })
verdict = convert_verdict_to_gitlab_constant(response.verdict) verdict = convert_verdict_to_gitlab_constant(response.verdict)
[verdict, response.error] [verdict, response.extra_attributes.to_h, response.error]
end end
private private
......
...@@ -9,12 +9,20 @@ RSpec.describe Gitlab::Spamcheck::Client do ...@@ -9,12 +9,20 @@ RSpec.describe Gitlab::Spamcheck::Client do
let_it_be(:user) { create(:user, organization: 'GitLab') } let_it_be(:user) { create(:user, organization: 'GitLab') }
let(:verdict_value) { nil } let(:verdict_value) { nil }
let(:error_value) { "" } let(:error_value) { "" }
let(:attribs_value) do
extra_attributes = Google::Protobuf::Map.new(:string, :string)
extra_attributes["monitorMode"] = "false"
extra_attributes
end
let_it_be(:issue) { create(:issue, description: 'Test issue description') } let_it_be(:issue) { create(:issue, description: 'Test issue description') }
let(:response) do let(:response) do
verdict = ::Spamcheck::SpamVerdict.new verdict = ::Spamcheck::SpamVerdict.new
verdict.verdict = verdict_value verdict.verdict = verdict_value
verdict.error = error_value verdict.error = error_value
verdict.extra_attributes = attribs_value
verdict verdict
end end
...@@ -45,7 +53,7 @@ RSpec.describe Gitlab::Spamcheck::Client do ...@@ -45,7 +53,7 @@ RSpec.describe Gitlab::Spamcheck::Client do
let(:verdict_value) { verdict } let(:verdict_value) { verdict }
it "returns expected spam constant" do it "returns expected spam constant" do
expect(subject).to eq([expected, ""]) expect(subject).to eq([expected, { "monitorMode" => "false" }, ""])
end end
end end
end end
......
...@@ -23,12 +23,17 @@ RSpec.describe Spam::SpamVerdictService do ...@@ -23,12 +23,17 @@ RSpec.describe Spam::SpamVerdictService do
described_class.new(user: user, target: issue, request: request, options: {}) described_class.new(user: user, target: issue, request: request, options: {})
end end
let(:attribs) do
extra_attributes = { "monitorMode" => "false" }
extra_attributes
end
describe '#execute' do describe '#execute' do
subject { service.execute } subject { service.execute }
before do before do
allow(service).to receive(:akismet_verdict).and_return(nil) allow(service).to receive(:akismet_verdict).and_return(nil)
allow(service).to receive(:spamcheck_verdict).and_return(nil) allow(service).to receive(:spamcheck_verdict).and_return([nil, attribs])
end end
context 'if all services return nil' do context 'if all services return nil' do
...@@ -63,7 +68,7 @@ RSpec.describe Spam::SpamVerdictService do ...@@ -63,7 +68,7 @@ RSpec.describe Spam::SpamVerdictService do
context 'and they are supported' do context 'and they are supported' do
before do before do
allow(service).to receive(:akismet_verdict).and_return(DISALLOW) allow(service).to receive(:akismet_verdict).and_return(DISALLOW)
allow(service).to receive(:spamcheck_verdict).and_return(BLOCK_USER) allow(service).to receive(:spamcheck_verdict).and_return([BLOCK_USER, attribs])
end end
it 'renders the more restrictive verdict' do it 'renders the more restrictive verdict' do
...@@ -74,7 +79,7 @@ RSpec.describe Spam::SpamVerdictService do ...@@ -74,7 +79,7 @@ RSpec.describe Spam::SpamVerdictService do
context 'and one is supported' do context 'and one is supported' do
before do before do
allow(service).to receive(:akismet_verdict).and_return('nonsense') allow(service).to receive(:akismet_verdict).and_return('nonsense')
allow(service).to receive(:spamcheck_verdict).and_return(BLOCK_USER) allow(service).to receive(:spamcheck_verdict).and_return([BLOCK_USER, attribs])
end end
it 'renders the more restrictive verdict' do it 'renders the more restrictive verdict' do
...@@ -85,13 +90,29 @@ RSpec.describe Spam::SpamVerdictService do ...@@ -85,13 +90,29 @@ RSpec.describe Spam::SpamVerdictService do
context 'and none are supported' do context 'and none are supported' do
before do before do
allow(service).to receive(:akismet_verdict).and_return('nonsense') allow(service).to receive(:akismet_verdict).and_return('nonsense')
allow(service).to receive(:spamcheck_verdict).and_return('rubbish') allow(service).to receive(:spamcheck_verdict).and_return(['rubbish', attribs])
end end
it 'renders the more restrictive verdict' do it 'renders the more restrictive verdict' do
expect(subject).to eq ALLOW expect(subject).to eq ALLOW
end end
end end
context 'and attribs - monitorMode is true' do
let(:attribs) do
extra_attributes = { "monitorMode" => "true" }
extra_attributes
end
before do
allow(service).to receive(:akismet_verdict).and_return(DISALLOW)
allow(service).to receive(:spamcheck_verdict).and_return([BLOCK_USER, attribs])
end
it 'renders the more restrictive verdict' do
expect(subject).to eq(DISALLOW)
end
end
end end
end end
...@@ -170,16 +191,42 @@ RSpec.describe Spam::SpamVerdictService do ...@@ -170,16 +191,42 @@ RSpec.describe Spam::SpamVerdictService do
let(:error) { '' } let(:error) { '' }
let(:verdict) { nil } let(:verdict) { nil }
let(:attribs) do
extra_attributes = { "monitorMode" => "false" }
extra_attributes
end
before do before do
allow(service).to receive(:spamcheck_client).and_return(spam_client) allow(service).to receive(:spamcheck_client).and_return(spam_client)
allow(spam_client).to receive(:issue_spam?).and_return([verdict, error]) allow(spam_client).to receive(:issue_spam?).and_return([verdict, attribs, error])
end
context 'if the result is a NOOP verdict' do
let(:verdict) { NOOP }
it 'returns the verdict' do
expect(subject).to eq([NOOP, attribs])
end
end
context 'if attribs - monitorMode is true' do
let(:attribs) do
extra_attributes = { "monitorMode" => "true" }
extra_attributes
end
let(:verdict) { ALLOW }
it 'returns the verdict' do
expect(subject).to eq([ALLOW, attribs])
end
end end
context 'the result is a valid verdict' do context 'the result is a valid verdict' do
let(:verdict) { ALLOW } let(:verdict) { ALLOW }
it 'returns the verdict' do it 'returns the verdict' do
expect(subject).to eq ALLOW expect(subject).to eq([ALLOW, attribs])
end end
end end
...@@ -203,7 +250,7 @@ RSpec.describe Spam::SpamVerdictService do ...@@ -203,7 +250,7 @@ RSpec.describe Spam::SpamVerdictService do
let(:verdict) { verdict_value } let(:verdict) { verdict_value }
it "returns expected spam constant" do it "returns expected spam constant" do
expect(subject).to eq(expected) expect(subject).to eq([expected, attribs])
end end
end end
end end
...@@ -218,7 +265,7 @@ RSpec.describe Spam::SpamVerdictService do ...@@ -218,7 +265,7 @@ RSpec.describe Spam::SpamVerdictService do
::Spam::SpamConstants::DISALLOW, ::Spam::SpamConstants::DISALLOW,
::Spam::SpamConstants::BLOCK_USER].each do |verdict_value| ::Spam::SpamConstants::BLOCK_USER].each do |verdict_value|
let(:verdict) { verdict_value } let(:verdict) { verdict_value }
let(:expected) { verdict_value } let(:expected) { [verdict_value, attribs] }
it "returns expected spam constant" do it "returns expected spam constant" do
expect(subject).to eq(expected) expect(subject).to eq(expected)
...@@ -230,7 +277,7 @@ RSpec.describe Spam::SpamVerdictService do ...@@ -230,7 +277,7 @@ RSpec.describe Spam::SpamVerdictService do
let(:verdict) { :this_is_fine } let(:verdict) { :this_is_fine }
it 'returns the string' do it 'returns the string' do
expect(subject).to eq verdict expect(subject).to eq([verdict, attribs])
end end
end end
...@@ -238,7 +285,7 @@ RSpec.describe Spam::SpamVerdictService do ...@@ -238,7 +285,7 @@ RSpec.describe Spam::SpamVerdictService do
let(:verdict) { '' } let(:verdict) { '' }
it 'returns nil' do it 'returns nil' do
expect(subject).to eq verdict expect(subject).to eq([verdict, attribs])
end end
end end
...@@ -246,7 +293,7 @@ RSpec.describe Spam::SpamVerdictService do ...@@ -246,7 +293,7 @@ RSpec.describe Spam::SpamVerdictService do
let(:verdict) { nil } let(:verdict) { nil }
it 'returns nil' do it 'returns nil' do
expect(subject).to be_nil expect(subject).to eq([nil, attribs])
end end
end end
...@@ -254,17 +301,19 @@ RSpec.describe Spam::SpamVerdictService do ...@@ -254,17 +301,19 @@ RSpec.describe Spam::SpamVerdictService do
let(:error) { "Sorry Dave, I can't do that" } let(:error) { "Sorry Dave, I can't do that" }
it 'returns nil' do it 'returns nil' do
expect(subject).to be_nil expect(subject).to eq([nil, attribs])
end end
end end
context 'the requested is aborted' do context 'the requested is aborted' do
let(:attribs) { nil }
before do before do
allow(spam_client).to receive(:issue_spam?).and_raise(GRPC::Aborted) allow(spam_client).to receive(:issue_spam?).and_raise(GRPC::Aborted)
end end
it 'returns nil' do it 'returns nil' do
expect(subject).to be(ALLOW) expect(subject).to eq([ALLOW, attribs])
end end
end end
...@@ -273,18 +322,20 @@ RSpec.describe Spam::SpamVerdictService do ...@@ -273,18 +322,20 @@ RSpec.describe Spam::SpamVerdictService do
let(:error) { 'oh noes!' } let(:error) { 'oh noes!' }
it 'renders the verdict' do it 'renders the verdict' do
expect(subject).to eq DISALLOW expect(subject).to eq [DISALLOW, attribs]
end end
end end
end end
context 'if the endpoint times out' do context 'if the endpoint times out' do
let(:attribs) { nil }
before do before do
allow(spam_client).to receive(:issue_spam?).and_raise(GRPC::DeadlineExceeded) allow(spam_client).to receive(:issue_spam?).and_raise(GRPC::DeadlineExceeded)
end end
it 'returns nil' do it 'returns nil' do
expect(subject).to be(ALLOW) expect(subject).to eq([ALLOW, attribs])
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