From b75fbcfc4eef89ea446982914e078a1302f60334 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Mon, 19 Jul 2021 11:29:44 +0200 Subject: [PATCH] Render error pages using our own templates (#9455) --- app/controllers/errors_controller.rb | 25 +++++++++ app/helpers/meta_tags_helper.rb | 13 +++++ app/views/layouts/_common_head.html.erb | 53 ++++++++++++++++++ app/views/layouts/base.html.erb | 61 +-------------------- app/views/layouts/only_logo.html.erb | 8 +-- config/application.rb | 3 + config/routes.rb | 5 ++ public/404.html | 52 ------------------ public/500.html | 55 ------------------- spec/features/errors/errors_handler_spec.rb | 28 ++++++++++ spec/routing/errors_routing_spec.rb | 35 ++++++++++++ 11 files changed, 165 insertions(+), 173 deletions(-) create mode 100644 app/controllers/errors_controller.rb create mode 100644 app/views/layouts/_common_head.html.erb delete mode 100644 public/404.html delete mode 100644 public/500.html create mode 100644 spec/features/errors/errors_handler_spec.rb create mode 100644 spec/routing/errors_routing_spec.rb diff --git a/app/controllers/errors_controller.rb b/app/controllers/errors_controller.rb new file mode 100644 index 00000000000..a394e08db8b --- /dev/null +++ b/app/controllers/errors_controller.rb @@ -0,0 +1,25 @@ +class ErrorsController < ::ActionController::Base + include ErrorsHelper + include OpenProjectErrorHelper + include Accounts::CurrentUser + + def not_found + render_404 + end + + def unacceptable + render file: "#{Rails.root}/public/422.html", + status: :unacceptable, + layout: false + end + + def internal_error + render_500 + end + + private + + def use_layout + 'only_logo' + end +end diff --git a/app/helpers/meta_tags_helper.rb b/app/helpers/meta_tags_helper.rb index f09c962c7f4..c1e52d4be48 100644 --- a/app/helpers/meta_tags_helper.rb +++ b/app/helpers/meta_tags_helper.rb @@ -38,6 +38,19 @@ module MetaTagsHelper reverse: true end + def initializer_meta_tag + tag :meta, + name: :openproject_initializer, + data: { + locale: I18n.locale, + defaultLocale: I18n.default_locale, + firstWeekOfYear: locale_first_week_of_year, + firstDayOfWeek: locale_first_day_of_week, + environment: Rails.env, + edition: OpenProject::Configuration.edition + } + end + ## # Writer of html_title as string def html_title(*args) diff --git a/app/views/layouts/_common_head.html.erb b/app/views/layouts/_common_head.html.erb new file mode 100644 index 00000000000..66c9f97834f --- /dev/null +++ b/app/views/layouts/_common_head.html.erb @@ -0,0 +1,53 @@ + + +<%= output_title_and_meta_tags %> +<%= sentry_frontend_tags %> + +<% relative_url_root = OpenProject::Configuration['rails_relative_url_root'] || '' %> + + +<% if @project %> + +<% end %> +<% unless User.current.anonymous? %> + +<% end %> + +<% if Setting.demo_projects_available %><% end %> +<% if Setting.boards_demo_data_available %><% end %> +<%= csrf_meta_tags %> +<%= initializer_meta_tag %> + + +<%= call_hook :view_layouts_base_html_meta %> + +<%= render 'common/favicons' %> + +<%# Include CLI assets (development) or prod build assets %> +<%= include_frontend_assets %> + +<%# Render CSS highlighting %> +<%= stylesheet_link_tag "/highlighting/styles/#{highlight_css_version_tag}", + media: :all, + skip_pipeline: true %> + +<%# Custom styles %> +<%= render partial: "custom_styles/inline_css_logo" %> +<% if apply_custom_styles? %> + <% cache(CustomStyle.current) do %> + <%= render partial: "custom_styles/inline_css" %> + <% if CustomStyle.current.favicon.present? %> + + <% end %> + <% if CustomStyle.current.touch_icon.present? %> + + <% end %> + <% end %> +<% end %> +<%= crowdin_in_context_translation %> \ No newline at end of file diff --git a/app/views/layouts/base.html.erb b/app/views/layouts/base.html.erb index 8f007d7f136..90fc1d39751 100644 --- a/app/views/layouts/base.html.erb +++ b/app/views/layouts/base.html.erb @@ -32,69 +32,12 @@ See docs/COPYRIGHT.rdoc for more details. xml:lang="<%= I18n.locale.to_s %>" class="<%= 'in_modal' unless show_decoration %>"> - - - <%= output_title_and_meta_tags %> - <%= sentry_frontend_tags %> - - <% relative_url_root = OpenProject::Configuration['rails_relative_url_root'] || '' %> - - - <% if @project %> - - <% end %> - <% unless User.current.anonymous? %> - - <% end %> - - - - <% if Setting.demo_projects_available %><% end %> - <% if Setting.boards_demo_data_available %><% end %> - <%= csrf_meta_tags %> - - - <%= call_hook :view_layouts_base_html_meta %> - - <%= render 'common/favicons' %> - - <%# Include CLI assets (development) or prod build assets %> - <%= include_frontend_assets %> - - <%# Render CSS highlighting %> - <%= stylesheet_link_tag "/highlighting/styles/#{highlight_css_version_tag}", - media: :all, - skip_pipeline: true %> - + <%= render partial: 'layouts/common_head' %> <%= call_hook :view_layouts_base_html_head %> <%= content_for(:header_tags) if content_for?(:header_tags) %> - <%= render partial: "custom_styles/inline_css_logo" %> - <% if apply_custom_styles? %> - <% cache(CustomStyle.current) do %> - <%= render partial: "custom_styles/inline_css" %> - <% if CustomStyle.current.favicon.present? %> - - <% end %> - <% if CustomStyle.current.touch_icon.present? %> - - <% end %> - <% end %> - <% end %> - <%= crowdin_in_context_translation %> + <%= render partial: 'warning_bar/warning_bar' %> diff --git a/app/views/layouts/only_logo.html.erb b/app/views/layouts/only_logo.html.erb index b5790f8af5b..e72b2a23d4a 100644 --- a/app/views/layouts/only_logo.html.erb +++ b/app/views/layouts/only_logo.html.erb @@ -32,13 +32,7 @@ See docs/COPYRIGHT.rdoc for more details. xml:lang="<%= I18n.locale.to_s %>" class="<%= 'in_modal' unless show_decoration %>"> - - - <%= output_title_and_meta_tags %> - <%= csrf_meta_tags %> - <%= render 'common/favicons' %> - <%# Include CLI assets (development) or prod build assets %> - <%= include_frontend_assets %> + <%= render partial: 'layouts/common_head' %>
diff --git a/config/application.rb b/config/application.rb index 1fb51ae1454..c163350a08d 100644 --- a/config/application.rb +++ b/config/application.rb @@ -105,6 +105,9 @@ module OpenProject config.paths.add Rails.root.join('lib').to_s, eager_load: true config.paths.add Rails.root.join('lib/constraints').to_s, eager_load: true + # Use our own error rendering for prettier error pages + config.exceptions_app = routes + # Only load the plugins named here, in the order given (default is alphabetical). # :all can be used as a placeholder for all plugins not explicitly named. # config.plugins = [ :exception_notification, :ssl_requirement, :all ] diff --git a/config/routes.rb b/config/routes.rb index e52e1cf1c9a..a85a235c31b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -32,6 +32,11 @@ OpenProject::Application.routes.draw do root to: 'homescreen#index', as: 'home' rails_relative_url_root = OpenProject::Configuration['rails_relative_url_root'] || '' + # Route for error pages + get '/404', to: "errors#not_found" + get '/422', to: "errors#unacceptable" + get '/500', to: "errors#internal_error" + # Route for health_checks get '/health_check' => 'ok_computer/ok_computer#show', check: 'web' # Override the default `all` checks route to return the full check diff --git a/public/404.html b/public/404.html deleted file mode 100644 index f75e29bfcc4..00000000000 --- a/public/404.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - -OpenProject 404 error - - -

Page not found

-

The page you were trying to access doesn't exist or has been removed.

-

Back

- - diff --git a/public/500.html b/public/500.html deleted file mode 100644 index 2e8abee6a99..00000000000 --- a/public/500.html +++ /dev/null @@ -1,55 +0,0 @@ - - - - -OpenProject 500 error - - -

Internal error

-

An error occurred on the page you were trying to access.
- If you continue to experience problems please contact your OpenProject administrator for assistance.

- -

If you are the OpenProject administrator, check your log files for details about the error.

-

Back

- - diff --git a/spec/features/errors/errors_handler_spec.rb b/spec/features/errors/errors_handler_spec.rb new file mode 100644 index 00000000000..0f3a14247af --- /dev/null +++ b/spec/features/errors/errors_handler_spec.rb @@ -0,0 +1,28 @@ +require 'spec_helper' + +describe 'Errors handling', type: :feature do + it 'renders the internal error page in case of exceptions' do + # We unfortunately cannot test raising exceptions as the test environment + # marks all requests as local and thus shows exception details instead (like in dev mode) + visit '/500' + expect(page).to have_current_path '/500' + expect(page).to have_text "An error occurred on the page you were trying to access." + expect(page).to have_no_text "Oh no, this is an internal error!" + end + + it 'renders the not found page' do + # We unfortunately cannot test raising exceptions as the test environment + # marks all requests as local and thus shows exception details instead (like in dev mode) + visit '/404' + expect(page).to have_current_path '/404' + expect(page).to have_text "[Error 404] The page you were trying to access doesn't exist or has been removed." + end + + it 'renders the unacceptable response' do + # This file exists in public and is recommended to be rendered, but I'm not aware + # of any path that would trigger this + visit '/422' + expect(page).to have_current_path '/422' + expect(page).to have_text 'The change you wanted was rejected.' + end +end \ No newline at end of file diff --git a/spec/routing/errors_routing_spec.rb b/spec/routing/errors_routing_spec.rb new file mode 100644 index 00000000000..98a9ceb2927 --- /dev/null +++ b/spec/routing/errors_routing_spec.rb @@ -0,0 +1,35 @@ +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 2012-2021 the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See docs/COPYRIGHT.rdoc for more details. +#++ + +require 'spec_helper' + +describe 'errors routing', type: :routing do + it { is_expected.to route(:get, '/404').to(controller: 'errors', action: 'not_found') } + it { is_expected.to route(:get, '/422').to(controller: 'errors', action: 'unacceptable') } + it { is_expected.to route(:get, '/500').to(controller: 'errors', action: 'internal_error') } +end