diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index ff085e6dc..ae9e1beb9 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -3,8 +3,17 @@ class ApplicationController < ActionController::Base rescue_from Pundit::NotAuthorizedError, with: :render_not_authorized + before_action :check_maintenance before_action :set_paper_trail_whodunnit + def check_maintenance + if FeatureToggle.maintenance_mode_enabled? && !%w[service-unavailable accessibility-statement privacy-notice cookies].include?(request.fullpath.split("?")[0].delete("/")) + redirect_to service_unavailable_path + elsif !FeatureToggle.maintenance_mode_enabled? && request.fullpath.split("?")[0].delete("/") == "service-unavailable" + redirect_back(fallback_location: root_path) + end + end + def render_not_found render "errors/not_found", status: :not_found end diff --git a/app/controllers/maintenance_controller.rb b/app/controllers/maintenance_controller.rb new file mode 100644 index 000000000..bb6ae1f80 --- /dev/null +++ b/app/controllers/maintenance_controller.rb @@ -0,0 +1,7 @@ +class MaintenanceController < ApplicationController + def service_unavailable + if current_user + sign_out + end + end +end diff --git a/app/services/feature_toggle.rb b/app/services/feature_toggle.rb index 379f51905..3cad5dadb 100644 --- a/app/services/feature_toggle.rb +++ b/app/services/feature_toggle.rb @@ -37,4 +37,8 @@ class FeatureToggle def self.duplicate_summary_enabled? !Rails.env.production? end + + def self.maintenance_mode_enabled? + false + end end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index ead90793a..d70c1e09a 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -91,11 +91,13 @@ navigation_classes: "govuk-header__navigation--end", ) do |component| component.product_name(name: t("service_name")) - if current_user.nil? - component.navigation_item(text: "Sign in", href: user_session_path) - else - component.navigation_item(text: "Your account", href: account_path) - component.navigation_item(text: "Sign out", href: destroy_user_session_path) + unless FeatureToggle.maintenance_mode_enabled? + if current_user.nil? + component.navigation_item(text: "Sign in", href: user_session_path) + else + component.navigation_item(text: "Your account", href: account_path) + component.navigation_item(text: "Sign out", href: destroy_user_session_path) + end end end %> diff --git a/app/views/maintenance/service_unavailable.html.erb b/app/views/maintenance/service_unavailable.html.erb new file mode 100644 index 000000000..cb106ce8d --- /dev/null +++ b/app/views/maintenance/service_unavailable.html.erb @@ -0,0 +1,11 @@ +

+ Sorry, the service is unavailable +

+ +
+
+

You will be able to use the service from 9am on Thursday 16 November 2023.

+

Changes from the page you were on have not been saved. Changes on pages where you have selected 'save and continue' have been saved.

+

<%= govuk_link_to "Contact the helpdesk", "https://dluhcdigital.atlassian.net/servicedesk/customer/portal/6/group/11" %> if you need help.

+
+
diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb index 74e6ce9a2..60cc29b3a 100644 --- a/config/initializers/sidekiq.rb +++ b/config/initializers/sidekiq.rb @@ -32,7 +32,10 @@ Redis.silence_deprecations = true Sidekiq.configure_server do |config| config.on(:startup) do - Sidekiq::Cron::Job.load_from_hash YAML.load_file("config/sidekiq_cron_schedule.yml") + Sidekiq::Cron::Job.all.each(&:destroy) + unless FeatureToggle.maintenance_mode_enabled? + Sidekiq::Cron::Job.load_from_hash YAML.load_file("config/sidekiq_cron_schedule.yml") + end end config.on(:shutdown) do diff --git a/config/routes.rb b/config/routes.rb index 621ee820c..498e7d9a2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -35,6 +35,7 @@ Rails.application.routes.draw do get "/accessibility-statement", to: "content#accessibility_statement" get "/privacy-notice", to: "content#privacy_notice" get "/data-sharing-agreement", to: "content#data_sharing_agreement" + get "/service-unavailable", to: "maintenance#service_unavailable" get "/download-23-24-lettings-form", to: "start#download_23_24_lettings_form" get "/download-22-23-lettings-form", to: "start#download_22_23_lettings_form" diff --git a/spec/controllers/maintenance_controller_spec.rb b/spec/controllers/maintenance_controller_spec.rb new file mode 100644 index 000000000..032ac4858 --- /dev/null +++ b/spec/controllers/maintenance_controller_spec.rb @@ -0,0 +1,27 @@ +require "rails_helper" + +RSpec.describe MaintenanceController do + let(:user) { FactoryBot.create(:user) } + + describe "GET #service_unavailable" do + context "when maintenance mode is enabled" do + it "logs the user out" do + allow(FeatureToggle).to receive(:maintenance_mode_enabled?).and_return(true) + sign_in user + expect(controller).to be_user_signed_in + get :service_unavailable + expect(controller).not_to be_user_signed_in + end + end + + context "when maintenance mode is disabled" do + it "doesn't log the user out" do + allow(FeatureToggle).to receive(:maintenance_mode_enabled?).and_return(false) + sign_in user + expect(controller).to be_user_signed_in + get :service_unavailable + expect(controller).to be_user_signed_in + end + end + end +end diff --git a/spec/features/user_spec.rb b/spec/features/user_spec.rb index 39327a75a..ca4e01ac6 100644 --- a/spec/features/user_spec.rb +++ b/spec/features/user_spec.rb @@ -139,6 +139,12 @@ RSpec.describe "User Features" do visit("/users/#{user.id}") expect(page).to have_content("Sign in to your account to submit CORE data") end + + it "does not show 'Sign in' link if maintenance mode is enabled" do + allow(FeatureToggle).to receive(:maintenance_mode_enabled?).and_return(true) + visit("/lettings-logs") + expect(page).not_to have_link("Sign in") + end end context "when the user is trying to log in with incorrect credentials" do @@ -324,6 +330,13 @@ RSpec.describe "User Features" do expect(page).to have_selector('[data-qa="change-data-protection-officer"]') expect(page).to have_selector('[data-qa="change-key-contact"]') end + + it "does not show 'Your account' or 'Sign out' links if maintenance mode is enabled" do + allow(FeatureToggle).to receive(:maintenance_mode_enabled?).and_return(true) + visit("/lettings-logs") + expect(page).not_to have_link("Your account") + expect(page).not_to have_link("Sign out") + end end context "when adding a new user" do diff --git a/spec/requests/content_controller_spec.rb b/spec/requests/content_controller_spec.rb index 07be4256b..c978ecaa9 100644 --- a/spec/requests/content_controller_spec.rb +++ b/spec/requests/content_controller_spec.rb @@ -4,45 +4,81 @@ RSpec.describe ContentController, type: :request do let(:headers) { { "Accept" => "text/html" } } let(:page) { Capybara::Node::Simple.new(response.body) } - describe "render privacy notice content page" do - before do - get "/privacy-notice", headers:, params: {} - end + describe "when maintenance mode is disabled" do + describe "render privacy notice content page" do + before do + get "/privacy-notice", headers:, params: {} + end - it "returns a 200" do - expect(response).to have_http_status(:success) - end + it "returns a 200" do + expect(response).to have_http_status(:success) + end - it "returns the page" do - expect(page).to have_title("Privacy notice") + it "returns the page" do + expect(page).to have_title("Privacy notice") + end end - end - describe "render accessibility statement content page" do - before do - get "/accessibility-statement", headers:, params: {} - end + describe "render accessibility statement content page" do + before do + get "/accessibility-statement", headers:, params: {} + end + + it "returns a 200" do + expect(response).to have_http_status(:success) + end - it "returns a 200" do - expect(response).to have_http_status(:success) + it "returns the page" do + expect(page).to have_title("Accessibility statement") + end end - it "returns the page" do - expect(page).to have_title("Accessibility statement") + describe "render data sharing agreement" do + before do + get "/data-sharing-agreement", headers:, params: {} + end + + it "returns a 200" do + expect(response).to have_http_status(:success) + end + + it "returns the page" do + expect(page).to have_title("Data sharing agreement") + end end end - describe "render data sharing agreement" do + describe "when maintenance mode is enabled" do before do - get "/data-sharing-agreement", headers:, params: {} + allow(FeatureToggle).to receive(:maintenance_mode_enabled?).and_return(true) end - it "returns a 200" do - expect(response).to have_http_status(:success) + describe "render privacy notice content page" do + before do + get "/privacy-notice", headers:, params: {} + end + + it "returns a 200" do + expect(response).to have_http_status(:success) + end + + it "returns the page" do + expect(page).to have_title("Privacy notice") + end end - it "returns the page" do - expect(page).to have_title("Data sharing agreement") + describe "render accessibility statement content page" do + before do + get "/accessibility-statement", headers:, params: {} + end + + it "returns a 200" do + expect(response).to have_http_status(:success) + end + + it "returns the page" do + expect(page).to have_title("Accessibility statement") + end end end end diff --git a/spec/requests/cookies_controller_spec.rb b/spec/requests/cookies_controller_spec.rb new file mode 100644 index 000000000..82cf06a10 --- /dev/null +++ b/spec/requests/cookies_controller_spec.rb @@ -0,0 +1,42 @@ +require "rails_helper" + +RSpec.describe CookiesController, type: :request do + let(:headers) { { "Accept" => "text/html" } } + let(:page) { Capybara::Node::Simple.new(response.body) } + + describe "when maintenance mode is disabled" do + describe "render cookies page" do + before do + get "/cookies", headers:, params: {} + end + + it "returns a 200" do + expect(response).to have_http_status(:success) + end + + it "returns the page" do + expect(page).to have_title("Cookies") + end + end + end + + describe "when maintenance mode is enabled" do + before do + allow(FeatureToggle).to receive(:maintenance_mode_enabled?).and_return(true) + end + + describe "render cookies page" do + before do + get "/cookies", headers:, params: {} + end + + it "returns a 200" do + expect(response).to have_http_status(:success) + end + + it "returns the page" do + expect(page).to have_title("Cookies") + end + end + end +end diff --git a/spec/requests/maintenance_controller_spec.rb b/spec/requests/maintenance_controller_spec.rb new file mode 100644 index 000000000..d900df3c5 --- /dev/null +++ b/spec/requests/maintenance_controller_spec.rb @@ -0,0 +1,85 @@ +require "rails_helper" + +RSpec.describe MaintenanceController, type: :request do + let(:page) { Capybara::Node::Simple.new(response.body) } + let(:user) { FactoryBot.create(:user) } + + before do + sign_in user + end + + describe "when maintenance mode is enabled" do + before do + allow(FeatureToggle).to receive(:maintenance_mode_enabled?).and_return(true) + end + + context "when a user visits a page other than the maintenance page" do + before do + get "/lettings-logs" + end + + it "redirects the user to the maintenance page" do + expect(response).to redirect_to(service_unavailable_path) + follow_redirect! + expect(page).to have_content("Sorry, the service is unavailable") + end + + it "the cookie banner is visible" do + follow_redirect! + expect(page).to have_content("We’d like to use analytics cookies so we can understand how you use the service and make improvements.") + end + end + + context "when a user visits the maintenance page" do + before do + get "/service-unavailable" + end + + it "keeps the user on the maintenance page" do + expect(response).not_to redirect_to(service_unavailable_path) + expect(page).to have_content("Sorry, the service is unavailable") + end + + it "the cookie banner is visible" do + expect(page).to have_content("We’d like to use analytics cookies so we can understand how you use the service and make improvements.") + end + end + end + + describe "when maintenance mode is disabled" do + before do + allow(FeatureToggle).to receive(:maintenance_mode_enabled?).and_return(false) + end + + context "when a user visits a page other than the maintenance page" do + before do + get "/lettings-logs" + end + + it "doesn't redirect the user to the maintenance page" do + expect(response).not_to redirect_to(service_unavailable_path) + expect(page).to have_content("Create a new lettings log") + end + + it "the cookie banner is visible" do + expect(page).to have_content("We’d like to use analytics cookies so we can understand how you use the service and make improvements.") + end + end + + context "when a user visits the maintenance page" do + before do + get "/service-unavailable" + end + + it "redirects the user to the start page" do + expect(response).to redirect_to(root_path) + end + + it "the cookie banner is visible" do + follow_redirect! + follow_redirect! + expect(page).to have_content("We’d like to use analytics cookies so we can understand how you use the service and make improvements.") + end + end + end +end