diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb index a9be99d451..6e3bdb8b4b 100644 --- a/app/controllers/comments_controller.rb +++ b/app/controllers/comments_controller.rb @@ -391,6 +391,9 @@ def create @comment = Comment.new(comment_params) @comment.ip_address = request.remote_ip @comment.user_agent = request.env["HTTP_USER_AGENT"]&.to(499) + @comment.cloudflare_bot_score = request.env["HTTP_CF_BOT_SCORE"] + @comment.cloudflare_ja3_hash = request.env["HTTP_CF_JA3_HASH"] + @comment.cloudflare_ja4 = request.env["HTTP_CF_JA4"] @comment.commentable = Comment.commentable_object(@commentable) @controller_name = params[:controller_name] diff --git a/app/models/comment.rb b/app/models/comment.rb index e9effa2ac9..3da6c01f61 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -24,6 +24,8 @@ class Comment < ApplicationRecord delegate :user, to: :pseud, allow_nil: true + attr_accessor :cloudflare_bot_score, :cloudflare_ja3_hash, :cloudflare_ja4 + # Whether the writer of the comment this is replying to allows guest replies validate :guest_can_reply, if: :reply_comment?, unless: :pseud_id, on: :create def guest_can_reply @@ -138,6 +140,10 @@ def akismet_attributes comment_post_modified_gmt: comment_post_modified_gmt } + attributes[:cloudflare_bot_score] = cloudflare_bot_score if cloudflare_bot_score + attributes[:cloudflare_ja3_hash] = cloudflare_ja3_hash if cloudflare_ja3_hash + attributes[:cloudflare_ja4] = cloudflare_ja4 if cloudflare_ja4 + attributes[:recheck_reason] = "edit" if will_save_change_to_edited_at? && will_save_change_to_comment_content? attributes diff --git a/spec/controllers/comments/default_rails_actions_spec.rb b/spec/controllers/comments/default_rails_actions_spec.rb index 7faaa25799..35d57d398c 100644 --- a/spec/controllers/comments/default_rails_actions_spec.rb +++ b/spec/controllers/comments/default_rails_actions_spec.rb @@ -661,6 +661,32 @@ end end end + + context "when cloudflare headers are available" do + let!(:comment) { create(:comment) } + before { fake_login } + + it "sets the bot score" do + request.env["HTTP_CF_BOT_SCORE"] = "42" + expect_any_instance_of(Comment).to receive(:cloudflare_bot_score=).with("42") + + post :create, params: { comment_id: comment.id, comment: anon_comment_attributes } + end + + it "sets the ja3 hash" do + request.env["HTTP_CF_JA3_HASH"] = "a_hash" + expect_any_instance_of(Comment).to receive(:cloudflare_ja3_hash=).with("a_hash") + + post :create, params: { comment_id: comment.id, comment: anon_comment_attributes } + end + + it "sets the ja3 hash" do + request.env["HTTP_CF_JA4"] = "another_hash" + expect_any_instance_of(Comment).to receive(:cloudflare_ja4=).with("another_hash") + + post :create, params: { comment_id: comment.id, comment: anon_comment_attributes } + end + end end describe "DELETE #destroy" do diff --git a/spec/models/comment_spec.rb b/spec/models/comment_spec.rb index 7136e2ca6d..c6e29bcfa0 100644 --- a/spec/models/comment_spec.rb +++ b/spec/models/comment_spec.rb @@ -355,6 +355,46 @@ def queue_adapter_for_test end end end + + context "when cloudflare headers are available" do + before do + subject.cloudflare_bot_score = "42" + subject.cloudflare_ja3_hash = "a_hash" + subject.cloudflare_ja4 = "another_hash" + end + + it "has cloudflare bot score" do + expect(subject.akismet_attributes[:cloudflare_bot_score]).to eq("42") + end + + it "has cloudflare ja3 hash" do + expect(subject.akismet_attributes[:cloudflare_ja3_hash]).to eq("a_hash") + end + + it "has cloudflare ja4" do + expect(subject.akismet_attributes[:cloudflare_ja4]).to eq("another_hash") + end + end + + context "when cloudflare headers aren't available" do + before do + subject.cloudflare_bot_score = nil + subject.cloudflare_ja3_hash = nil + subject.cloudflare_ja4 = nil + end + + it "doesn't have cloudflare bot score" do + expect(subject.akismet_attributes).not_to have_key(:cloudflare_bot_score) + end + + it "doesn't have cloudflare ja3 hash" do + expect(subject.akismet_attributes).not_to have_key(:cloudflare_ja3_hash) + end + + it "doesn't have cloudflare ja4" do + expect(subject.akismet_attributes).not_to have_key(:cloudflare_ja4) + end + end end end