diff --git a/app/controllers/legacy_reports_controller.rb b/app/controllers/legacy_reports_controller.rb new file mode 100644 index 000000000..ed7b4d92d --- /dev/null +++ b/app/controllers/legacy_reports_controller.rb @@ -0,0 +1,47 @@ +class LegacyReportsController < ApplicationController + include ActionView::Helpers::TagHelper + + before_action :authenticate_user! + + def index; end + + def progress + redirect_to Report.new("editorial_progress").url, allow_other_host: true + end + + def organisation_content + redirect_to Report.new("organisation_content").url, allow_other_host: true + end + + def edition_churn + redirect_to Report.new("edition_churn").url, allow_other_host: true + end + + def all_edition_churn + redirect_to Report.new("all_edition_churn").url, allow_other_host: true + end + + def content_workflow + redirect_to Report.new("content_workflow").url, allow_other_host: true + end + + def all_content_workflow + redirect_to Report.new("all_content_workflow").url, allow_other_host: true + end + + def all_urls + redirect_to Report.new("all_urls").url, allow_other_host: true + end + +private + + def report_last_updated(report_name) + last_updated = ::Report.new(report_name).last_updated + if last_updated + tag.span "Generated #{last_updated.to_fs(:govuk_date)}", class: "text-muted" + else + tag.span "Report currently unavailable", class: "text-muted" + end + end + helper_method :report_last_updated +end diff --git a/app/views/legacy_reports/index.html.erb b/app/views/legacy_reports/index.html.erb new file mode 100644 index 000000000..d54f206f0 --- /dev/null +++ b/app/views/legacy_reports/index.html.erb @@ -0,0 +1,35 @@ + + +

+ <%= link_to 'All documents for departmental distribution', organisation_content_report_path(format: :csv) %>
+ <%= report_last_updated("organisation_content")%> +

+

+ <%= link_to 'Churn in non-archived editions', edition_churn_report_path(format: :csv) %>
+ <%= report_last_updated("edition_churn")%> +

+

+ <%= link_to 'Churn in all editions', all_edition_churn_report_path(format: :csv) %>
+ <%= report_last_updated("all_edition_churn")%> +

+

+ <%= link_to 'Progress on all non-archived editions', progress_report_path(format: :csv) %>
+ <%= report_last_updated("editorial_progress")%> +

+

+ <%= link_to 'Content summary and workflow history for all published editions', content_workflow_report_path(format: :csv) %>
+ <%= report_last_updated("content_workflow")%> +

+

+ <%= link_to 'Content summary and workflow history for all editions', all_content_workflow_report_path(format: :csv) %>
+ <%= report_last_updated("all_content_workflow")%> +

+

+ <%= link_to 'All URLs', all_urls_report_path(format: :csv) %>
+ <%= report_last_updated("all_urls")%> +

+ +<% content_for :page_title, "Reports" %> diff --git a/config/brakeman.ignore b/config/brakeman.ignore index c5f887e77..6f979892c 100644 --- a/config/brakeman.ignore +++ b/config/brakeman.ignore @@ -1,5 +1,51 @@ { "ignored_warnings": [ + { + "warning_type": "Redirect", + "warning_code": 18, + "fingerprint": "17210c84682f1087da739d7c48998ec063833a0ead94cab74161f376a02902c8", + "check_name": "Redirect", + "message": "Possible unprotected redirect", + "file": "app/controllers/legacy_reports_controller.rb", + "line": 25, + "link": "https://brakemanscanner.org/docs/warning_types/redirect/", + "code": "redirect_to(Report.new(\"content_workflow\").url, :allow_other_host => true)", + "render_path": null, + "location": { + "type": "method", + "class": "LegacyReportsController", + "method": "content_workflow" + }, + "user_input": "Report.new(\"content_workflow\").url", + "confidence": "Weak", + "cwe_id": [ + 601 + ], + "note": "" + }, + { + "warning_type": "Redirect", + "warning_code": 18, + "fingerprint": "21d15a1dedb4e98b76dd4206d5d9755c0c2fbb5ac22a3845342390fb14f32405", + "check_name": "Redirect", + "message": "Possible unprotected redirect", + "file": "app/controllers/legacy_reports_controller.rb", + "line": 9, + "link": "https://brakemanscanner.org/docs/warning_types/redirect/", + "code": "redirect_to(Report.new(\"editorial_progress\").url, :allow_other_host => true)", + "render_path": null, + "location": { + "type": "method", + "class": "LegacyReportsController", + "method": "progress" + }, + "user_input": "Report.new(\"editorial_progress\").url", + "confidence": "Weak", + "cwe_id": [ + 601 + ], + "note": "" + }, { "warning_type": "Redirect", "warning_code": 18, @@ -23,6 +69,86 @@ ], "note": "" }, + { + "warning_type": "Redirect", + "warning_code": 18, + "fingerprint": "547dd1ed93af0f3b1b537207879e41d3acc5d30344b527cfe61a7fa99e8bcfe2", + "check_name": "Redirect", + "message": "Possible unprotected redirect", + "file": "app/controllers/legacy_reports_controller.rb", + "line": 33, + "link": "https://brakemanscanner.org/docs/warning_types/redirect/", + "code": "redirect_to(Report.new(\"all_urls\").url, :allow_other_host => true)", + "render_path": null, + "location": { + "type": "method", + "class": "LegacyReportsController", + "method": "all_urls" + }, + "user_input": "Report.new(\"all_urls\").url", + "confidence": "Weak", + "cwe_id": [ + 601 + ], + "note": "" + }, + { + "warning_type": "Dangerous Send", + "warning_code": 23, + "fingerprint": "5da50023d480fee0db69426e97c68a6172b789a65999b5707297aafe8f52fd4a", + "check_name": "Send", + "message": "User controlled method execution", + "file": "app/views/root/index.html.erb", + "line": 61, + "link": "https://brakemanscanner.org/docs/warning_types/dangerous_send/", + "code": "@presenter.send((params[:list] or \"drafts\"))", + "render_path": [ + { + "type": "controller", + "class": "RootController", + "method": "index", + "line": 20, + "file": "app/controllers/root_controller.rb", + "rendered": { + "name": "root/index", + "file": "app/views/root/index.html.erb" + } + } + ], + "location": { + "type": "template", + "template": "root/index" + }, + "user_input": "params[:list]", + "confidence": "High", + "cwe_id": [ + 77 + ], + "note": "" + }, + { + "warning_type": "Redirect", + "warning_code": 18, + "fingerprint": "8b9b1897c23071c0620b3b89373e4b67c9c018f55d2bf9c9b10139194112876e", + "check_name": "Redirect", + "message": "Possible unprotected redirect", + "file": "app/controllers/legacy_reports_controller.rb", + "line": 29, + "link": "https://brakemanscanner.org/docs/warning_types/redirect/", + "code": "redirect_to(Report.new(\"all_content_workflow\").url, :allow_other_host => true)", + "render_path": null, + "location": { + "type": "method", + "class": "LegacyReportsController", + "method": "all_content_workflow" + }, + "user_input": "Report.new(\"all_content_workflow\").url", + "confidence": "Weak", + "cwe_id": [ + 601 + ], + "note": "" + }, { "warning_type": "Redirect", "warning_code": 18, @@ -49,17 +175,17 @@ { "warning_type": "Redirect", "warning_code": 18, - "fingerprint": "b52a4a72f485842b28181b0e846a46fc44f92bb4b998e7143bee1d56ab2cb592", + "fingerprint": "907123917bfc82d11454ff52d42cccf5a906b3340f2bd0e67e48b4a02e326254", "check_name": "Redirect", "message": "Possible unprotected redirect", - "file": "app/controllers/reports_controller.rb", + "file": "app/controllers/legacy_reports_controller.rb", "line": 13, "link": "https://brakemanscanner.org/docs/warning_types/redirect/", "code": "redirect_to(Report.new(\"organisation_content\").url, :allow_other_host => true)", "render_path": null, "location": { "type": "method", - "class": "ReportsController", + "class": "LegacyReportsController", "method": "organisation_content" }, "user_input": "Report.new(\"organisation_content\").url", @@ -170,36 +296,25 @@ "note": "" }, { - "warning_type": "Dangerous Send", - "warning_code": 23, - "fingerprint": "5da50023d480fee0db69426e97c68a6172b789a65999b5707297aafe8f52fd4a", - "check_name": "Send", - "message": "User controlled method execution", - "file": "app/views/root/index.html.erb", - "line": 61, - "link": "https://brakemanscanner.org/docs/warning_types/dangerous_send/", - "code": "@presenter.send((params[:list] or \"drafts\"))", - "render_path": [ - { - "type": "controller", - "class": "RootController", - "method": "index", - "line": 20, - "file": "app/controllers/root_controller.rb", - "rendered": { - "name": "root/index", - "file": "app/views/root/index.html.erb" - } - } - ], + "warning_type": "Redirect", + "warning_code": 18, + "fingerprint": "a9dfe519dba7fb86018e3cf55f2aa7184127d83afa1c6db8b15b788aab813ad0", + "check_name": "Redirect", + "message": "Possible unprotected redirect", + "file": "app/controllers/legacy_reports_controller.rb", + "line": 21, + "link": "https://brakemanscanner.org/docs/warning_types/redirect/", + "code": "redirect_to(Report.new(\"all_edition_churn\").url, :allow_other_host => true)", + "render_path": null, "location": { - "type": "template", - "template": "root/index" + "type": "method", + "class": "LegacyReportsController", + "method": "all_edition_churn" }, - "user_input": "params[:list]", - "confidence": "High", + "user_input": "Report.new(\"all_edition_churn\").url", + "confidence": "Weak", "cwe_id": [ - 77 + 601 ], "note": "" }, @@ -248,8 +363,54 @@ 601 ], "note": "" + }, + { + "warning_type": "Redirect", + "warning_code": 18, + "fingerprint": "b52a4a72f485842b28181b0e846a46fc44f92bb4b998e7143bee1d56ab2cb592", + "check_name": "Redirect", + "message": "Possible unprotected redirect", + "file": "app/controllers/reports_controller.rb", + "line": 13, + "link": "https://brakemanscanner.org/docs/warning_types/redirect/", + "code": "redirect_to(Report.new(\"organisation_content\").url, :allow_other_host => true)", + "render_path": null, + "location": { + "type": "method", + "class": "ReportsController", + "method": "organisation_content" + }, + "user_input": "Report.new(\"organisation_content\").url", + "confidence": "Weak", + "cwe_id": [ + 601 + ], + "note": "" + }, + { + "warning_type": "Redirect", + "warning_code": 18, + "fingerprint": "df4a142e2b4cccb80d2434a4195dd33a2873dfd4f1f7cac0f021c14fab463e3f", + "check_name": "Redirect", + "message": "Possible unprotected redirect", + "file": "app/controllers/legacy_reports_controller.rb", + "line": 17, + "link": "https://brakemanscanner.org/docs/warning_types/redirect/", + "code": "redirect_to(Report.new(\"edition_churn\").url, :allow_other_host => true)", + "render_path": null, + "location": { + "type": "method", + "class": "LegacyReportsController", + "method": "edition_churn" + }, + "user_input": "Report.new(\"edition_churn\").url", + "confidence": "Weak", + "cwe_id": [ + 601 + ], + "note": "" } ], - "updated": "2024-01-16 16:43:33 +0000", + "updated": "2024-01-24 11:41:24 +0000", "brakeman_version": "6.1.1" } diff --git a/config/features.rb b/config/features.rb index e10ab9803..e023058ef 100644 --- a/config/features.rb +++ b/config/features.rb @@ -8,4 +8,8 @@ default: true, description: "A feature only used by tests; not to be used for any actual features." end + + feature :design_system_reports_page, + default: false, + description: "A transition of the reports page to use the GOV.UK Design System" end diff --git a/config/routes.rb b/config/routes.rb index 2a9254844..af094be48 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -45,14 +45,24 @@ resource :downtime, only: %i[new create edit update destroy] end - get "reports" => "reports#index", as: :reports - get "reports/progress" => "reports#progress", as: :progress_report - get "reports/organisation-content" => "reports#organisation_content", :as => :organisation_content_report - get "reports/edition-churn" => "reports#edition_churn", as: "edition_churn_report" - get "reports/all-edition-churn" => "reports#all_edition_churn", as: "all_edition_churn_report" - get "reports/content-workflow" => "reports#content_workflow", as: "content_workflow_report" - get "reports/all-content-workflow" => "reports#all_content_workflow", as: "all_content_workflow_report" - get "reports/all-urls" => "reports#all_urls", as: "all_urls_report" + constraints FeatureConstraint.new("design_system_reports_page") do + get "reports" => "reports#index", as: :reports + get "reports/progress" => "reports#progress", as: :progress_report + get "reports/organisation-content" => "reports#organisation_content", :as => :organisation_content_report + get "reports/edition-churn" => "reports#edition_churn", as: "edition_churn_report" + get "reports/all-edition-churn" => "reports#all_edition_churn", as: "all_edition_churn_report" + get "reports/content-workflow" => "reports#content_workflow", as: "content_workflow_report" + get "reports/all-content-workflow" => "reports#all_content_workflow", as: "all_content_workflow_report" + get "reports/all-urls" => "reports#all_urls", as: "all_urls_report" + end + get "reports" => "legacy_reports#index" + get "reports/progress" => "legacy_reports#progress" + get "reports/organisation-content" => "legacy_reports#organisation_content" + get "reports/edition-churn" => "legacy_reports#edition_churn" + get "reports/all-edition-churn" => "legacy_reports#all_edition_churn" + get "reports/content-workflow" => "legacy_reports#content_workflow" + get "reports/all-content-workflow" => "legacy_reports#all_content_workflow" + get "reports/all-urls" => "legacy_reports#all_urls" get "user_search" => "user_search#index" diff --git a/test/functional/legacy_reports_controller_test.rb b/test/functional/legacy_reports_controller_test.rb new file mode 100644 index 000000000..e618a073a --- /dev/null +++ b/test/functional/legacy_reports_controller_test.rb @@ -0,0 +1,33 @@ +require "test_helper" + +class LegacyReportsControllerTest < ActionController::TestCase + setup do + login_as_stub_user + + last_modified = Time.zone.local(2023, 12, 12, 1, 1, 1) + + Aws.config[:s3] = { + stub_responses: { + head_object: { last_modified: }, + }, + } + + ENV["REPORTS_S3_BUCKET_NAME"] = "example" + end + + teardown do + ENV["REPORTS_S3_BUCKET_NAME"] = nil + end + + test "it redirects the user to S3" do + get :progress + + assert_equal 302, response.status + end + + test "shows the last updated time on the index page" do + get :index + + assert_match(/Generated 1:01am, 12 December 2023/, response.body) + end +end diff --git a/test/integration/routes_test.rb b/test/integration/routes_test.rb new file mode 100644 index 000000000..984213dfe --- /dev/null +++ b/test/integration/routes_test.rb @@ -0,0 +1,17 @@ +require "integration_test_helper" + +class RoutesTest < ActionDispatch::IntegrationTest + should "route to new reports controller when 'design_system_reports_page' toggle is enabled" do + test_strategy = Flipflop::FeatureSet.current.test! + test_strategy.switch!(:design_system_reports_page, true) + + assert_routing("/reports", controller: "reports", action: "index") + end + + should "route to legacy reports controller when 'design_system_reports_page' toggle is disabled" do + test_strategy = Flipflop::FeatureSet.current.test! + test_strategy.switch!(:design_system_reports_page, false) + + assert_routing("/reports", controller: "legacy_reports", action: "index") + end +end