Skip to content

Commit 13215c1

Browse files
authored
Merge pull request #18 from alphagov/Accept-fact-check-requests-from-Publisher
Add Agnostic Fact Check Request API
2 parents 5f6b838 + 426e46b commit 13215c1

File tree

4 files changed

+133
-2
lines changed

4 files changed

+133
-2
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
module Api
2+
class RequestsController < ApplicationController
3+
# TODO: Implement authentication later
4+
# before_action :authenticate_publisher!
5+
# TO REMOVE:
6+
# protect_from_forgery with: :null_session
7+
8+
def create
9+
if recipients.blank?
10+
return render json: { errors: ["At least one recipient email is required"] }, status: :bad_request
11+
end
12+
13+
fact_check_request = Request.new(request_params.except(:recipients))
14+
15+
recipients.each do |email|
16+
user = User.find_or_create_by!(email: email) do |u|
17+
u.name = email.split("@").first
18+
u.uid = SecureRandom.uuid
19+
end
20+
21+
fact_check_request.collaborations.build(user: user, role: "fact_checker")
22+
end
23+
24+
if fact_check_request.save
25+
render json: { id: fact_check_request.id, source_id: fact_check_request.source_id }, status: :created
26+
else
27+
render json: { errors: fact_check_request.errors.full_messages }, status: :bad_request
28+
end
29+
end
30+
31+
private
32+
33+
def request_params
34+
params.require(:request).permit(
35+
:source_app,
36+
:source_id,
37+
:source_url, # optional
38+
:source_title, # optional
39+
:requester_name,
40+
:requester_email,
41+
:current_content,
42+
:previous_content, # optional
43+
:deadline, # optional
44+
)
45+
end
46+
47+
def recipients
48+
params.fetch(:recipients, [])
49+
end
50+
end
51+
end

config/routes.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,8 @@
33
get "/healthcheck/ready", to: GovukHealthcheck.rack_response
44

55
root to: "application#hello_world"
6+
7+
namespace :api do
8+
resources :requests, only: [:create]
9+
end
610
end

db/schema.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#
1111
# It's strongly recommended that you check this file into your version control system.
1212

13-
ActiveRecord::Schema[8.0].define(version: 2026_02_04_143415) do
13+
ActiveRecord::Schema[8.0].define(version: 2026_02_05_161332) do
1414
# These are extensions that must be enabled in order to support this database
1515
enable_extension "pg_catalog.plpgsql"
1616
enable_extension "pgcrypto"
@@ -30,7 +30,7 @@
3030
t.uuid "source_id", null: false
3131
t.string "requester_name", null: false
3232
t.string "requester_email", null: false
33-
t.string "status", default: "in_progress", null: false
33+
t.string "status", default: "new", null: false
3434
t.text "previous_content"
3535
t.text "current_content", null: false
3636
t.datetime "deadline"

spec/requests/api/requests_spec.rb

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
require "rails_helper"
2+
3+
RSpec.describe "POST /api/requests", type: :request do
4+
let!(:user) do
5+
User.create!(
6+
name: "FCM User",
7+
email: "fcm-user@example.com",
8+
uid: "test-uid",
9+
)
10+
end
11+
12+
let(:valid_payload) do
13+
{
14+
source_app: "Mainstream",
15+
source_id: SecureRandom.uuid,
16+
source_url: "",
17+
source_title: "",
18+
requester_name: "GDS Content Designer",
19+
requester_email: "gds-content-designer@example.com",
20+
current_content: "<p>Test HTML</p>",
21+
previous_content: "",
22+
deadline: 1.week.from_now.iso8601,
23+
recipients: ["recipient1@example.com", "recipient2@example.com"],
24+
}
25+
end
26+
27+
context "with a valid payload" do
28+
it "creates a new Request with collaborations" do
29+
expect {
30+
post "/api/requests", params: valid_payload, as: :json
31+
}.to change(Request, :count).by(1)
32+
.and change(Collaboration, :count).by(2)
33+
34+
expect(response).to have_http_status(:created)
35+
36+
json = JSON.parse(response.body)
37+
expect(json).to include("id")
38+
39+
request = Request.last
40+
expect(request.source_app).to eq("Mainstream")
41+
expect(request.source_id).to be_present
42+
expect(request.current_content).to eq("<p>Test HTML</p>")
43+
expect(request.status).to eq("new")
44+
expect(request.requester_name).to eq("GDS Content Designer")
45+
expect(request.requester_email).to eq("gds-content-designer@example.com")
46+
end
47+
end
48+
49+
context "with invalid payload" do
50+
it "returns errors for missing required fields" do
51+
invalid_payload = { requester_name: "Alice", recipients: ["recipient1@example.com", "recipient2@example.com"] }
52+
53+
post "/api/requests", params: invalid_payload, as: :json
54+
55+
expect(response).to have_http_status(:bad_request)
56+
json = JSON.parse(response.body)
57+
expect(json["errors"]).to include(
58+
"Source can't be blank",
59+
"Requester email can't be blank",
60+
)
61+
end
62+
end
63+
64+
context "without recipients" do
65+
it "returns a 400 error" do
66+
payload = valid_payload
67+
payload.delete(:recipients)
68+
69+
post "/api/requests", params: payload, as: :json
70+
71+
expect(response).to have_http_status(:bad_request)
72+
expect(JSON.parse(response.body)["errors"])
73+
.to include("At least one recipient email is required")
74+
end
75+
end
76+
end

0 commit comments

Comments
 (0)