gitlab-org--gitlab-foss/app/services/spam/spam_action_service.rb

102 lines
2.9 KiB
Ruby

# frozen_string_literal: true
module Spam
class SpamActionService
include SpamConstants
attr_accessor :target, :request, :options
attr_reader :spam_log
def initialize(spammable:, request:, user:, context: {})
@target = spammable
@request = request
@user = user
@context = context
@options = {}
if @request
@options[:ip_address] = @request.env['action_dispatch.remote_ip'].to_s
@options[:user_agent] = @request.env['HTTP_USER_AGENT']
@options[:referrer] = @request.env['HTTP_REFERRER']
else
@options[:ip_address] = @target.ip_address
@options[:user_agent] = @target.user_agent
end
end
def execute(api: false, recaptcha_verified:, spam_log_id:)
if recaptcha_verified
# If it's a request which is already verified through reCAPTCHA,
# update the spam log accordingly.
SpamLog.verify_recaptcha!(user_id: user.id, id: spam_log_id)
else
return if allowlisted?(user)
return unless request
return unless check_for_spam?
perform_spam_service_check(api)
end
end
delegate :check_for_spam?, to: :target
private
attr_reader :user, :context
def allowlisted?(user)
user.try(:gitlab_employee?) || user.try(:gitlab_bot?) || user.try(:gitlab_service_user?)
end
def perform_spam_service_check(api)
# since we can check for spam, and recaptcha is not verified,
# ask the SpamVerdictService what to do with the target.
spam_verdict_service.execute.tap do |result|
case result
when CONDITIONAL_ALLOW
# at the moment, this means "ask for reCAPTCHA"
create_spam_log(api)
break if target.allow_possible_spam?
target.needs_recaptcha!
when DISALLOW
# TODO: remove `unless target.allow_possible_spam?` once this flag has been passed to `SpamVerdictService`
# https://gitlab.com/gitlab-org/gitlab/-/issues/214739
target.spam! unless target.allow_possible_spam?
create_spam_log(api)
when ALLOW
target.clear_spam_flags!
end
end
end
def create_spam_log(api)
@spam_log = SpamLog.create!(
{
user_id: target.author_id,
title: target.spam_title,
description: target.spam_description,
source_ip: options[:ip_address],
user_agent: options[:user_agent],
noteable_type: notable_type,
via_api: api
}
)
target.spam_log = spam_log
end
def spam_verdict_service
SpamVerdictService.new(target: target,
user: user,
request: @request,
options: options,
context: context.merge(target_type: notable_type))
end
def notable_type
@notable_type ||= target.class.to_s
end
end
end