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