diff --git a/config/routes.rb b/config/routes.rb
index 7636a67c28..9cd68aaaab 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -189,17 +189,17 @@ def matches?(request)
end
#### Followups controller
- match '/request/:request_id/followups/new' => 'followups#new',
+ match '/request/:request_url_title/followups/new' => 'followups#new',
:as => :new_request_followup,
:via => :get
- match '/request/:request_id/followups/new/:incoming_message_id' =>
+ match '/request/:request_url_title/followups/new/:incoming_message_id' =>
'followups#new',
:as => :new_request_incoming_followup,
:via => :get
- match '/request/:request_id/followups/preview' => 'followups#preview',
+ match '/request/:request_url_title/followups/preview' => 'followups#preview',
:as => :preview_request_followups,
:via => :post
- match '/request/:request_id/followups' => 'followups#create',
+ match '/request/:request_url_title/followups' => 'followups#create',
:as => :request_followups,
:via => :post
####
diff --git a/config/routes/redirects.rb b/config/routes/redirects.rb
index 207e3d2044..20f7fdc0fc 100644
--- a/config/routes/redirects.rb
+++ b/config/routes/redirects.rb
@@ -6,9 +6,12 @@
ability = Ability.new(User.authenticate_from_session(request.session))
raise ActiveRecord::RecordNotFound if ability.cannot?(:read, info_request)
+ # split path components
+ suffix = params[:suffix]&.split('/') # suffix is optional
+
# encode path components
encoded_parts = [
- *params[:locale], 'request', info_request.url_title
+ *params[:locale], 'request', info_request.url_title, *suffix
].map do |part|
if RUBY_VERSION < '3.1'
URI.encode_www_form_component(part).gsub('+', '%20')
@@ -24,3 +27,7 @@
get '/request/:id',
constraints: { id: /\d+/ },
to: info_request_redirect
+
+get '/request/:id(/*suffix)',
+ constraints: { id: /\d+/, suffix: %r(followups/new(/\d+)?) },
+ to: info_request_redirect
diff --git a/spec/controllers/classifications_controller_spec.rb b/spec/controllers/classifications_controller_spec.rb
index 49936215c0..aea327dc94 100644
--- a/spec/controllers/classifications_controller_spec.rb
+++ b/spec/controllers/classifications_controller_spec.rb
@@ -493,7 +493,7 @@ def post_status(status, message: nil)
post_status('waiting_clarification')
expect(response).to redirect_to(
new_request_incoming_followup_path(
- info_request.id,
+ info_request.url_title,
incoming_message_id: info_request.get_last_public_response.id
)
)
@@ -512,7 +512,7 @@ def post_status(status, message: nil)
post_status('waiting_clarification')
expect(response).to redirect_to(
new_request_followup_path(
- info_request.id,
+ info_request.url_title,
incoming_message_id: nil
)
)
@@ -566,7 +566,7 @@ def post_status(status, message: nil)
post_status('gone_postal')
expect(response).to redirect_to(
new_request_incoming_followup_path(
- info_request.id,
+ info_request.url_title,
incoming_message_id: info_request.get_last_public_response.id,
gone_postal: 1
)
@@ -668,7 +668,7 @@ def post_status(status, message: nil)
post_status('user_withdrawn')
expect(response).to redirect_to(
new_request_incoming_followup_path(
- info_request.id,
+ info_request.url_title,
incoming_message_id: info_request.get_last_public_response.id
)
)
diff --git a/spec/controllers/followups_controller_spec.rb b/spec/controllers/followups_controller_spec.rb
index ae7d2318c3..e17833eb3c 100644
--- a/spec/controllers/followups_controller_spec.rb
+++ b/spec/controllers/followups_controller_spec.rb
@@ -15,7 +15,7 @@
it 'raises an ActiveRecord::RecordNotFound error for an embargoed request' do
embargoed_request = FactoryBot.create(:embargoed_request)
expect {
- get :new, params: { request_id: embargoed_request.id }
+ get :new, params: { request_url_title: embargoed_request.url_title }
}.to raise_error(ActiveRecord::RecordNotFound)
end
end
@@ -28,13 +28,13 @@
it 'finds their own embargoed requests' do
embargoed_request = FactoryBot.create(:embargoed_request,
user: pro_user)
- get :new, params: { request_id: embargoed_request.id }
+ get :new, params: { request_url_title: embargoed_request.url_title }
expect(response).to be_successful
end
it "displays 'wrong user' message when not logged in as the request owner" do
get :new, params: {
- request_id: request.id,
+ request_url_title: request.url_title,
incoming_message_id: message_id
}
expect(response).to render_template('user/wrong_user')
@@ -43,7 +43,7 @@
it 'raises an ActiveRecord::RecordNotFound error for other embargoed requests' do
embargoed_request = FactoryBot.create(:embargoed_request)
expect {
- get :new, params: { request_id: embargoed_request.id }
+ get :new, params: { request_url_title: embargoed_request.url_title }
}.to raise_error(ActiveRecord::RecordNotFound)
end
end
@@ -51,7 +51,7 @@
it "displays 'wrong user' message when not logged in as the request owner" do
sign_in FactoryBot.create(:user)
get :new, params: {
- request_id: request.id,
+ request_url_title: request.url_title,
incoming_message_id: message_id
}
expect(response).to render_template('user/wrong_user')
@@ -60,13 +60,13 @@
it "does not allow follow ups to external requests" do
sign_in FactoryBot.create(:user)
external_request = FactoryBot.create(:external_request)
- get :new, params: { request_id: external_request.id }
+ get :new, params: { request_url_title: external_request.url_title }
expect(response).to render_template('followup_bad')
expect(assigns[:reason]).to eq('external')
end
it "redirects to the signin page if not logged in" do
- get :new, params: { request_id: request.id }
+ get :new, params: { request_url_title: request.url_title }
expect(response).
to redirect_to(signin_url(token: get_last_post_redirect.token))
end
@@ -74,14 +74,14 @@
it "calls the message a followup if there is an incoming message" do
expected_reason = "To send a follow up message " \
"to #{request.public_body.name}"
- get :new, params: { request_id: request.id,
+ get :new, params: { request_url_title: request.url_title,
incoming_message_id: message_id }
expect(get_last_post_redirect.reason_params[:web]).to eq(expected_reason)
end
it "calls the message a reply if there is no incoming message" do
expected_reason = "To reply to #{request.public_body.name}."
- get :new, params: { request_id: request.id }
+ get :new, params: { request_url_title: request.url_title }
expect(get_last_post_redirect.reason_params[:web]).to eq(expected_reason)
end
@@ -91,12 +91,12 @@
end
it "shows the followup form" do
- get :new, params: { request_id: request.id }
+ get :new, params: { request_url_title: request.url_title }
expect(response).to render_template('new')
end
it "shows the followup form when replying to an incoming message" do
- get :new, params: { request_id: request.id,
+ get :new, params: { request_url_title: request.url_title,
incoming_message_id: message_id }
expect(response).to render_template('new')
end
@@ -105,7 +105,7 @@
before { request.create_embargo!(embargo_duration: '3_months') }
it 'shows the followup form' do
- get :new, params: { request_id: request.id }
+ get :new, params: { request_url_title: request.url_title }
expect(response).to render_template('new')
end
end
@@ -122,7 +122,7 @@
end
it "offers the opportunity to reply to the main address" do
- get :new, params: { request_id: request.id,
+ get :new, params: { request_url_title: request.url_title,
incoming_message_id: message_id }
expect(response.body).
to have_css("div#other_recipients ul li",
@@ -131,9 +131,9 @@
it "offers an opportunity to reply to another address" do
get :new, params: {
- request_id: request.id,
- incoming_message_id: message_id
- }
+ request_url_title: request.url_title,
+ incoming_message_id: message_id
+ }
expect(response.body).
to have_css("div#other_recipients ul li", text: "Frob")
end
@@ -146,7 +146,7 @@
end
it "does not show the form, even to the request owner" do
- get :new, params: { request_id: hidden_request.id }
+ get :new, params: { request_url_title: hidden_request.url_title }
expect(response).to render_template('request/hidden')
end
@@ -154,7 +154,7 @@
incoming_message_id = hidden_request.incoming_messages[0].id
expect do
get :new, params: {
- request_id: hidden_request.id,
+ request_url_title: hidden_request.url_title,
incoming_message_id: incoming_message_id,
format: 'json'
}
@@ -167,7 +167,7 @@
it "does not allow follow ups to external requests" do
sign_in FactoryBot.create(:user)
external_request = FactoryBot.create(:external_request)
- get :new, params: { request_id: external_request.id }
+ get :new, params: { request_url_title: external_request.url_title }
expect(response).to render_template('followup_bad')
expect(assigns[:reason]).to eq('external')
end
@@ -175,8 +175,8 @@
it 'the response code should be successful' do
sign_in FactoryBot.create(:user)
get :new, params: {
- request_id: FactoryBot.create(:external_request).id
- }
+ request_url_title: FactoryBot.create(:external_request).url_title
+ }
expect(response).to be_successful
end
end
@@ -190,7 +190,7 @@
it "sets @in_pro_area" do
sign_in pro_user
with_feature_enabled(:alaveteli_pro) do
- get :new, params: { request_id: embargoed_request.id }
+ get :new, params: { request_url_title: embargoed_request.url_title }
expect(assigns[:in_pro_area]).to eq true
end
end
@@ -204,7 +204,7 @@
request, internal_review: false, user: request.user
).and_call_original
- get :new, params: { request_id: request.id }
+ get :new, params: { request_url_title: request.url_title }
end
it 'initialise with internal_review option' do
@@ -212,11 +212,14 @@
request, internal_review: true, user: request.user
).and_call_original
- get :new, params: { request_id: request.id, internal_review: 1 }
+ get :new, params: {
+ request_url_title: request.url_title,
+ internal_review: 1
+ }
end
it 'assigns @refusal_advice' do
- get :new, params: { request_id: request.id }
+ get :new, params: { request_url_title: request.url_title }
expect(assigns[:refusal_advice]).to be_a(RefusalAdvice)
end
end
@@ -234,7 +237,7 @@
expect {
post :preview, params: {
outgoing_message: dummy_message,
- request_id: embargoed_request.id
+ request_url_title: embargoed_request.url_title
}
}.to raise_error(ActiveRecord::RecordNotFound)
end
@@ -242,7 +245,7 @@
it "redirects to the signin page" do
post :preview, params: {
outgoing_message: dummy_message,
- request_id: request.id,
+ request_url_title: request.url_title,
incoming_message_id: message_id
}
expect(response).
@@ -260,7 +263,7 @@
user: pro_user)
post :preview, params: {
outgoing_message: dummy_message,
- request_id: embargoed_request.id
+ request_url_title: embargoed_request.url_title
}
expect(response).to be_successful
end
@@ -270,7 +273,7 @@
expect {
post :preview, params: {
outgoing_message: dummy_message,
- request_id: embargoed_request.id
+ request_url_title: embargoed_request.url_title
}
}.to raise_error(ActiveRecord::RecordNotFound)
end
@@ -280,7 +283,7 @@
sign_in FactoryBot.create(:user)
post :preview, params: {
outgoing_message: dummy_message,
- request_id: request.id,
+ request_url_title: request.url_title,
incoming_message_id: message_id
}
expect(response).to render_template('user/wrong_user')
@@ -293,7 +296,7 @@
it "displays the edit form with an error when the message body is blank" do
post :preview, params: {
- request_id: request.id,
+ request_url_title: request.url_title,
outgoing_message: {
body: "",
what_doing: "normal_sort"
@@ -308,7 +311,7 @@
it "shows a preview when input is good" do
post :preview, params: {
outgoing_message: dummy_message,
- request_id: request.id,
+ request_url_title: request.url_title,
incoming_message_id: message_id,
preview: 1
}
@@ -318,7 +321,7 @@
it "allows re-editing of a preview" do
post :preview, params: {
outgoing_message: dummy_message,
- request_id: request.id,
+ request_url_title: request.url_title,
incoming_message_id: message_id,
reedit: "Re-edit this request"
}
@@ -335,7 +338,7 @@
it "sets @in_pro_area" do
sign_in pro_user
with_feature_enabled(:alaveteli_pro) do
- get :new, params: { request_id: embargoed_request.id }
+ get :new, params: { request_url_title: embargoed_request.url_title }
expect(assigns[:in_pro_area]).to eq true
end
end
@@ -356,7 +359,7 @@
it 'sends the followup message' do
post :create, params: {
outgoing_message: dummy_message,
- request_id: request.id,
+ request_url_title: request.url_title,
incoming_message_id: message_id
}
@@ -380,7 +383,7 @@
expect {
post :create, params: {
outgoing_message: dummy_message,
- request_id: embargoed_request.id
+ request_url_title: embargoed_request.url_title
}
}.to raise_error(ActiveRecord::RecordNotFound)
end
@@ -388,7 +391,7 @@
it "redirects to the signin page" do
post :create, params: {
outgoing_message: dummy_message,
- request_id: request.id,
+ request_url_title: request.url_title,
incoming_message_id: message_id
}
expect(response).
@@ -407,7 +410,7 @@
expected_url = show_request_url(embargoed_request.url_title)
post :create, params: {
outgoing_message: dummy_message,
- request_id: embargoed_request.id
+ request_url_title: embargoed_request.url_title
}
expect(response).to redirect_to(expected_url)
end
@@ -417,7 +420,7 @@
expect {
post :create, params: {
outgoing_message: dummy_message,
- request_id: embargoed_request.id
+ request_url_title: embargoed_request.url_title
}
}.to raise_error(ActiveRecord::RecordNotFound)
end
@@ -427,7 +430,7 @@
sign_in FactoryBot.create(:user)
post :create, params: {
outgoing_message: dummy_message,
- request_id: request.id,
+ request_url_title: request.url_title,
incoming_message_id: message_id
}
expect(response).to render_template('user/wrong_user')
@@ -436,7 +439,7 @@
it "gives an error and renders 'show_response' when a body isn't given" do
post :create, params: {
outgoing_message: dummy_message.merge(body: ''),
- request_id: request.id,
+ request_url_title: request.url_title,
incoming_message_id: message_id
}
@@ -449,7 +452,7 @@
def send_request
post :create, params: {
outgoing_message: dummy_message,
- request_id: request.id,
+ request_url_title: request.url_title,
incoming_message_id: message_id
}
end
@@ -464,7 +467,7 @@ def send_request
it "updates the status for successful followup sends" do
post :create, params: {
outgoing_message: dummy_message,
- request_id: request.id,
+ request_url_title: request.url_title,
incoming_message_id: message_id
}
@@ -482,7 +485,7 @@ def send_request
it 'reopens the parent request to new responses' do
post :create, params: {
outgoing_message: dummy_message,
- request_id: request.id,
+ request_url_title: request.url_title,
incoming_message_id: message_id
}
@@ -498,7 +501,7 @@ def send_request
post :create, params: {
outgoing_message: dummy_message,
- request_id: request.id,
+ request_url_title: request.url_title,
incoming_message_id: message_id
}
@@ -509,7 +512,7 @@ def send_request
it "redirects to the request page" do
post :create, params: {
outgoing_message: dummy_message,
- request_id: request.id,
+ request_url_title: request.url_title,
incoming_message_id: message_id
}
@@ -520,7 +523,7 @@ def send_request
it "displays the a confirmation once the message has been sent" do
post :create, params: {
outgoing_message: dummy_message,
- request_id: request.id,
+ request_url_title: request.url_title,
incoming_message_id: message_id
}
expect(flash[:notice]).
@@ -535,7 +538,7 @@ def send_request
post :create,
params: {
outgoing_message: dummy_message,
- request_id: closed_request.id,
+ request_url_title: closed_request.url_title,
incoming_message_id: closed_request.incoming_messages[0].id
}
deliveries = ActionMailer::Base.deliveries
@@ -554,13 +557,13 @@ def send_request
before(:each) do
post :create, params: {
outgoing_message: dummy_message,
- request_id: request.id,
+ request_url_title: request.url_title,
incoming_message_id: message_id
}
post :create, params: {
outgoing_message: dummy_message,
- request_id: request.id,
+ request_url_title: request.url_title,
incoming_message_id: message_id
}
end
diff --git a/spec/controllers/refusal_advice_controller_spec.rb b/spec/controllers/refusal_advice_controller_spec.rb
index 21fe5a455c..ed3fc319e2 100644
--- a/spec/controllers/refusal_advice_controller_spec.rb
+++ b/spec/controllers/refusal_advice_controller_spec.rb
@@ -38,7 +38,7 @@
it 'redirects to new followup action' do
post :create, params: params
expect(response).to redirect_to(
- new_request_followup_path(info_request.id)
+ new_request_followup_path(info_request.url_title)
)
end
end
@@ -49,7 +49,9 @@
it 'redirects to new internal review action' do
post :create, params: params
expect(response).to redirect_to(
- new_request_followup_path(info_request.id, internal_review: '1')
+ new_request_followup_path(
+ info_request.url_title, internal_review: '1'
+ )
)
end
end
diff --git a/spec/fixtures/files/notification_mailer/daily-summary.txt b/spec/fixtures/files/notification_mailer/daily-summary.txt
index b34f2ba69f..0ea9ab0450 100644
--- a/spec/fixtures/files/notification_mailer/daily-summary.txt
+++ b/spec/fixtures/files/notification_mailer/daily-summary.txt
@@ -41,7 +41,7 @@ Late expenses claims
What's happened:
Ministry of fact keeping have not replied to your FOI request Late expenses claims promptly, as normally required by law. Click on the link below to remind them to reply.
-http://test.host/en/profile/sign_in?r=%2Fen%2Frequest%2F$LATE_EXPENSES_CLAIMS_MOF_ID$%2Ffollowups%2Fnew
+http://test.host/en/profile/sign_in?r=%2Fen%2Frequest%2F$LATE_EXPENSES_CLAIMS_MOF_URL_TITLE$%2Ffollowups%2Fnew
Extremely late expenses claims
@@ -50,7 +50,7 @@ Extremely late expenses claims
What's happened:
Ministry of fact keeping have still not replied to your FOI request Extremely late expenses claims, as normally required by law. Click on the link below to tell them to reply. You might like to ask for an internal review, asking them to find out why their response to the request has been so slow.
-http://test.host/en/profile/sign_in?r=%2Fen%2Frequest%2F$EXTREMELY_LATE_EXPENSES_CLAIMS_MOF_ID$%2Ffollowups%2Fnew
+http://test.host/en/profile/sign_in?r=%2Fen%2Frequest%2F$EXTREMELY_LATE_EXPENSES_CLAIMS_MOF_URL_TITLE$%2Ffollowups%2Fnew
Misdelivered letters
@@ -114,8 +114,8 @@ What's happened:
You can see the requests and remind the bodies to respond with the following links:
- Ministry of fact keeping: http://test.host/en/profile/sign_in?r=%2Fen%2Frequest%2F$LATE_FOI_REQUESTS_MOF_ID$%2Ffollowups%2Fnew
- Minor infractions quango: http://test.host/en/profile/sign_in?r=%2Fen%2Frequest%2F$LATE_FOI_REQUESTS_2_MIQ_ID$%2Ffollowups%2Fnew
+ Ministry of fact keeping: http://test.host/en/profile/sign_in?r=%2Fen%2Frequest%2F$LATE_FOI_REQUESTS_MOF_URL_TITLE$%2Ffollowups%2Fnew
+ Minor infractions quango: http://test.host/en/profile/sign_in?r=%2Fen%2Frequest%2F$LATE_FOI_REQUESTS_2_MIQ_URL_TITLE$%2Ffollowups%2Fnew
Ignored FOI requests
@@ -130,8 +130,8 @@ What's happened:
You can see the requests and tell the bodies to respond with the following links. You might like to ask for internal reviews, asking the bodies to find out why responses to the requests have been so slow.
- Ministry of fact keeping: http://test.host/en/profile/sign_in?r=%2Fen%2Frequest%2F$IGNORED_FOI_REQUESTS_MOF_ID$%2Ffollowups%2Fnew
- Minor infractions quango: http://test.host/en/profile/sign_in?r=%2Fen%2Frequest%2F$IGNORED_FOI_REQUESTS_2_MIQ_ID$%2Ffollowups%2Fnew
+ Ministry of fact keeping: http://test.host/en/profile/sign_in?r=%2Fen%2Frequest%2F$IGNORED_FOI_REQUESTS_MOF_URL_TITLE$%2Ffollowups%2Fnew
+ Minor infractions quango: http://test.host/en/profile/sign_in?r=%2Fen%2Frequest%2F$IGNORED_FOI_REQUESTS_2_MIQ_URL_TITLE$%2Ffollowups%2Fnew
diff --git a/spec/fixtures/files/notification_mailer/overdue.txt b/spec/fixtures/files/notification_mailer/overdue.txt
index 2ad08008cb..d849554ab1 100644
--- a/spec/fixtures/files/notification_mailer/overdue.txt
+++ b/spec/fixtures/files/notification_mailer/overdue.txt
@@ -4,7 +4,7 @@ They have not replied to your FOI request Here is a character that needs quoting
Click on the link below to send a message to Test public body reminding them to reply to your request.
-http://test.host/en/profile/sign_in?r=%2Fen%2Frequest%2FINFO_REQUEST_ID%2Ffollowups%2Fnew
+http://test.host/en/profile/sign_in?r=%2Fen%2Frequest%2FINFO_REQUEST_URL_TITLE%2Ffollowups%2Fnew
-- the Alaveteli team
diff --git a/spec/fixtures/files/notification_mailer/very_overdue.txt b/spec/fixtures/files/notification_mailer/very_overdue.txt
index 43a11522ed..2df84ef4b8 100644
--- a/spec/fixtures/files/notification_mailer/very_overdue.txt
+++ b/spec/fixtures/files/notification_mailer/very_overdue.txt
@@ -4,6 +4,6 @@ They have still not replied to your FOI request Here is a character that needs q
Click on the link below to send a message to Test public body telling them to reply to your request. You might like to ask for an internal review, asking them to find out why their response to the request has been so slow.
-http://test.host/en/profile/sign_in?r=%2Fen%2Frequest%2FINFO_REQUEST_ID%2Ffollowups%2Fnew
+http://test.host/en/profile/sign_in?r=%2Fen%2Frequest%2FINFO_REQUEST_URL_TITLE%2Ffollowups%2Fnew
-- the Alaveteli team
diff --git a/spec/helpers/info_request_helper_spec.rb b/spec/helpers/info_request_helper_spec.rb
index 57b3c88d1e..12931c3a9c 100644
--- a/spec/helpers/info_request_helper_spec.rb
+++ b/spec/helpers/info_request_helper_spec.rb
@@ -158,14 +158,15 @@
'title="2014-12-31 00:00:00 UTC">' \
'December 31, 2014'
+ path = new_request_followup_path(
+ info_request.url_title, internal_review: 1
+ )
expected = "Response to this request is long overdue" \
". By law, under all circumstances, " \
"#{ body_link } should have responded by now " \
"(details" \
"). You can complain by " \
- "requesting an internal " \
- "review."
+ "requesting an internal review."
expect(status_text(info_request)).to eq(expected)
@@ -189,15 +190,16 @@
'title="2014-12-31 00:00:00 UTC">' \
'December 31, 2014'
+ path = new_request_followup_path(
+ info_request.url_title, internal_review: 1
+ )
expected = "Response to this request is long overdue" \
". " \
"Although not legally required to do so, we would have " \
"expected #{ body_link } to have responded by now " \
"(details" \
"). You can complain by " \
- "requesting an internal " \
- "review."
+ "requesting an internal review."
expect(status_text(info_request)).to eq(expected)
@@ -293,10 +295,10 @@
to receive(:get_last_public_response).
and_return(nil)
+ path = new_request_followup_path(info_request.url_title)
expected = "#{ body.name } is waiting for your clarification" \
- ". Please " \
- "" \
- "send a follow up message."
+ ". Please send a follow up " \
+ "message."
actual = status_text(info_request, is_owning_user: true)
diff --git a/spec/mailers/notification_mailer_spec.rb b/spec/mailers/notification_mailer_spec.rb
index 72c68d5418..a57b34a797 100644
--- a/spec/mailers/notification_mailer_spec.rb
+++ b/spec/mailers/notification_mailer_spec.rb
@@ -351,7 +351,7 @@
# HACK: We can't control the IDs of the requests or incoming messages create
# a data structure of mappings here so that we can replace keys in fixture
# files with the ID that will end up in the URL.
- let(:id_mappings) do
+ let(:url_id_mappings) do
all_notifications.each_with_object({}) do |notification, data|
event = notification.info_request_event
case event.event_type
@@ -362,7 +362,7 @@
else
request = event.info_request
key = "#{request.url_title}_#{request.public_body.url_name}".upcase
- data["#{key}_ID"] = request.id
+ data["#{key}_URL_TITLE"] = request.url_title
end
end
end
@@ -387,7 +387,7 @@
mail = NotificationMailer.daily_summary(user, all_notifications)
expected_message = load_file_fixture(
"notification_mailer/daily-summary.txt", 'r:utf-8')
- id_mappings.each do |key, id|
+ url_id_mappings.each do |key, id|
expected_message.gsub!("$#{key}$", id.to_s)
end
expect(mail.body.encoded).to eq(expected_message)
@@ -719,7 +719,7 @@
mail = NotificationMailer.overdue_notification(notification)
expected_message = load_file_fixture(
"notification_mailer/overdue.txt", 'r:utf-8')
- expected_message.gsub!(/INFO_REQUEST_ID/, info_request.id.to_s)
+ expected_message.gsub!(/INFO_REQUEST_URL_TITLE/, info_request.url_title)
expect(mail.body.encoded).to eq(expected_message)
end
end
@@ -790,7 +790,7 @@
mail = NotificationMailer.very_overdue_notification(notification)
expected_message = load_file_fixture(
"notification_mailer/very_overdue.txt", 'r:utf-8')
- expected_message.gsub!(/INFO_REQUEST_ID/, info_request.id.to_s)
+ expected_message.gsub!(/INFO_REQUEST_URL_TITLE/, info_request.url_title)
expect(mail.body.encoded).to eq(expected_message)
end
end
diff --git a/spec/mailers/request_mailer_spec.rb b/spec/mailers/request_mailer_spec.rb
index 4ee111cfa7..653db16fe0 100644
--- a/spec/mailers/request_mailer_spec.rb
+++ b/spec/mailers/request_mailer_spec.rb
@@ -746,8 +746,11 @@ def kitten_mails
mail.body.to_s =~ /(http:\/\/.*)/
mail_url = $1
- expect(mail_url).
- to match(new_request_followup_path(@kitten_request.id))
+ expect(mail_url).to match(
+ new_request_followup_path(
+ request_url_title: @kitten_request.url_title
+ )
+ )
end
end
@@ -856,8 +859,11 @@ def kitten_mails
mail.body.to_s =~ /(http:\/\/.*)/
mail_url = $1
- expect(mail_url).
- to match(new_request_followup_path(@kitten_request.id))
+ expect(mail_url).to match(
+ new_request_followup_path(
+ request_url_title: @kitten_request.url_title
+ )
+ )
end
end
@@ -938,7 +944,7 @@ def force_updated_at_to_past(request)
expect(mail_url).to match(
new_request_incoming_followup_path(
- ir.id,
+ ir.url_title,
incoming_message_id: ir.incoming_messages.last.id
)
)
diff --git a/spec/models/alaveteli_pro/activity_list/overdue_spec.rb b/spec/models/alaveteli_pro/activity_list/overdue_spec.rb
index 68cd201bba..ced9bcf270 100644
--- a/spec/models/alaveteli_pro/activity_list/overdue_spec.rb
+++ b/spec/models/alaveteli_pro/activity_list/overdue_spec.rb
@@ -26,7 +26,7 @@
it 'returns the url of the info_request' do
expect(activity.call_to_action_url).to eq(
new_request_followup_path(
- event.info_request.id, anchor: 'followup'
+ event.info_request.url_title, anchor: 'followup'
)
)
end
diff --git a/spec/models/alaveteli_pro/activity_list/very_overdue_spec.rb b/spec/models/alaveteli_pro/activity_list/very_overdue_spec.rb
index 14783ec007..8b5cebd159 100644
--- a/spec/models/alaveteli_pro/activity_list/very_overdue_spec.rb
+++ b/spec/models/alaveteli_pro/activity_list/very_overdue_spec.rb
@@ -26,7 +26,7 @@
it 'returns the url of the info_request' do
expect(activity.call_to_action_url).to eq(
new_request_followup_path(
- event.info_request.id,
+ event.info_request.url_title,
anchor: 'followup',
internal_review: 1
)
diff --git a/spec/routing/redirects_spec.rb b/spec/routing/redirects_spec.rb
index a784a575dc..f4d94a31ec 100644
--- a/spec/routing/redirects_spec.rb
+++ b/spec/routing/redirects_spec.rb
@@ -13,4 +13,9 @@
get('/en_GB/request/105')
expect(response).to redirect_to('/en_GB/request/the_cost_of_boring')
end
+
+ it 'routes numerical request member routes to URL title member routes' do
+ get('/request/105/followups/new')
+ expect(response).to redirect_to('/request/the_cost_of_boring/followups/new')
+ end
end
diff --git a/spec/views/request/show.html.erb_spec.rb b/spec/views/request/show.html.erb_spec.rb
index 93556e1ead..1507e3a4b0 100644
--- a/spec/views/request/show.html.erb_spec.rb
+++ b/spec/views/request/show.html.erb_spec.rb
@@ -88,7 +88,7 @@ def request_page
and_return(mock_response)
request_page
expected_url = new_request_incoming_followup_path(
- mock_request.id,
+ mock_request.url_title,
incoming_message_id: mock_response.id
)
expect(response.body).
@@ -107,7 +107,7 @@ def request_page
it "should show a link to follow up the request without reference to a specific response" do
request_page
- expected_url = new_request_followup_path(mock_request.id)
+ expected_url = new_request_followup_path(mock_request.url_title)
expect(response.body).
to have_css(
"a[href='#{expected_url}']",
From e0cd4afc814efc5e0d88c7a7c417754a321c1759 Mon Sep 17 00:00:00 2001
From: Alexander Griffen
Date: Fri, 27 Oct 2023 17:03:38 +0100
Subject: [PATCH 10/12] URL Perms: Attachments controller
Replace request IDs in URLs with titles
This does remove a few tests that were looking specifically at
IDs, or 'ugly' IDs)
---
app/controllers/attachments_controller.rb | 2 +-
app/helpers/info_request_helper.rb | 3 +-
config/routes.rb | 7 +--
config/routes/redirects.rb | 5 ++
.../attachments_controller_spec.rb | 52 +++----------------
spec/helpers/info_request_helper_spec.rb | 8 +--
spec/integration/errors_spec.rb | 5 +-
spec/integration/incoming_mail_spec.rb | 12 ++---
.../viewing_attachment_as_html_spec.rb | 2 +-
.../prominence/viewing_raw_attachment_spec.rb | 2 +-
spec/integration/view_request_spec.rb | 2 +-
spec/routing/redirects_spec.rb | 12 +++++
12 files changed, 48 insertions(+), 64 deletions(-)
diff --git a/app/controllers/attachments_controller.rb b/app/controllers/attachments_controller.rb
index 1c1fdedfac..0c02a76e80 100644
--- a/app/controllers/attachments_controller.rb
+++ b/app/controllers/attachments_controller.rb
@@ -58,7 +58,7 @@ def find_info_request
if public_token?
InfoRequest.find_by!(public_token: public_token)
else
- InfoRequest.find(params[:id])
+ InfoRequest.find_by!(url_title: params[:request_url_title])
end
end
diff --git a/app/helpers/info_request_helper.rb b/app/helpers/info_request_helper.rb
index 1314ad220b..a39c74a113 100644
--- a/app/helpers/info_request_helper.rb
+++ b/app/helpers/info_request_helper.rb
@@ -315,7 +315,8 @@ def attachment_params(attachment, options = {})
if public_token?
attach_params[:public_token] = public_token
else
- attach_params[:id] = attachment.incoming_message.info_request_id
+ attach_params[:request_url_title] = attachment.incoming_message.
+ info_request.url_title
end
if options[:html]
attach_params[:file_name] = "#{attachment.display_filename}.html"
diff --git a/config/routes.rb b/config/routes.rb
index 9cd68aaaab..442fc4357b 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -127,13 +127,14 @@ def matches?(request)
:as => :similar_request,
:via => :get
- match '/request/:id/response/:incoming_message_id/attach/html' \
- '/(:part(/*file_name))' => 'attachments#show_as_html',
+ match '/request/:request_url_title/response/:incoming_message_id/attach' \
+ '/html/(:part(/*file_name))' => 'attachments#show_as_html',
:format => false,
:as => :get_attachment_as_html,
:via => :get,
:constraints => { :part => /\d+/ }
- match '/request/:id/response/:incoming_message_id/attach/:part(/*file_name)' => 'attachments#show',
+ match '/request/:request_url_title/response/:incoming_message_id/attach' \
+ '/:part(/*file_name)' => 'attachments#show',
:format => false,
:as => :get_attachment,
:via => :get,
diff --git a/config/routes/redirects.rb b/config/routes/redirects.rb
index 20f7fdc0fc..cd004ca778 100644
--- a/config/routes/redirects.rb
+++ b/config/routes/redirects.rb
@@ -31,3 +31,8 @@
get '/request/:id(/*suffix)',
constraints: { id: /\d+/, suffix: %r(followups/new(/\d+)?) },
to: info_request_redirect
+
+get '/request/:id(/*suffix)',
+ format: false,
+ constraints: { id: /\d+/, suffix: %r(response/\d+/attach(/html)?/\d+/.*) },
+ to: info_request_redirect
diff --git a/spec/controllers/attachments_controller_spec.rb b/spec/controllers/attachments_controller_spec.rb
index f9f1d128eb..cf2b870806 100644
--- a/spec/controllers/attachments_controller_spec.rb
+++ b/spec/controllers/attachments_controller_spec.rb
@@ -43,39 +43,13 @@ def show(params = {})
part: attachment.url_part_number,
file_name: attachment.display_filename
}
- default_params[:id] = info_request.id unless params[:public_token]
+ unless params[:public_token]
+ default_params[:request_url_title] = info_request.url_title
+ end
rebuild_raw_emails(info_request)
get :show, params: default_params.merge(params)
end
- # This is a regression test for a bug where URLs of this form were causing
- # 500 errors instead of 404s.
- #
- # (Note that in fact only the integer-prefix of the URL part is used, so
- # there are *some* “ugly URLs containing a request id that isn\'t an
- # integer” that actually return a 200 response. The point is that IDs of
- # this sort were triggering an error in the error-handling path, causing
- # the wrong sort of error response to be returned in the case where the
- # integer prefix referred to the wrong request.)
- #
- # https://github.com/mysociety/alaveteli/issues/351
- it 'should return 404 for ugly URLs containing a request id that isn\'t an integer' do
- ugly_id = '55195'
- expect { show(id: ugly_id) }
- .to raise_error(ActiveRecord::RecordNotFound)
- end
-
- it 'should return 404 when incoming message and request ids don\'t match' do
- expect { show(id: info_request.id + 1) }
- .to raise_error(ActiveRecord::RecordNotFound)
- end
-
- it 'should return 404 for ugly URLs contain a request id that isn\'t an integer, even if the integer prefix refers to an actual request' do
- ugly_id = '#{FactoryBot.create(:info_request).id}95'
- expect { show(id: ugly_id) }
- .to raise_error(ActiveRecord::RecordNotFound)
- end
-
it 'should redirect to the incoming message if there\'s a wrong part number and an ambiguous filename' do
show(
part: attachment.url_part_number + 1,
@@ -167,7 +141,7 @@ def show(params = {})
allow(controller).to receive(:verifier).and_return(verifier)
allow(verifier).to receive(:generate).with(
get_attachment_path(
- info_request.id,
+ info_request.url_title,
incoming_message_id: attachment.incoming_message_id,
part: attachment.url_part_number,
file_name: attachment.filename
@@ -460,7 +434,9 @@ def show_as_html(params = {})
part: attachment.url_part_number,
file_name: attachment.display_filename
}
- default_params[:id] = info_request.id unless params[:public_token]
+ unless params[:public_token]
+ default_params[:request_url_title] = info_request.url_title
+ end
get :show_as_html, params: default_params.merge(params)
end
@@ -482,18 +458,6 @@ def show_as_html(params = {})
expect(response.headers['X-Robots-Tag']).to eq 'noindex'
end
- it 'should return 404 for ugly URLs containing a request id that isn\'t an integer' do
- ugly_id = '55195'
- expect { show_as_html(id: ugly_id) }
- .to raise_error(ActiveRecord::RecordNotFound)
- end
-
- it 'should return 404 for ugly URLs contain a request id that isn\'t an integer, even if the integer prefix refers to an actual request' do
- ugly_id = FactoryBot.create(:info_request).id.to_s + '95'
- expect { show_as_html(id: ugly_id) }
- .to raise_error(ActiveRecord::RecordNotFound)
- end
-
context 'when attachment has not been masked' do
let(:attachment) do
FactoryBot.create(
@@ -542,7 +506,7 @@ def show_as_html(params = {})
allow(controller).to receive(:verifier).and_return(verifier)
allow(verifier).to receive(:generate).with(
get_attachment_as_html_path(
- info_request.id,
+ info_request.url_title,
incoming_message_id: attachment.incoming_message_id,
part: attachment.url_part_number,
file_name: attachment.filename
diff --git a/spec/helpers/info_request_helper_spec.rb b/spec/helpers/info_request_helper_spec.rb
index 12931c3a9c..65e868f90a 100644
--- a/spec/helpers/info_request_helper_spec.rb
+++ b/spec/helpers/info_request_helper_spec.rb
@@ -644,7 +644,7 @@
context 'when given no format options' do
it 'returns the path to the attachment with a cookie cookie_passthrough param' do
expect(attachment_path(jpeg_attachment)).to eq(
- "/request/#{incoming_message.info_request_id}" \
+ "/request/#{incoming_message.info_request.url_title}" \
"/response/#{incoming_message.id}/" \
"attach/#{jpeg_attachment.url_part_number}" \
"/interesting.jpg?cookie_passthrough=1"
@@ -655,7 +655,7 @@
context 'when given an html format option' do
it 'returns the path to the HTML version of the attachment' do
expect(attachment_path(jpeg_attachment, html: true)).to eq(
- "/request/#{incoming_message.info_request_id}" \
+ "/request/#{incoming_message.info_request.url_title}" \
"/response/#{incoming_message.id}" \
"/attach/html/#{jpeg_attachment.url_part_number}" \
"/interesting.jpg.html"
@@ -686,7 +686,7 @@
it 'returns the URL to the attachment with a cookie cookie_passthrough param' do
expect(attachment_url(jpeg_attachment)).to eq(
"http://test.host" \
- "/request/#{incoming_message.info_request_id}" \
+ "/request/#{incoming_message.info_request.url_title}" \
"/response/#{incoming_message.id}" \
"/attach/#{jpeg_attachment.url_part_number}" \
"/interesting.jpg?cookie_passthrough=1"
@@ -698,7 +698,7 @@
it 'returns the URL to the HTML version of the attachment' do
expect(attachment_url(jpeg_attachment, html: true)).to eq(
"http://test.host" \
- "/request/#{incoming_message.info_request_id}" \
+ "/request/#{incoming_message.info_request.url_title}" \
"/response/#{incoming_message.id}" \
"/attach/html/#{jpeg_attachment.url_part_number}" \
"/interesting.jpg.html"
diff --git a/spec/integration/errors_spec.rb b/spec/integration/errors_spec.rb
index 228bd9298f..7254826b68 100644
--- a/spec/integration/errors_spec.rb
+++ b/spec/integration/errors_spec.rb
@@ -90,6 +90,7 @@
it 'should render a 403 with text body for attempts at directory listing for attachments' do
info_request = FactoryBot.create(:info_request_with_pdf_attachment)
id = info_request.id
+ url_title = info_request.url_title
prefix = id.to_s[0..2]
msg_id = info_request.incoming_messages.first.id
@@ -99,11 +100,11 @@
)
FileUtils.mkdir_p(cache_key_path)
- get "/request/#{id}/response/#{msg_id}/attach/html/1/"
+ get "/request/#{url_title}/response/#{msg_id}/attach/html/1/"
expect(response.body).to include('Directory listing not allowed')
expect(response.code).to eq('403')
- get "/request/#{id}/response/#{msg_id}/attach/html"
+ get "/request/#{url_title}/response/#{msg_id}/attach/html"
expect(response.body).to include('Directory listing not allowed')
expect(response.code).to eq('403')
end
diff --git a/spec/integration/incoming_mail_spec.rb b/spec/integration/incoming_mail_spec.rb
index 98844c2890..40451ba816 100644
--- a/spec/integration/incoming_mail_spec.rb
+++ b/spec/integration/incoming_mail_spec.rb
@@ -23,14 +23,14 @@
email_to: info_request.incoming_email)
attachment_1_path = get_attachment_path(
- info_request.id,
+ info_request.url_title,
incoming_message_id: info_request.incoming_messages.first.id,
part: 2,
file_name: 'hello world.txt',
skip_cache: 1
)
attachment_2_path = get_attachment_path(
- info_request.id,
+ info_request.url_title,
incoming_message_id: info_request.incoming_messages.first.id,
part: 3,
file_name: 'hello world.txt',
@@ -65,7 +65,7 @@
receive_incoming_mail('incoming-request-two-same-name.email',
email_to: info_request.incoming_email)
attachment_path = get_attachment_as_html_path(
- info_request.id,
+ info_request.url_title,
incoming_message_id: info_request.incoming_messages.first.id,
part: 2,
file_name: 'hello world.txt.html',
@@ -83,7 +83,7 @@
receive_incoming_mail('incoming-request-pdf-attachment.email',
email_to: info_request.incoming_email)
attachment_path = get_attachment_as_html_path(
- info_request.id,
+ info_request.url_title,
incoming_message_id: info_request.incoming_messages.first.id,
part: 2,
file_name: 'fs 50379341.pdf.html',
@@ -103,7 +103,7 @@
# asking for an attachment by the wrong filename should result in
# redirecting back to the incoming message
visit get_attachment_as_html_path(
- info_request.id,
+ info_request.url_title,
incoming_message_id: info_request.incoming_messages.first.id,
part: 2,
file_name: 'hello world.txt.baz.html',
@@ -118,7 +118,7 @@
email_to: info_request.incoming_email)
attachment_path = get_attachment_path(
- info_request.id,
+ info_request.url_title,
incoming_message_id: info_request.incoming_messages.first.id,
part: 2,
file_name: 'hello.qwglhm',
diff --git a/spec/integration/prominence/viewing_attachment_as_html_spec.rb b/spec/integration/prominence/viewing_attachment_as_html_spec.rb
index beeb7d3604..3f7e01b14e 100644
--- a/spec/integration/prominence/viewing_attachment_as_html_spec.rb
+++ b/spec/integration/prominence/viewing_attachment_as_html_spec.rb
@@ -8,7 +8,7 @@
let(:within_session) do
-> {
visit get_attachment_as_html_url(
- info_request.id,
+ info_request.url_title,
incoming_message_id: attachment.incoming_message_id,
part: attachment.url_part_number,
file_name: "#{attachment.display_filename}.html"
diff --git a/spec/integration/prominence/viewing_raw_attachment_spec.rb b/spec/integration/prominence/viewing_raw_attachment_spec.rb
index 7d49a6cd0f..2e1ec5922a 100644
--- a/spec/integration/prominence/viewing_raw_attachment_spec.rb
+++ b/spec/integration/prominence/viewing_raw_attachment_spec.rb
@@ -10,7 +10,7 @@
rebuild_raw_emails(info_request)
visit get_attachment_url(
- info_request.id,
+ info_request.url_title,
incoming_message_id: attachment.incoming_message_id,
part: attachment.url_part_number,
file_name: attachment.display_filename
diff --git a/spec/integration/view_request_spec.rb b/spec/integration/view_request_spec.rb
index 20424be918..0d35264dfe 100644
--- a/spec/integration/view_request_spec.rb
+++ b/spec/integration/view_request_spec.rb
@@ -51,7 +51,7 @@
)
rebuild_raw_emails(info_request)
- attachment_url = "/es/request/#{info_request.id}/response/" \
+ attachment_url = "/es/request/#{info_request.url_title}/response/" \
"#{incoming_message.id}/attach/#{attachment.url_part_number}/" \
"#{attachment.filename}"
using_session(non_owner) { visit(attachment_url) }
diff --git a/spec/routing/redirects_spec.rb b/spec/routing/redirects_spec.rb
index f4d94a31ec..6a3cf109ee 100644
--- a/spec/routing/redirects_spec.rb
+++ b/spec/routing/redirects_spec.rb
@@ -18,4 +18,16 @@
get('/request/105/followups/new')
expect(response).to redirect_to('/request/the_cost_of_boring/followups/new')
end
+
+ it 'routes numerical request attachment routes to URL title attachment routes' do
+ get('/request/105/response/1/attach/2/filename.txt')
+ expect(response).to redirect_to(
+ '/request/the_cost_of_boring/response/1/attach/2/filename.txt'
+ )
+
+ get('/request/105/response/1/attach/html/2/filename.txt.html')
+ expect(response).to redirect_to(
+ '/request/the_cost_of_boring/response/1/attach/html/2/filename.txt.html'
+ )
+ end
end
From f23496da2941f14092ea64a4bd49cde642a9186b Mon Sep 17 00:00:00 2001
From: Alexander Griffen
Date: Mon, 20 Nov 2023 13:30:35 +0000
Subject: [PATCH 11/12] URL Perms: Reports, widgets controllers
Replace request IDs in URLs with titles
---
app/controllers/reports_controller.rb | 2 +-
app/controllers/widget_votes_controller.rb | 3 +-
app/controllers/widgets_controller.rb | 2 +-
app/views/request/_act.html.erb | 2 +-
app/views/widgets/new.html.erb | 4 +-
app/views/widgets/show.html.erb | 2 +-
config/routes.rb | 2 +-
config/routes/redirects.rb | 8 ++
spec/controllers/reports_controller_spec.rb | 84 +++++++++----------
.../widget_votes_controller_spec.rb | 20 +++--
spec/controllers/widgets_controller_spec.rb | 48 +++++------
spec/routing/redirects_spec.rb | 9 ++
12 files changed, 103 insertions(+), 83 deletions(-)
diff --git a/app/controllers/reports_controller.rb b/app/controllers/reports_controller.rb
index 5daecd8ed2..30e590bf5b 100644
--- a/app/controllers/reports_controller.rb
+++ b/app/controllers/reports_controller.rb
@@ -50,7 +50,7 @@ def new
def set_info_request
@info_request = InfoRequest.not_embargoed.
- find_by_url_title!(params[:request_id])
+ find_by_url_title!(params[:request_url_title])
end
def set_comment
diff --git a/app/controllers/widget_votes_controller.rb b/app/controllers/widget_votes_controller.rb
index d5338ddc0c..7e097b4df0 100644
--- a/app/controllers/widget_votes_controller.rb
+++ b/app/controllers/widget_votes_controller.rb
@@ -37,7 +37,8 @@ def check_widget_config
end
def find_info_request
- @info_request = InfoRequest.not_embargoed.find(params[:request_id])
+ @info_request = InfoRequest.not_embargoed.
+ find_by!(url_title: params[:request_url_title])
end
def check_prominence
diff --git a/app/controllers/widgets_controller.rb b/app/controllers/widgets_controller.rb
index 4484734993..1a57827989 100644
--- a/app/controllers/widgets_controller.rb
+++ b/app/controllers/widgets_controller.rb
@@ -42,7 +42,7 @@ def check_widget_config
end
def find_info_request
- @info_request = InfoRequest.find(params[:request_id])
+ @info_request = InfoRequest.find_by!(url_title: params[:request_url_title])
end
def check_prominence
diff --git a/app/views/request/_act.html.erb b/app/views/request/_act.html.erb
index a055c6148a..844306e5f1 100644
--- a/app/views/request/_act.html.erb
+++ b/app/views/request/_act.html.erb
@@ -44,7 +44,7 @@
<% if AlaveteliConfiguration::enable_widgets %>
- <%= link_to _("Create a widget for this request"), new_request_widget_path(info_request) %>
+ <%= link_to _("Create a widget for this request"), new_request_widget_path(info_request.url_title) %>
<% end %>
diff --git a/app/views/widgets/new.html.erb b/app/views/widgets/new.html.erb
index 0d24d2ff66..6e13b67972 100644
--- a/app/views/widgets/new.html.erb
+++ b/app/views/widgets/new.html.erb
@@ -4,12 +4,12 @@
<%= _("To add a widget for {{info_request_title}}, copy and paste " \
"the following code to your web page:",
:info_request_title => @info_request.title) %>
-
+
<%= _("The widget will look like this:") %>
-
+
diff --git a/app/views/widgets/show.html.erb b/app/views/widgets/show.html.erb
index d0a1207720..2786b6f69d 100644
--- a/app/views/widgets/show.html.erb
+++ b/app/views/widgets/show.html.erb
@@ -57,7 +57,7 @@
<%= _('I also want to know!') %>
<% end %>
<% else %>
- <%= form_tag request_widget_votes_url(@info_request),
+ <%= form_tag request_widget_votes_url(request_url_title: @info_request.url_title),
:method => 'post', :target => '_top' do %>
<%= submit_tag _('I also want to know!'),
:class => 'alaveteli-widget__bottom__action alaveteli-widget__button--create-vote',
diff --git a/config/routes.rb b/config/routes.rb
index 442fc4357b..3bc4c9d9a9 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -234,7 +234,7 @@ def matches?(request)
end
get '/health_checks' => redirect('/health/checks')
- resources :request, :only => [] do
+ resources :request, :only => [], param: :url_title do
resource :report, :only => [:new, :create]
resource :widget, :only => [:new, :show]
resources :widget_votes, :only => [:create]
diff --git a/config/routes/redirects.rb b/config/routes/redirects.rb
index cd004ca778..4c6f977ce7 100644
--- a/config/routes/redirects.rb
+++ b/config/routes/redirects.rb
@@ -36,3 +36,11 @@
format: false,
constraints: { id: /\d+/, suffix: %r(response/\d+/attach(/html)?/\d+/.*) },
to: info_request_redirect
+
+get '/request/:id(/*suffix)',
+ constraints: { id: /\d+/, suffix: %r(report/new) },
+ to: info_request_redirect
+
+get '/request/:id(/*suffix)',
+ constraints: { id: /\d+/, suffix: %r(widget(/new)?) },
+ to: info_request_redirect
diff --git a/spec/controllers/reports_controller_spec.rb b/spec/controllers/reports_controller_spec.rb
index 893eb786e8..e4bee67f6b 100644
--- a/spec/controllers/reports_controller_spec.rb
+++ b/spec/controllers/reports_controller_spec.rb
@@ -8,7 +8,7 @@
context "when reporting a request when not logged in" do
it "should only allow logged-in users to report requests" do
post :create, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
reason: "my reason"
}
expect(flash[:notice]).to match(/You need to be logged in/)
@@ -24,7 +24,7 @@
it "finds the expected request" do
post :create, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
reason: "my reason"
}
@@ -33,7 +33,7 @@
it "sets reportable to the request" do
post :create, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
reason: "my reason"
}
@@ -42,7 +42,7 @@
it "sets report_reasons to the request report reasons" do
post :create, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
reason: "my reason"
}
@@ -51,7 +51,7 @@
it 'logs an event' do
post :create, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
reason: 'my reason'
}
last_event = info_request.reload.last_event
@@ -68,7 +68,7 @@
it 'ignores an empty comment_id param' do
post :create, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
comment_id: '',
reason: "my reason"
}
@@ -77,14 +77,14 @@
it "should 404 for non-existent requests" do
expect {
- post :create, params: { request_id: "hjksfdhjk_louytu_qqxxx" }
+ post :create, params: { request_url_title: "hjksfdhjk_louytu_qqxxx" }
}.to raise_error(ActiveRecord::RecordNotFound)
end
it 'should 404 for embargoed requests' do
info_request = FactoryBot.create(:embargoed_request)
expect {
- post :create, params: { request_id: info_request.url_title }
+ post :create, params: { request_url_title: info_request.url_title }
}.to raise_error(ActiveRecord::RecordNotFound)
end
@@ -92,7 +92,7 @@
expect(info_request.attention_requested).to eq(false)
post :create, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
reason: "my reason"
}
expect(response).
@@ -107,7 +107,7 @@
expected = "This request has been reported for administrator attention"
post :create, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
reason: "my reason",
message: "It's just not"
}
@@ -117,14 +117,14 @@
it "should not allow a request to be reported twice" do
post :create, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
reason: "my reason"
}
expect(response).
to redirect_to show_request_url(info_request.url_title)
post :create, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
reason: "my reason"
}
expect(response).
@@ -134,7 +134,7 @@
it "should send an email from the reporter to admins" do
post :create, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
reason: "my reason",
message: "It's just not"
}
@@ -150,7 +150,7 @@
it "should force the user to pick a reason" do
post :create, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
reason: ""
}
expect(response).to render_template("new")
@@ -170,7 +170,7 @@
it "finds the expected request" do
post :create, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
comment_id: comment.id,
reason: "my reason"
}
@@ -180,7 +180,7 @@
it "finds the expected comment" do
post :create, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
comment_id: comment.id,
reason: "my reason"
}
@@ -190,7 +190,7 @@
it "sets reportable to the comment" do
post :create, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
comment_id: comment.id,
reason: "my reason"
}
@@ -200,7 +200,7 @@
it "sets report_reasons to the comment report reasons" do
post :create, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
comment_id: comment.id,
reason: "my reason"
}
@@ -212,7 +212,7 @@
new_comment = FactoryBot.create(:comment)
expect {
post :create, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
comment_id: new_comment.id,
reason: "my reason"
}
@@ -221,7 +221,7 @@
it "marks the comment as having been reported" do
post :create, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
comment_id: comment.id,
reason: "my reason"
}
@@ -232,7 +232,7 @@
it "does not mark the parent request as having been reported" do
post :create, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
comment_id: comment.id,
reason: "my reason"
}
@@ -244,7 +244,7 @@
it "sends an email alerting admins to the report" do
post :create, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
comment_id: comment.id,
reason: "my reason",
message: "It's just not"
@@ -272,7 +272,7 @@
"administrator attention"
post :create, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
comment_id: comment.id,
reason: "my reason",
message: "It's just not"
@@ -283,7 +283,7 @@
it "redirects to the parent info_request page" do
post :create, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
comment_id: comment.id,
reason: "my reason",
message: "It's just not"
@@ -301,7 +301,7 @@
context "not logged in" do
it "should require the user to be logged in" do
- get :new, params: { request_id: info_request.url_title }
+ get :new, params: { request_url_title: info_request.url_title }
expect(response).
to redirect_to(signin_path(token: PostRedirect.last.token))
end
@@ -313,42 +313,42 @@
end
it "finds the expected request" do
- get :new, params: { request_id: info_request.url_title }
+ get :new, params: { request_url_title: info_request.url_title }
expect(assigns(:info_request)).to eq(info_request)
end
it "sets reportable to the request" do
- get :new, params: { request_id: info_request.url_title }
+ get :new, params: { request_url_title: info_request.url_title }
expect(assigns(:reportable)).to eq(info_request)
end
it "sets report_reasons to the request report reasons" do
- get :new, params: { request_id: info_request.url_title }
+ get :new, params: { request_url_title: info_request.url_title }
expect(assigns(:report_reasons)).to eq(info_request.report_reasons)
end
it "sets the page title" do
- get :new, params: { request_id: info_request.url_title }
+ get :new, params: { request_url_title: info_request.url_title }
expect(assigns(:title)).
to eq("Report request: #{ info_request.title }")
end
it "should show the form" do
- get :new, params: { request_id: info_request.url_title }
+ get :new, params: { request_url_title: info_request.url_title }
expect(response).to render_template("new")
end
it "should 404 for non-existent requests" do
expect {
- get :new, params: { request_id: "hjksfdhjk_louytu_qqxxx" }
+ get :new, params: { request_url_title: "hjksfdhjk_louytu_qqxxx" }
}.to raise_error(ActiveRecord::RecordNotFound)
end
it 'should 404 for embargoed requests' do
info_request = FactoryBot.create(:embargoed_request)
expect {
- get :new, params: { request_id: info_request.url_title }
+ get :new, params: { request_url_title: info_request.url_title }
}.to raise_error(ActiveRecord::RecordNotFound)
end
end
@@ -367,7 +367,7 @@
it "finds the expected request" do
get :new, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
comment_id: comment.id
}
expect(assigns(:info_request)).to eq(info_request)
@@ -375,7 +375,7 @@
it "finds the expected comment" do
get :new, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
comment_id: comment.id,
reason: "my reason"
}
@@ -385,7 +385,7 @@
it "sets reportable to the comment" do
get :new, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
comment_id: comment.id
}
@@ -394,7 +394,7 @@
it "sets report_reasons to the comment report reasons" do
get :new, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
comment_id: comment.id
}
@@ -403,7 +403,7 @@
it "sets the page title" do
get :new, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
comment_id: comment.id
}
@@ -415,7 +415,7 @@
new_comment = FactoryBot.create(:comment)
expect {
get :new, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
comment_id: new_comment.id
}
}.to raise_error(ActiveRecord::RecordNotFound)
@@ -423,7 +423,7 @@
it "should show the form" do
get :new, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
comment_id: comment.id
}
expect(response).to render_template("new")
@@ -431,7 +431,7 @@
it "copies the comment id into a hidden form field" do
get :new, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
comment_id: comment.id
}
expect(response.body).
@@ -442,7 +442,7 @@
it "should 404 for non-existent requests" do
expect {
get :new, params: {
- request_id: "hjksfdhjk_louytu_qqxxx",
+ request_url_title: "hjksfdhjk_louytu_qqxxx",
comment_id: comment.id
}
}.to raise_error(ActiveRecord::RecordNotFound)
@@ -452,7 +452,7 @@
info_request = FactoryBot.create(:embargoed_request)
expect {
get :new, params: {
- request_id: info_request.url_title,
+ request_url_title: info_request.url_title,
comment_id: comment.id
}
}.to raise_error(ActiveRecord::RecordNotFound)
diff --git a/spec/controllers/widget_votes_controller_spec.rb b/spec/controllers/widget_votes_controller_spec.rb
index 88028d5502..ab9f4ef4c4 100644
--- a/spec/controllers/widget_votes_controller_spec.rb
+++ b/spec/controllers/widget_votes_controller_spec.rb
@@ -11,12 +11,12 @@
end
it 'should find the info request' do
- post :create, params: { request_id: info_request.id }
+ post :create, params: { request_url_title: info_request.url_title }
expect(assigns[:info_request]).to eq(info_request)
end
it 'should redirect to the track path for the info request' do
- post :create, params: { request_id: info_request.id }
+ post :create, params: { request_url_title: info_request.url_title }
track_thing = TrackThing.create_track_for_request(info_request)
expect(response).to redirect_to(do_track_path(track_thing))
end
@@ -24,7 +24,7 @@
context 'for a non-logged-in user without a tracking cookie' do
it 'sets a tracking cookie' do
allow(SecureRandom).to receive(:hex).and_return(mock_cookie)
- post :create, params: { request_id: info_request.id }
+ post :create, params: { request_url_title: info_request.url_title }
expect(cookies[:widget_vote]).to eq(mock_cookie)
end
@@ -34,7 +34,7 @@
widget_votes.
where(cookie: mock_cookie)
- post :create, params: { request_id: info_request.id }
+ post :create, params: { request_url_title: info_request.url_title }
expect(votes.size).to eq(1)
end
@@ -43,7 +43,7 @@
context 'for a non-logged-in user with a tracking cookie' do
it 'retains the existing tracking cookie' do
request.cookies['widget_vote'] = mock_cookie
- post :create, params: { request_id: info_request.id }
+ post :create, params: { request_url_title: info_request.url_title }
expect(cookies[:widget_vote]).to eq(mock_cookie)
end
@@ -53,7 +53,7 @@
widget_votes.
where(cookie: mock_cookie)
- post :create, params: { request_id: info_request.id }
+ post :create, params: { request_url_title: info_request.url_title }
expect(votes.size).to eq(1)
end
@@ -65,7 +65,7 @@
to receive(:enable_widgets).
and_return(false)
expect {
- post :create, params: { request_id: info_request.id }
+ post :create, params: { request_url_title: info_request.url_title }
}.to raise_error(ActiveRecord::RecordNotFound)
end
end
@@ -74,7 +74,7 @@
it 'should return a 403' do
info_request.prominence = 'hidden'
info_request.save!
- post :create, params: { request_id: info_request.id }
+ post :create, params: { request_url_title: info_request.url_title }
expect(response.code).to eq("403")
end
end
@@ -83,7 +83,9 @@
it 'should raise an ActiveRecord::RecordNotFound error' do
embargoed_request = FactoryBot.create(:embargoed_request)
expect {
- post :create, params: { request_id: embargoed_request.id }
+ post :create, params: {
+ request_url_title: embargoed_request.url_title
+ }
}.to raise_error ActiveRecord::RecordNotFound
end
end
diff --git a/spec/controllers/widgets_controller_spec.rb b/spec/controllers/widgets_controller_spec.rb
index 44ab9996f3..7930e163db 100644
--- a/spec/controllers/widgets_controller_spec.rb
+++ b/spec/controllers/widgets_controller_spec.rb
@@ -10,22 +10,22 @@
end
it 'should render the widget template' do
- get :show, params: { request_id: @info_request.id }
+ get :show, params: { request_url_title: @info_request.url_title }
expect(response).to render_template('show')
end
it 'should find the info request' do
- get :show, params: { request_id: @info_request.id }
+ get :show, params: { request_url_title: @info_request.url_title }
expect(assigns[:info_request]).to eq(@info_request)
end
it 'should create a track thing for the request' do
- get :show, params: { request_id: @info_request.id }
+ get :show, params: { request_url_title: @info_request.url_title }
expect(assigns[:track_thing].info_request).to eq(@info_request)
end
it 'should assign the request status' do
- get :show, params: { request_id: @info_request.id }
+ get :show, params: { request_url_title: @info_request.url_title }
expect(assigns[:status]).to eq(@info_request.calculate_status)
end
@@ -42,7 +42,7 @@
@info_request.widget_votes.create(cookie: SecureRandom.hex(10))
end
- get :show, params: { request_id: @info_request.id }
+ get :show, params: { request_url_title: @info_request.url_title }
# Count should be 5
# 1 for the request's owning user
@@ -53,25 +53,25 @@
it 'sets user_owns_request to true if the user owns the request' do
sign_in @info_request.user
- get :show, params: { request_id: @info_request.id }
+ get :show, params: { request_url_title: @info_request.url_title }
expect(assigns[:user_owns_request]).to be true
end
it 'sets user_owns_request to false if the user does not own the request' do
sign_in FactoryBot.create(:user)
- get :show, params: { request_id: @info_request.id }
+ get :show, params: { request_url_title: @info_request.url_title }
expect(assigns[:user_owns_request]).to be false
end
it 'should not send an x-frame-options header' do
- get :show, params: { request_id: @info_request.id }
+ get :show, params: { request_url_title: @info_request.url_title }
expect(response.headers["X-Frame-Options"]).to be_nil
end
context 'for a non-logged-in user with a tracking cookie' do
it 'will not find existing tracks' do
request.cookies['widget_vote'] = mock_cookie
- get :show, params: { request_id: @info_request.id }
+ get :show, params: { request_url_title: @info_request.url_title }
expect(assigns[:existing_track]).to be_nil
end
@@ -80,14 +80,14 @@
info_request: @info_request,
cookie: mock_cookie)
request.cookies['widget_vote'] = vote.cookie
- get :show, params: { request_id: @info_request.id }
+ get :show, params: { request_url_title: @info_request.url_title }
expect(assigns[:existing_vote]).to be true
end
it 'will not find any existing votes if none exist' do
WidgetVote.delete_all
request.cookies['widget_vote'] = mock_cookie
- get :show, params: { request_id: @info_request.id }
+ get :show, params: { request_url_title: @info_request.url_title }
expect(assigns[:existing_vote]).to be false
end
end
@@ -95,13 +95,13 @@
context 'for a non-logged-in user without a tracking cookie' do
it 'will not find existing tracks' do
request.cookies['widget_vote'] = nil
- get :show, params: { request_id: @info_request.id }
+ get :show, params: { request_url_title: @info_request.url_title }
expect(assigns[:existing_track]).to be_nil
end
it 'will not find any existing votes' do
request.cookies['widget_vote'] = nil
- get :show, params: { request_id: @info_request.id }
+ get :show, params: { request_url_title: @info_request.url_title }
expect(assigns[:existing_vote]).to be false
end
end
@@ -115,7 +115,7 @@
track.save!
sign_in user
- get :show, params: { request_id: @info_request.id }
+ get :show, params: { request_url_title: @info_request.url_title }
expect(assigns[:existing_track]).to eq(track)
end
@@ -127,7 +127,7 @@
user = FactoryBot.create(:user)
sign_in user
- get :show, params: { request_id: @info_request.id }
+ get :show, params: { request_url_title: @info_request.url_title }
expect(assigns[:existing_track]).to be_nil
end
@@ -140,7 +140,7 @@
sign_in @info_request.user
request.cookies['widget_vote'] = mock_cookie
- get :show, params: { request_id: @info_request.id }
+ get :show, params: { request_url_title: @info_request.url_title }
expect(assigns[:existing_vote]).to be true
end
@@ -151,7 +151,7 @@
sign_in @info_request.user
request.cookies['widget_vote'] = mock_cookie
- get :show, params: { request_id: @info_request.id }
+ get :show, params: { request_url_title: @info_request.url_title }
expect(assigns[:existing_vote]).to be false
end
@@ -163,7 +163,7 @@
to receive(:enable_widgets).
and_return(false)
expect {
- get :show, params: { request_id: @info_request.id }
+ get :show, params: { request_url_title: @info_request.url_title }
}.to raise_error(ActiveRecord::RecordNotFound)
end
end
@@ -172,7 +172,7 @@
it 'should return a 403' do
@info_request.prominence = 'hidden'
@info_request.save!
- get :show, params: { request_id: @info_request.id }
+ get :show, params: { request_url_title: @info_request.url_title }
expect(response.code).to eq("403")
end
@@ -182,7 +182,7 @@
cookie: mock_cookie)
sign_in @info_request.user
- get :show, params: { request_id: @info_request.id }
+ get :show, params: { request_url_title: @info_request.url_title }
expect(assigns[:existing_vote]).to be false
end
@@ -198,12 +198,12 @@
end
it 'should render the create widget template' do
- get :new, params: { request_id: @info_request.id }
+ get :new, params: { request_url_title: @info_request.url_title }
expect(response).to render_template('new')
end
it 'should find the info request' do
- get :new, params: { request_id: @info_request.id }
+ get :new, params: { request_url_title: @info_request.url_title }
expect(assigns[:info_request]).to eq(@info_request)
end
@@ -213,7 +213,7 @@
to receive(:enable_widgets).
and_return(false)
expect {
- get :new, params: { request_id: @info_request.id }
+ get :new, params: { request_url_title: @info_request.url_title }
}.to raise_error(ActiveRecord::RecordNotFound)
end
end
@@ -222,7 +222,7 @@
it 'should return a 403' do
@info_request.prominence = 'hidden'
@info_request.save!
- get :show, params: { request_id: @info_request.id }
+ get :show, params: { request_url_title: @info_request.url_title }
expect(response.code).to eq("403")
end
end
diff --git a/spec/routing/redirects_spec.rb b/spec/routing/redirects_spec.rb
index 6a3cf109ee..bc02d8026c 100644
--- a/spec/routing/redirects_spec.rb
+++ b/spec/routing/redirects_spec.rb
@@ -17,6 +17,15 @@
it 'routes numerical request member routes to URL title member routes' do
get('/request/105/followups/new')
expect(response).to redirect_to('/request/the_cost_of_boring/followups/new')
+
+ get('/request/105/report/new')
+ expect(response).to redirect_to('/request/the_cost_of_boring/report/new')
+
+ get('/request/105/widget')
+ expect(response).to redirect_to('/request/the_cost_of_boring/widget')
+
+ get('/request/105/widget/new')
+ expect(response).to redirect_to('/request/the_cost_of_boring/widget/new')
end
it 'routes numerical request attachment routes to URL title attachment routes' do
From dcca4ed3481fdc427b9e1293d65debc92109837c Mon Sep 17 00:00:00 2001
From: Alexander Griffen
Date: Mon, 27 Nov 2023 15:23:44 +0000
Subject: [PATCH 12/12] Update changelog
---
doc/CHANGES.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/doc/CHANGES.md b/doc/CHANGES.md
index 3194f69996..973df430b6 100644
--- a/doc/CHANGES.md
+++ b/doc/CHANGES.md
@@ -2,6 +2,8 @@
## Highlighted Features
+* Change request URL patterns to only use titles rather than request IDs
+ (Alexander Griffen, Graeme Porteous)
* Colourise holding pen guess scores (Gareth Rees)
* Fix default holding pen guess scores (Gareth Rees)
* Add support for Debian 12 "Bookworm" (Graeme Porteous)