From 3d53366678ac5d2645d62d1428b7b538d32ef595 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Thu, 26 Apr 2018 10:52:41 +0200 Subject: [PATCH] [fix #1877] add maintenance mode --- app/controllers/application_controller.rb | 22 ++++++++ config/features.rb | 2 + .../application_controller_spec.rb | 53 +++++++++++++++++++ 3 files changed, 77 insertions(+) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 870441667..4db6b6ab2 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,10 +1,13 @@ class ApplicationController < ActionController::Base + MAINTENANCE_MESSAGE = 'Le site est actuellement en maintenance. Il sera à nouveau disponible dans un court instant.' + # Prevent CSRF attacks by raising an exception. # For APIs, you may want to use :null_session instead. protect_from_forgery with: :exception before_action :load_navbar_left_pannel_partial_url before_action :set_raven_context before_action :authorize_request_for_profiler + before_action :reject, if: -> { Flipflop.maintenance_mode? } before_action :staging_authenticate @@ -135,4 +138,23 @@ class ApplicationController < ActionController::Base ) # END OF FIXME end + + def reject + authorized_request = + request.path_info == '/' || + request.path_info.start_with?('/manager') || + request.path_info.start_with?('/administrations') + + api_request = request.path_info.start_with?('/api/') + + if administration_signed_in? || authorized_request + flash.now.alert = MAINTENANCE_MESSAGE + elsif api_request + render json: { error: MAINTENANCE_MESSAGE }.to_json, status: :service_unavailable + else + %i(user gestionnaire administrateur).each { |role| sign_out(role) } + flash[:alert] = MAINTENANCE_MESSAGE + redirect_to root_path + end + end end diff --git a/config/features.rb b/config/features.rb index 2fb97a82e..14e779b0c 100644 --- a/config/features.rb +++ b/config/features.rb @@ -21,4 +21,6 @@ Flipflop.configure do feature :weekly_overview, default: Rails.env.production? end + + feature :maintenance_mode end diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index 89d601eaa..ce2dbc1c1 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -82,4 +82,57 @@ describe ApplicationController, type: :controller do end end end + + describe 'reject before action' do + let(:path_info) { '/one_path' } + + before do + allow(@controller).to receive(:redirect_to) + allow(@controller).to receive(:sign_out) + allow(@controller).to receive(:render) + @request.path_info = path_info + end + + context 'when no administration is logged in' do + before { @controller.send(:reject) } + + it { expect(@controller).to have_received(:sign_out).with(:user) } + it { expect(@controller).to have_received(:sign_out).with(:gestionnaire) } + it { expect(@controller).to have_received(:sign_out).with(:administrateur) } + it { expect(flash[:alert]).to eq(ApplicationController::MAINTENANCE_MESSAGE) } + it { expect(@controller).to have_received(:redirect_to).with(root_path) } + + context 'when the path is safe' do + %w(/ /manager /administrations).each do |path| + let(:path_info) { path } + + it { expect(@controller).not_to have_received(:sign_out) } + it { expect(@controller).not_to have_received(:redirect_to) } + it { expect(flash.alert).to eq(ApplicationController::MAINTENANCE_MESSAGE) } + end + end + + context 'when the path is api related' do + let(:path_info) { '/api/some-stuff' } + let(:json_error) { { error: ApplicationController::MAINTENANCE_MESSAGE }.to_json } + it { expect(@controller).not_to have_received(:sign_out) } + it { expect(@controller).not_to have_received(:redirect_to) } + it { expect(flash.alert).to be_nil } + it { expect(@controller).to have_received(:render).with({ json: json_error, status: :service_unavailable }) } + end + end + + context 'when a administration is logged in' do + let(:current_administration) { create(:administration) } + + before do + sign_in(current_administration) + @controller.send(:reject) + end + + it { expect(@controller).not_to have_received(:sign_out) } + it { expect(@controller).not_to have_received(:redirect_to) } + it { expect(flash[:alert]).to eq(ApplicationController::MAINTENANCE_MESSAGE) } + end + end end