Merge pull request #3846 from consul/redirects

Avoid redirects with unprotected query params
This commit is contained in:
Javier Martín
2019-11-12 20:12:24 +01:00
committed by GitHub
21 changed files with 145 additions and 21 deletions

View File

@@ -15,14 +15,14 @@ class Admin::HiddenBudgetInvestmentsController < Admin::BaseController
def confirm_hide
@investment.confirm_hide
redirect_to request.query_parameters.merge(action: :index)
redirect_with_query_params_to(action: :index)
end
def restore
@investment.restore(recursive: true)
@investment.ignore_flag
Activity.log(current_user, :restore, @investment)
redirect_to request.query_parameters.merge(action: :index)
redirect_with_query_params_to(action: :index)
end
private

View File

@@ -10,14 +10,14 @@ class Admin::HiddenCommentsController < Admin::BaseController
def confirm_hide
@comment.confirm_hide
redirect_to request.query_parameters.merge(action: :index)
redirect_with_query_params_to(action: :index)
end
def restore
@comment.restore(recursive: true)
@comment.ignore_flag
Activity.log(current_user, :restore, @comment)
redirect_to request.query_parameters.merge(action: :index)
redirect_with_query_params_to(action: :index)
end
private

View File

@@ -13,14 +13,14 @@ class Admin::HiddenDebatesController < Admin::BaseController
def confirm_hide
@debate.confirm_hide
redirect_to request.query_parameters.merge(action: :index)
redirect_with_query_params_to(action: :index)
end
def restore
@debate.restore!(recursive: true)
@debate.ignore_flag
Activity.log(current_user, :restore, @debate)
redirect_to request.query_parameters.merge(action: :index)
redirect_with_query_params_to(action: :index)
end
private

View File

@@ -14,14 +14,14 @@ class Admin::HiddenProposalsController < Admin::BaseController
def confirm_hide
@proposal.confirm_hide
redirect_to request.query_parameters.merge(action: :index)
redirect_with_query_params_to(action: :index)
end
def restore
@proposal.restore(recursive: true)
@proposal.ignore_flag
Activity.log(current_user, :restore, @proposal)
redirect_to request.query_parameters.merge(action: :index)
redirect_with_query_params_to(action: :index)
end
private

View File

@@ -15,13 +15,13 @@ class Admin::HiddenUsersController < Admin::BaseController
def confirm_hide
@user.confirm_hide
redirect_to request.query_parameters.merge(action: :index)
redirect_with_query_params_to(action: :index)
end
def restore
@user.restore
Activity.log(current_user, :restore, @user)
redirect_to request.query_parameters.merge(action: :index)
redirect_with_query_params_to(action: :index)
end
private

View File

@@ -19,11 +19,11 @@ class Admin::OrganizationsController < Admin::BaseController
def verify
@organization.verify
redirect_to request.query_parameters.merge(action: :index)
redirect_with_query_params_to(action: :index)
end
def reject
@organization.reject
redirect_to request.query_parameters.merge(action: :index)
redirect_with_query_params_to(action: :index)
end
end

View File

@@ -12,14 +12,14 @@ class Admin::ProposalNotificationsController < Admin::BaseController
def confirm_hide
@proposal_notification.confirm_hide
redirect_to request.query_parameters.merge(action: :index)
redirect_with_query_params_to(action: :index)
end
def restore
@proposal_notification.restore
@proposal_notification.ignore_flag
Activity.log(current_user, :restore, @proposal_notification)
redirect_to request.query_parameters.merge(action: :index)
redirect_with_query_params_to(action: :index)
end
private

View File

@@ -120,4 +120,11 @@ class ApplicationController < ActionController::Base
def current_budget
Budget.current
end
def redirect_with_query_params_to(options, response_status = {})
path_options = { controller: params[:controller] }.merge(options).merge(only_path: true)
path = url_for(request.query_parameters.merge(path_options))
redirect_to path, response_status
end
end

View File

@@ -28,7 +28,7 @@ module ModerateActions
User.where(id: author_ids).accessible_by(current_ability, :block).each { |user| block_user user }
end
redirect_to request.query_parameters.merge(action: :index)
redirect_with_query_params_to(action: :index)
end
private

View File

@@ -37,12 +37,12 @@ class DebatesController < ApplicationController
def unmark_featured
@debate.update!(featured_at: nil)
redirect_to request.query_parameters.merge(action: :index)
redirect_to debates_path
end
def mark_featured
@debate.update!(featured_at: Time.current)
redirect_to request.query_parameters.merge(action: :index)
redirect_to debates_path
end
def disable_recommendations

View File

@@ -11,7 +11,7 @@ class ImagesController < ApplicationController
else
flash[:alert] = t "images.actions.destroy.alert"
end
redirect_to params[:from]
redirect_to request.referer
end
format.js do
if @image.destroy

View File

@@ -9,7 +9,7 @@ class Moderation::UsersController < Moderation::BaseController
def hide_in_moderation_screen
block_user
redirect_to request.query_parameters.merge(action: :index), notice: I18n.t("moderation.users.notice_hide")
redirect_with_query_params_to({ action: :index }, { notice: I18n.t("moderation.users.notice_hide") })
end
def hide

View File

@@ -3,7 +3,7 @@ module ApplicationHelper
# notice: if query_params have a param which also exist in current path,
# it "overrides" (query_params is merged last)
def current_path_with_query_params(query_parameters)
url_for(request.query_parameters.merge(query_parameters))
url_for(request.query_parameters.merge(query_parameters).merge(only_path: true))
end
def markdown(text)

View File

@@ -26,7 +26,7 @@
<div class="sidebar-divider"></div>
<h2><%= t("budgets.investments.show.author") %></h2>
<div class="show-actions-menu">
<%= link_to image_path(investment.image, from: request.url),
<%= link_to image_path(investment.image),
method: :delete,
class: "button hollow alert expanded" do %>
<span class="icon-image"></span>

View File

@@ -0,0 +1,25 @@
require "rails_helper"
describe Admin::HiddenDebatesController do
before { sign_in create(:administrator).user }
describe "PUT confirm_hide" do
it "keeps query parameters while using protected redirects" do
debate = create(:debate, :hidden)
get :confirm_hide, params: { id: debate, filter: "all", host: "evil.dev" }
expect(response).to redirect_to "/admin/hidden_debates?filter=all"
end
end
describe "PUT restore" do
it "keeps query parameters while using protected redirects" do
debate = create(:debate, :hidden, :with_confirmed_hide)
get :restore, params: { id: debate, filter: "all", host: "evil.dev" }
expect(response).to redirect_to "/admin/hidden_debates?filter=all"
end
end
end

View File

@@ -0,0 +1,25 @@
require "rails_helper"
describe Admin::OrganizationsController do
before { sign_in create(:administrator).user }
describe "PUT verify" do
it "keeps query parameters while using protected redirects" do
organization = create(:organization)
get :verify, params: { id: organization, filter: "pending", host: "evil.dev" }
expect(response).to redirect_to "/admin/organizations?filter=pending"
end
end
describe "PUT reject" do
it "keeps query parameters while using protected redirects" do
organization = create(:organization)
get :reject, params: { id: organization, filter: "pending", host: "evil.dev" }
expect(response).to redirect_to "/admin/organizations?filter=pending"
end
end
end

View File

@@ -50,4 +50,15 @@ describe DebatesController do
end.not_to change { debate.reload.votes_for.size }
end
end
describe "PUT mark_featured" do
it "ignores query parameters" do
debate = create(:debate)
sign_in create(:administrator).user
get :mark_featured, params: { id: debate, controller: "proposals" }
expect(response).to redirect_to debates_path
end
end
end

View File

@@ -0,0 +1,17 @@
require "rails_helper"
describe ImagesController do
let(:user) { create(:user) }
before { sign_in user }
describe "DELETE destroy" do
it "redirects to the referer URL" do
image = create(:image, imageable: create(:proposal, author: user))
request.env["HTTP_REFERER"] = "/proposals"
delete :destroy, params: { id: image, from: "http://evil.dev" }
expect(response).to redirect_to "/proposals"
end
end
end

View File

@@ -0,0 +1,15 @@
require "rails_helper"
describe Moderation::Budgets::InvestmentsController do
before { sign_in create(:moderator).user }
describe "PUT moderate" do
it "keeps query parameters while using protected redirects" do
id = create(:budget_investment).id
get :moderate, params: { resource_ids: [id], filter: "all", host: "evil.dev" }
expect(response).to redirect_to "/moderation/budget_investments?filter=all&resource_ids%5B%5D=#{id}"
end
end
end

View File

@@ -0,0 +1,15 @@
require "rails_helper"
describe Moderation::UsersController do
before { sign_in create(:moderator).user }
describe "PUT hide_in_moderation_screen" do
it "keeps query parameters while using protected redirects" do
user = create(:user, email: "user@consul.dev")
get :hide_in_moderation_screen, params: { id: user, name_or_email: "user@consul.dev", host: "evil.dev" }
expect(response).to redirect_to "/moderation/users?name_or_email=user%40consul.dev"
end
end
end

View File

@@ -40,6 +40,15 @@ describe "Localization" do
expect(page).to have_select("locale-switcher", selected: "Español")
end
scenario "Keeps query parameters while using protected redirects", :js do
visit "/debates?order=created_at&host=evil.dev"
select("Español", from: "locale-switcher")
expect(current_host).to eq "http://127.0.0.1"
expect(page).to have_current_path "/debates?locale=es&order=created_at"
end
context "Only one locale" do
before do
allow(I18n).to receive(:available_locales).and_return([:en])