From 1b2c83c01f37e8d3ff85a57de71e49a90633a715 Mon Sep 17 00:00:00 2001
From: HelenWDTK <120410992+HelenWDTK@users.noreply.github.com>
Date: Sun, 2 Apr 2023 17:27:11 +0100
Subject: [PATCH 001/265] Update _show.html.erb
Add snippet of note body to the admin page.
---
app/views/admin/notes/_show.html.erb | 2 ++
1 file changed, 2 insertions(+)
diff --git a/app/views/admin/notes/_show.html.erb b/app/views/admin/notes/_show.html.erb
index 5eccb94753..ea5ad9cbef 100644
--- a/app/views/admin/notes/_show.html.erb
+++ b/app/views/admin/notes/_show.html.erb
@@ -4,6 +4,7 @@
ID
Notable ID
+
Note Body
Notable type
Notable tag
Actions
@@ -13,6 +14,7 @@
<%= h note.id %>
<%= h note.notable_id %>
+
<%= truncate(h(note.body), length: 50) %>
<%= h note.notable_type %>
<%= h note.notable_tag %>
<%= link_to "Edit", edit_admin_note_path(note) %>
From 7417b471a6a5c7aaa44239e2c51a8a552d4e4f07 Mon Sep 17 00:00:00 2001
From: Gareth Rees
Date: Tue, 4 Apr 2023 12:39:57 +0100
Subject: [PATCH 002/265] Configurable user content limits
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Allow `User.content_limits` to be configurable per-install via theme
customisation.
For example, we could tune the `user_messages` daily limit like:
User.content_limits = {
info_requests: AlaveteliConfiguration.max_requests_per_user_per_day,
comments: AlaveteliConfiguration.max_requests_per_user_per_day,
user_messages: 2
}
Can probably tidy up the use of `content_limits` _and_ `content_limit`,
but that would currently involve reworking the specs – this is good
enough for now.
---
app/models/user.rb | 6 ++++--
app/views/comment/rate_limited.html.erb | 2 +-
app/views/users/messages/rate_limited.html.erb | 2 +-
3 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/app/models/user.rb b/app/models/user.rb
index 035fc1cc51..50736e473b 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -47,12 +47,14 @@ class User < ApplicationRecord
include User::OneTimePassword
include User::Survey
- CONTENT_LIMIT = {
+ DEFAULT_CONTENT_LIMITS = {
info_requests: AlaveteliConfiguration.max_requests_per_user_per_day,
comments: AlaveteliConfiguration.max_requests_per_user_per_day,
user_messages: AlaveteliConfiguration.max_requests_per_user_per_day
}.freeze
+ cattr_accessor :content_limits, default: DEFAULT_CONTENT_LIMITS
+
rolify before_add: :setup_pro_account,
after_add: :assign_role_features,
after_remove: :assign_role_features
@@ -700,6 +702,6 @@ def update_pro_account
end
def content_limit(content)
- CONTENT_LIMIT[content]
+ content_limits[content]
end
end
diff --git a/app/views/comment/rate_limited.html.erb b/app/views/comment/rate_limited.html.erb
index d9cbf08470..46d4708045 100644
--- a/app/views/comment/rate_limited.html.erb
+++ b/app/views/comment/rate_limited.html.erb
@@ -5,7 +5,7 @@
<%= _('You have hit the rate limit on annotations. Users are ordinarily ' \
'limited to {{comment_limit}} annotations per day.',
- comment_limit: User::CONTENT_LIMIT[:comments]) %>
+ comment_limit: User.content_limits[:comments]) %>
<%= _('You have hit the rate limit on user messages. Users are ordinarily ' \
'limited to {{message_limit}} messages per day.',
- message_limit: User::CONTENT_LIMIT[:user_messages]) %>
+ message_limit: User.content_limits[:user_messages]) %>
From 616baf4d758282e2ab327923d9ce0f497168c24b Mon Sep 17 00:00:00 2001
From: Gareth Rees
Date: Fri, 14 Apr 2023 13:50:25 +0100
Subject: [PATCH 003/265] Extract knowledge to GoogleDocsViewer
`GoogleDocsViewer` should know what content types it supports. This
enables some cleanup of `FoiAttachment`.
---
app/models/foi_attachment.rb | 17 +---------------
.../adapters/google_docs_viewer.rb | 20 +++++++++++++++++++
.../adapters/google_docs_viewer_spec.rb | 13 ++++++++++++
spec/models/foi_attachment_spec.rb | 14 +++++++++++++
4 files changed, 48 insertions(+), 16 deletions(-)
diff --git a/app/models/foi_attachment.rb b/app/models/foi_attachment.rb
index f67986eed4..5f841462c2 100644
--- a/app/models/foi_attachment.rb
+++ b/app/models/foi_attachment.rb
@@ -241,23 +241,8 @@ def update_display_size!
end
end
- # Whether this type can be shown in the Google Docs Viewer.
- # The full list of supported types can be found at
- # https://docs.google.com/support/bin/answer.py?hl=en&answer=1189935
def has_google_docs_viewer?
- [
- "application/pdf", # .pdf
- "image/tiff", # .tiff
-
- "application/vnd.ms-word", # .doc
- "application/vnd.openxmlformats-officedocument.wordprocessingml.document", # .docx
-
- "application/vnd.ms-powerpoint", # .ppt
- "application/vnd.openxmlformats-officedocument.presentationml.presentation", # .pptx
-
- "application/vnd.ms-excel", # .xls
- "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" # .xlsx
- ].include?(content_type)
+ AttachmentToHTML::Adapters::GoogleDocsViewer.viewable?(content_type)
end
# Whether this type has a "View as HTML"
diff --git a/lib/attachment_to_html/adapters/google_docs_viewer.rb b/lib/attachment_to_html/adapters/google_docs_viewer.rb
index 47c128caa2..f1fa709fc7 100644
--- a/lib/attachment_to_html/adapters/google_docs_viewer.rb
+++ b/lib/attachment_to_html/adapters/google_docs_viewer.rb
@@ -7,6 +7,26 @@ module Adapters
# constructed iframe (which is tested) that Google will make this
# Just Work.
class GoogleDocsViewer < Adapter
+ # rubocop:disable Style/LineLength
+ VIEWABLE_CONTENT_TYPPES = [
+ 'application/pdf', # .pdf
+ 'image/tiff', # .tiff
+ 'application/vnd.ms-word', # .doc
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', # .docx
+ 'application/vnd.ms-powerpoint', # .ppt
+ 'application/vnd.openxmlformats-officedocument.presentationml.presentation', # .pptx
+ 'application/vnd.ms-excel', # .xls
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' # .xlsx
+ ].freeze
+ # rubocop:enable Style/LineLength
+
+ # Whether this type can be shown in the Google Docs Viewer.
+ # The full list of supported types can be found at
+ # https://docs.google.com/support/bin/answer.py?hl=en&answer=1189935
+ def self.viewable?(content_type)
+ VIEWABLE_CONTENT_TYPPES.include?(content_type)
+ end
+
attr_reader :attachment_url
# Public: Initialize a GoogleDocsViewer converter
diff --git a/spec/lib/attachment_to_html/adapters/google_docs_viewer_spec.rb b/spec/lib/attachment_to_html/adapters/google_docs_viewer_spec.rb
index dab8a01d3d..8f279a3fb8 100644
--- a/spec/lib/attachment_to_html/adapters/google_docs_viewer_spec.rb
+++ b/spec/lib/attachment_to_html/adapters/google_docs_viewer_spec.rb
@@ -1,6 +1,19 @@
require 'spec_helper'
RSpec.describe AttachmentToHTML::Adapters::GoogleDocsViewer do
+ describe '.viewable?' do
+ subject { described_class.viewable?(content_type) }
+
+ context 'when the content_type is supported' do
+ let(:content_type) { 'application/pdf' }
+ it { is_expected.to eq(true) }
+ end
+
+ context 'when the content_type is unsupported' do
+ let(:content_type) { 'an/invalid/content-type' }
+ it { is_expected.to eq(false) }
+ end
+ end
let(:attachment) { FactoryBot.build(:pdf_attachment) }
let(:adapter) do
diff --git a/spec/models/foi_attachment_spec.rb b/spec/models/foi_attachment_spec.rb
index b8feefbe6a..b0b0bb8c8d 100644
--- a/spec/models/foi_attachment_spec.rb
+++ b/spec/models/foi_attachment_spec.rb
@@ -179,6 +179,20 @@
end
+ describe '#has_google_docs_viewer?' do
+ subject { foi_attachment.has_google_docs_viewer? }
+
+ context 'with a supported attachment' do
+ let(:foi_attachment) { FactoryBot.build(:pdf_attachment) }
+ it { is_expected.to eq(true) }
+ end
+
+ context 'with an unsupported attachment' do
+ let(:foi_attachment) { FactoryBot.build(:html_attachment) }
+ it { is_expected.to eq(false) }
+ end
+ end
+
describe '#has_body_as_html?' do
it 'should be true for a pdf attachment' do
From 29fe75fb83bbddf98811667495034187d3a64a3d Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 17 Apr 2023 05:00:32 +0000
Subject: [PATCH 004/265] Build(deps): Bump flipper-active_record from 0.24.1
to 0.28.0
Bumps [flipper-active_record](https://github.com/jnunemaker/flipper) from 0.24.1 to 0.28.0.
- [Release notes](https://github.com/jnunemaker/flipper/releases)
- [Changelog](https://github.com/jnunemaker/flipper/blob/main/Changelog.md)
- [Commits](https://github.com/jnunemaker/flipper/compare/v0.24.1...v0.28.0)
---
updated-dependencies:
- dependency-name: flipper-active_record
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
---
Gemfile.lock | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/Gemfile.lock b/Gemfile.lock
index 0fd3ddda59..c00037df55 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -203,10 +203,11 @@ GEM
faraday (>= 0.7.4, < 1.0)
fast_gettext (2.3.0)
fivemat (1.3.7)
- flipper (0.24.1)
- flipper-active_record (0.24.1)
+ flipper (0.28.0)
+ concurrent-ruby (< 2)
+ flipper-active_record (0.28.0)
activerecord (>= 4.2, < 8)
- flipper (~> 0.24.1)
+ flipper (~> 0.28.0)
forwardable (1.3.3)
gender_detector (2.0.0)
gettext (3.4.3)
From 890ce4e0259077d57b3ba7c26dc55f7235ed34ab Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 17 Apr 2023 05:01:32 +0000
Subject: [PATCH 005/265] Build(deps): Bump flipper from 0.24.1 to 0.28.0
Bumps [flipper](https://github.com/jnunemaker/flipper) from 0.24.1 to 0.28.0.
- [Release notes](https://github.com/jnunemaker/flipper/releases)
- [Changelog](https://github.com/jnunemaker/flipper/blob/main/Changelog.md)
- [Commits](https://github.com/jnunemaker/flipper/compare/v0.24.1...v0.28.0)
---
updated-dependencies:
- dependency-name: flipper
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
---
Gemfile.lock | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/Gemfile.lock b/Gemfile.lock
index 0fd3ddda59..c00037df55 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -203,10 +203,11 @@ GEM
faraday (>= 0.7.4, < 1.0)
fast_gettext (2.3.0)
fivemat (1.3.7)
- flipper (0.24.1)
- flipper-active_record (0.24.1)
+ flipper (0.28.0)
+ concurrent-ruby (< 2)
+ flipper-active_record (0.28.0)
activerecord (>= 4.2, < 8)
- flipper (~> 0.24.1)
+ flipper (~> 0.28.0)
forwardable (1.3.3)
gender_detector (2.0.0)
gettext (3.4.3)
From 931ff537a9566228fc3eb5b8b2cef92eb89973bc Mon Sep 17 00:00:00 2001
From: Alexander Griffen
Date: Sun, 23 Apr 2023 21:59:05 +0100
Subject: [PATCH 006/265] style: Layout/SpaceInsideHashLiteralBraces RuboCop
Automatic correction to cop in app/* files
---
app/controllers/api_controller.rb | 6 +++---
app/controllers/request_controller.rb | 2 +-
app/helpers/link_to_helper.rb | 6 +++---
app/mailers/request_mailer.rb | 8 ++++----
app/models/info_request/pro_query.rb | 2 +-
app/models/info_request_event.rb | 2 +-
app/models/public_body.rb | 8 ++++----
7 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/app/controllers/api_controller.rb b/app/controllers/api_controller.rb
index d5d9521d98..4670237c66 100644
--- a/app/controllers/api_controller.rb
+++ b/app/controllers/api_controller.rb
@@ -208,14 +208,14 @@ def body_request_events
@events = InfoRequestEvent.where(event_type_clause).
joins(:info_request).
where("public_body_id = ?", @public_body.id).
- includes([{info_request: :user}, :outgoing_message]).
+ includes([{ info_request: :user }, :outgoing_message]).
order(created_at: :desc)
if since_date_str
begin
since_date = Date.strptime(since_date_str, "%Y-%m-%d")
rescue ArgumentError
- render json: {"errors" => [
+ render json: { "errors" => [
"Parameter since_date must be in format yyyy-mm-dd (not '#{since_date_str}')"
] },
status: 500
@@ -230,7 +230,7 @@ def body_request_events
begin
event = InfoRequestEvent.find(since_event_id)
rescue ActiveRecord::RecordNotFound
- render json: {"errors" => [
+ render json: { "errors" => [
"Event ID #{since_event_id} not found"
] },
status: 500
diff --git a/app/controllers/request_controller.rb b/app/controllers/request_controller.rb
index e4692be147..4e22f0e151 100644
--- a/app/controllers/request_controller.rb
+++ b/app/controllers/request_controller.rb
@@ -604,7 +604,7 @@ def make_request_summary_file(info_request)
end
def render_new_compose
- params[:info_request] = { } unless params[:info_request]
+ params[:info_request] = {} unless params[:info_request]
# Reconstruct the params
# first the public body (by URL name or id)
diff --git a/app/helpers/link_to_helper.rb b/app/helpers/link_to_helper.rb
index d8f151f769..4add916300 100755
--- a/app/helpers/link_to_helper.rb
+++ b/app/helpers/link_to_helper.rb
@@ -11,7 +11,7 @@ module LinkToHelper
# Requests
def request_url(info_request, options = {})
- show_request_url({url_title: info_request.url_title}.merge(options))
+ show_request_url({ url_title: info_request.url_title }.merge(options))
end
def request_path(info_request, options = {})
@@ -236,10 +236,10 @@ def search_url(query, options = nil)
query -= ["", nil]
query = query.join("/")
end
- routing_info = {controller: 'general',
+ routing_info = { controller: 'general',
action: 'search',
combined: query,
- view: nil}
+ view: nil }
routing_info = options.merge(routing_info) unless options.nil?
if routing_info.is_a?(Hash)
diff --git a/app/mailers/request_mailer.rb b/app/mailers/request_mailer.rb
index a256c71e52..f97a03731a 100644
--- a/app/mailers/request_mailer.rb
+++ b/app/mailers/request_mailer.rb
@@ -24,8 +24,8 @@ def fake_response(info_request, from_user, message_body, attachment_name, attach
if !attachment_name.nil? && !attachment_content.nil?
content_type = AlaveteliFileTypes.filename_to_mimetype(attachment_name) || 'application/octet-stream'
- attachments[attachment_name] = {content: attachment_content,
- content_type: content_type}
+ attachments[attachment_name] = { content: attachment_content,
+ content_type: content_type }
end
mail(from: from_user.name_and_email,
@@ -38,8 +38,8 @@ def external_response(info_request, message_body, sent_at, attachment_hashes)
@message_body = message_body
attachment_hashes.each do |attachment_hash|
- attachments[attachment_hash[:filename]] = {content: attachment_hash[:body],
- content_type: attachment_hash[:content_type]}
+ attachments[attachment_hash[:filename]] = { content: attachment_hash[:body],
+ content_type: attachment_hash[:content_type] }
end
mail(from: blackhole_email,
diff --git a/app/models/info_request/pro_query.rb b/app/models/info_request/pro_query.rb
index 4cab5280b8..46cde2defe 100644
--- a/app/models/info_request/pro_query.rb
+++ b/app/models/info_request/pro_query.rb
@@ -7,7 +7,7 @@ def initialize(relation = InfoRequest)
def call
@relation
.includes(user: :roles)
- .where(roles: {name: 'pro'})
+ .where(roles: { name: 'pro' })
.references(:roles)
end
end
diff --git a/app/models/info_request_event.rb b/app/models/info_request_event.rb
index 3892b1a0a9..31a56015d2 100644
--- a/app/models/info_request_event.rb
+++ b/app/models/info_request_event.rb
@@ -261,7 +261,7 @@ def params_diff
end
end
new_params.delete_if { |key, _value| ignore.keys.include?(key) }
- {new: new_params, old: old_params, other: other_params}
+ { new: new_params, old: old_params, other: other_params }
end
def is_incoming_message?
diff --git a/app/models/public_body.rb b/app/models/public_body.rb
index fd6dc3adcf..6940d1978d 100644
--- a/app/models/public_body.rb
+++ b/app/models/public_body.rb
@@ -497,7 +497,7 @@ def self.import_csv_from_file(csv_filename, tag, tag_behaviour, dry_run, editor,
field_names = { 'name' => 1, 'request_email' => 2 }
line = 0
- import_options = {field_names: field_names,
+ import_options = { field_names: field_names,
available_locales: available_locales,
tag: tag,
tag_behaviour: tag_behaviour,
@@ -736,7 +736,7 @@ def self.get_request_totals(n, highest, minimum_requests)
'public_bodies' => public_bodies,
'y_values' => y_values,
'y_max' => y_values.max,
- 'totals' => y_values}
+ 'totals' => y_values }
end
# Return data for the 'n' public bodies with the highest (or
@@ -785,7 +785,7 @@ def self.get_request_percentages(column, n, highest, minimum_requests)
'cis_below' => cis_below,
'cis_above' => cis_above,
'y_max' => 100,
- 'totals' => original_totals}
+ 'totals' => original_totals }
end
def self.popular_bodies(locale)
@@ -894,7 +894,7 @@ def update_counter_cache
described_state: 'not_held' },
info_requests_successful_count: { awaiting_description: false,
described_state: success_states },
- info_requests_visible_classified_count: { awaiting_description: false},
+ info_requests_visible_classified_count: { awaiting_description: false },
info_requests_visible_count: {}
}
From 2be3a02355fa9bc94d2d37f3fc9ef6c77b61b27c Mon Sep 17 00:00:00 2001
From: Alexander Griffen
Date: Sun, 23 Apr 2023 21:59:59 +0100
Subject: [PATCH 007/265] style: Layout/SpaceInsideHashLiteralBraces RuboCop
Automatic correction to cop in lib/* files
---
lib/acts_as_xapian/acts_as_xapian.rb | 4 +--
lib/graphs.rb | 2 +-
lib/mail_handler.rb | 4 +--
lib/memory_profiler.rb | 2 +-
lib/tasks/config_files.rake | 4 +--
lib/tasks/graphs.rake | 38 +++++++++++++-------------
lib/tasks/stats.rake | 10 +++----
lib/tasks/themes.rake | 40 ++++++++++++++--------------
8 files changed, 52 insertions(+), 52 deletions(-)
diff --git a/lib/acts_as_xapian/acts_as_xapian.rb b/lib/acts_as_xapian/acts_as_xapian.rb
index fd572e2444..c4635e9eb1 100644
--- a/lib/acts_as_xapian/acts_as_xapian.rb
+++ b/lib/acts_as_xapian/acts_as_xapian.rb
@@ -424,10 +424,10 @@ def results
# Pull out all the results
iter = matches._begin
until iter.equals(matches._end)
- docs.push({data: iter.document.data,
+ docs.push({ data: iter.document.data,
percent: iter.percent,
weight: iter.weight,
- collapse_count: iter.collapse_count})
+ collapse_count: iter.collapse_count })
iter.next
end
}
diff --git a/lib/graphs.rb b/lib/graphs.rb
index 3ffea5846f..1529cbd4de 100644
--- a/lib/graphs.rb
+++ b/lib/graphs.rb
@@ -46,7 +46,7 @@ def select_as_columns(sql)
# for outputting the graph
# returns the resulting Gnuplot::DataSet
def create_dataset(data, options)
- default = {using: "1:2"} #in most cases, we just want the first 2 columns
+ default = { using: "1:2" } #in most cases, we just want the first 2 columns
options = default.merge(options)
Gnuplot::DataSet.new(data) do |ds|
options.keys.each do |option|
diff --git a/lib/mail_handler.rb b/lib/mail_handler.rb
index 7694f2f12a..189665da46 100644
--- a/lib/mail_handler.rb
+++ b/lib/mail_handler.rb
@@ -100,7 +100,7 @@ def get_attachment_text_one_file(content_type, body, charset = 'utf-8')
"-dump-charset", "utf-8",
"-force-html", "-dump",
tempfile.path,
- default_params.merge(env: {"LANG" => "C"}))
+ default_params.merge(env: { "LANG" => "C" }))
elsif content_type == 'application/vnd.ms-excel'
# Bit crazy using /usr/bin/strings - but xls2csv, xlhtml and
# py_xls2txt only extract text from cells, not from floating
@@ -120,7 +120,7 @@ def get_attachment_text_one_file(content_type, body, charset = 'utf-8')
"-c",
tempfile.path,
"word/document.xml",
- {binary_output: false})
+ { binary_output: false })
unless xml.nil?
doc = REXML::Document.new(xml)
text += doc.each_element( './/text()' ) {}.join(" ")
diff --git a/lib/memory_profiler.rb b/lib/memory_profiler.rb
index bc01745edc..ba0dcea7c9 100644
--- a/lib/memory_profiler.rb
+++ b/lib/memory_profiler.rb
@@ -13,7 +13,7 @@
# strings `ls -1t *profiler_strings* | head --lines=1` |sort > a; strings `ls -1t *profiler_strings* | head --lines=2 | tail --lines=1` |sort > b; diff b a |less
class MemoryProfiler
- DEFAULTS = {delay: 10, string_debug: false}
+ DEFAULTS = { delay: 10, string_debug: false }
def self.start(opt={})
opt = DEFAULTS.dup.merge(opt)
diff --git a/lib/tasks/config_files.rake b/lib/tasks/config_files.rake
index 5dfa0cbb99..49f4d52bd1 100644
--- a/lib/tasks/config_files.rake
+++ b/lib/tasks/config_files.rake
@@ -175,9 +175,9 @@ namespace :config_files do
check_for_env_vars(%w[REJECTED_THRESHOLD AGE_IN_MONTHS], example)
dryrun = ENV['DRYRUN'] != '0'
STDERR.puts "Only a dry run; info_requests will not be updated" if dryrun
- options = {rejection_threshold: ENV['REJECTED_THRESHOLD'],
+ options = { rejection_threshold: ENV['REJECTED_THRESHOLD'],
age_in_months: ENV['AGE_IN_MONTHS'],
- dryrun: dryrun}
+ dryrun: dryrun }
updated_count = InfoRequest.reject_incoming_at_mta(options) do |ids|
puts "Info Request\tRejected incoming count\tLast updated"
diff --git a/lib/tasks/graphs.rake b/lib/tasks/graphs.rake
index bd0511ca7a..675556b7f7 100644
--- a/lib/tasks/graphs.rake
+++ b/lib/tasks/graphs.rake
@@ -88,9 +88,9 @@ namespace :graphs do
]
# plot all users
- options = {with: "impulses",
+ options = { with: "impulses",
linecolor: COLOURS[state_list[0][:colour]],
- linewidth: 15, title: state_list[0][:title]}
+ linewidth: 15, title: state_list[0][:title] }
all_users = select_as_columns(aggregate_signups)
# nothing to do, bail
@@ -113,7 +113,7 @@ namespace :graphs do
title: state_info[:title],
linecolor: COLOURS[state_info[:colour]],
with: state_info[:with],
- linewidth: state_info[:linewidth]})
+ linewidth: state_info[:linewidth] })
)
end
end
@@ -130,7 +130,7 @@ namespace :graphs do
with: "lines",
linewidth: 1,
linecolor: COLOURS[:lightgreen],
- using: "1:3"})
+ using: "1:3" })
plot_data_from_columns(all_users, options, plot.data)
end
end
@@ -189,21 +189,21 @@ namespace :graphs do
# get the data, plot the graph
- state_list = [ {state: 'waiting_response', colour: :darkblue},
- {state: 'waiting_clarification', colour: :lightblue},
- {state: 'not_held', colour: :yellow},
- {state: 'rejected', colour: :red},
- {state: 'successful', colour: :lightgreen},
- {state: 'partially_successful', colour: :darkgreen},
- {state: 'requires_admin', colour: :cyan},
- {state: 'gone_postal', colour: :darkyellow},
- {state: 'internal_review', colour: :mauve},
- {state: 'error_message', colour: :redbrown},
- {state: 'user_withdrawn', colour: :pink} ]
-
- options = {with: "impulses",
+ state_list = [ { state: 'waiting_response', colour: :darkblue },
+ { state: 'waiting_clarification', colour: :lightblue },
+ { state: 'not_held', colour: :yellow },
+ { state: 'rejected', colour: :red },
+ { state: 'successful', colour: :lightgreen },
+ { state: 'partially_successful', colour: :darkgreen },
+ { state: 'requires_admin', colour: :cyan },
+ { state: 'gone_postal', colour: :darkyellow },
+ { state: 'internal_review', colour: :mauve },
+ { state: 'error_message', colour: :redbrown },
+ { state: 'user_withdrawn', colour: :pink } ]
+
+ options = { with: "impulses",
linecolor: COLOURS[state_list[0][:colour]],
- linewidth: 4, title: state_list[0][:state]}
+ linewidth: 4, title: state_list[0][:state] }
# here be database-specific dragons...
# this uses a window function which is not supported by MySQL, but
@@ -240,7 +240,7 @@ namespace :graphs do
assemble_sql(state_exclusion_sql(previous_states)),
options.merge({
title: state_info[:state],
- linecolor: COLOURS[state_info[:colour]]})
+ linecolor: COLOURS[state_info[:colour]] })
)
end
previous_states << state_list[index][:state]
diff --git a/lib/tasks/stats.rake b/lib/tasks/stats.rake
index ae2fef4f77..6b1f42bcec 100644
--- a/lib/tasks/stats.rake
+++ b/lib/tasks/stats.rake
@@ -271,17 +271,17 @@ namespace :stats do
requester_only_requests = InfoRequest.where(prominence: 'requester_only')
hidden_incoming = InfoRequest.joins(:incoming_messages).
- where(incoming_messages: {prominence: 'hidden'}).uniq
+ where(incoming_messages: { prominence: 'hidden' }).uniq
requester_only_incoming = InfoRequest.joins(:incoming_messages).
- where(incoming_messages: {prominence: 'requester_only'}).uniq
+ where(incoming_messages: { prominence: 'requester_only' }).uniq
hidden_outgoing = InfoRequest.joins(:outgoing_messages).
- where(outgoing_messages: {prominence: 'hidden'}).uniq
+ where(outgoing_messages: { prominence: 'hidden' }).uniq
requester_only_outgoing = InfoRequest.joins(:outgoing_messages).
- where(outgoing_messages: {prominence: 'requester_only'}).uniq
+ where(outgoing_messages: { prominence: 'requester_only' }).uniq
hidden_comments = InfoRequest.joins(:comments).
- where(comments: {visible: false}).uniq
+ where(comments: { visible: false }).uniq
[['Hidden requests', hidden_requests],
['Requester-only requests', requester_only_requests],
diff --git a/lib/tasks/themes.rake b/lib/tasks/themes.rake
index 572b1702da..d6d03aed47 100644
--- a/lib/tasks/themes.rake
+++ b/lib/tasks/themes.rake
@@ -212,36 +212,36 @@ EOF
theme_url_to_theme_name(theme_url)
end
- help_templates_info = [{name: 'about',
+ help_templates_info = [{ name: 'about',
sections: %w[whybother_them
reporting
- reporting_unavailable]},
- {name: 'alaveteli',
- sections: []},
- {name: 'api',
- sections: []},
- {name: 'contact',
- sections: []},
- {name: 'credits',
- sections: ['helpus']},
- {name: 'officers',
- sections: ['copyright']},
- {name: 'privacy',
+ reporting_unavailable] },
+ { name: 'alaveteli',
+ sections: [] },
+ { name: 'api',
+ sections: [] },
+ { name: 'contact',
+ sections: [] },
+ { name: 'credits',
+ sections: ['helpus'] },
+ { name: 'officers',
+ sections: ['copyright'] },
+ { name: 'privacy',
sections: %w[email_address
full_address
postal_answer
public_request
- real_name]},
- {name: 'requesting',
+ real_name] },
+ { name: 'requesting',
sections: %w[focused
data_protection
missing_body
- quickly_response]},
- {name: 'unhappy',
+ quickly_response] },
+ { name: 'unhappy',
sections: %w[internal_review
- other_means]},
- {name: '_why_they_should_reply_by_email',
- sections: []}]
+ other_means] },
+ { name: '_why_they_should_reply_by_email',
+ sections: [] }]
theme_names.each do |theme_name|
AlaveteliLocalization.available_locales.each do |locale|
From 056c6902a496a37d023f0a174e0b4d8812cbd3d7 Mon Sep 17 00:00:00 2001
From: Alexander Griffen
Date: Sun, 23 Apr 2023 22:00:59 +0100
Subject: [PATCH 008/265] style: Layout/SpaceInsideHashLiteralBraces RuboCop
Automatic correction to cop in controller specs
---
.../controllers/admin_incoming_message_controller_spec.rb | 6 +++---
.../controllers/admin_outgoing_message_controller_spec.rb | 6 +++---
spec/controllers/admin_public_body_controller_spec.rb | 8 ++++----
.../admin_public_body_headings_controller_spec.rb | 2 +-
spec/controllers/admin_raw_email_controller_spec.rb | 2 +-
.../alaveteli_pro/info_request_batches_controller_spec.rb | 4 ++--
spec/controllers/general_controller_spec.rb | 2 +-
spec/controllers/info_request_batch_controller_spec.rb | 2 +-
.../public_body_change_requests_controller_spec.rb | 4 ++--
spec/controllers/request_controller_spec.rb | 2 +-
10 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/spec/controllers/admin_incoming_message_controller_spec.rb b/spec/controllers/admin_incoming_message_controller_spec.rb
index 4d21488a21..b2557d6663 100644
--- a/spec/controllers/admin_incoming_message_controller_spec.rb
+++ b/spec/controllers/admin_incoming_message_controller_spec.rb
@@ -258,9 +258,9 @@ def make_request(params=@default_params)
context 'if the incoming message is not valid' do
it 'should render the edit template' do
- make_request({id: @incoming.id,
- incoming_message: {prominence: 'fantastic',
- prominence_reason: 'dull'}})
+ make_request({ id: @incoming.id,
+ incoming_message: { prominence: 'fantastic',
+ prominence_reason: 'dull' } })
expect(response).to render_template("edit")
end
diff --git a/spec/controllers/admin_outgoing_message_controller_spec.rb b/spec/controllers/admin_outgoing_message_controller_spec.rb
index 6ccf8cfc88..801fca6270 100644
--- a/spec/controllers/admin_outgoing_message_controller_spec.rb
+++ b/spec/controllers/admin_outgoing_message_controller_spec.rb
@@ -280,10 +280,10 @@ def make_request(params = default_params)
context 'if the incoming message is not valid' do
it 'should render the edit template' do
- make_request({id: outgoing.id,
- outgoing_message: {prominence: 'fantastic',
+ make_request({ id: outgoing.id,
+ outgoing_message: { prominence: 'fantastic',
prominence_reason: 'dull',
- body: 'Some information please'}})
+ body: 'Some information please' } })
expect(response).to render_template("edit")
end
diff --git a/spec/controllers/admin_public_body_controller_spec.rb b/spec/controllers/admin_public_body_controller_spec.rb
index 485f27f6fc..ccd6033253 100644
--- a/spec/controllers/admin_public_body_controller_spec.rb
+++ b/spec/controllers/admin_public_body_controller_spec.rb
@@ -36,7 +36,7 @@
it "sets a using_admin flag" do
sign_in admin_user
- get :show, params: { id: public_body.id}
+ get :show, params: { id: public_body.id }
expect(session[:using_admin]).to eq(1)
end
@@ -736,7 +736,7 @@
it 'should raise an error on an invalid temp file name' do
params = { temporary_csv_file: 'bad_name',
original_csv_file: 'original_contents.txt',
- commit: 'Dry run'}
+ commit: 'Dry run' }
expected_error = "Invalid filename in upload_csv: bad_name"
expect {
post :import_csv, params: params
@@ -747,7 +747,7 @@
temp_name = "csv_upload-20461231-394"
params = { temporary_csv_file: temp_name,
original_csv_file: 'original_contents.txt',
- commit: 'Dry run'}
+ commit: 'Dry run' }
expected_error = "Missing file in upload_csv: csv_upload-20461231-394"
expect {
post :import_csv, params: params
@@ -829,7 +829,7 @@ def setup_emergency_credentials(username, password)
}
expect(session[:using_admin]).to eq(1)
n = PublicBody.count
- post :destroy, params: {id: public_bodies(:forlorn_public_body).id }
+ post :destroy, params: { id: public_bodies(:forlorn_public_body).id }
expect(session[:using_admin]).to eq(1)
expect(PublicBody.count).to eq(n - 1)
end
diff --git a/spec/controllers/admin_public_body_headings_controller_spec.rb b/spec/controllers/admin_public_body_headings_controller_spec.rb
index 613d705ed3..4411e124b2 100644
--- a/spec/controllers/admin_public_body_headings_controller_spec.rb
+++ b/spec/controllers/admin_public_body_headings_controller_spec.rb
@@ -553,7 +553,7 @@ def make_request(params=@default_params)
context 'when handling invalid input' do
before do
- @params = { headings: [@second.id, @first.id, @second.id + 1]}
+ @params = { headings: [@second.id, @first.id, @second.id + 1] }
end
it 'should return an "unprocessable entity" status and an error message' do
diff --git a/spec/controllers/admin_raw_email_controller_spec.rb b/spec/controllers/admin_raw_email_controller_spec.rb
index 095c21aa41..ef923f2f42 100644
--- a/spec/controllers/admin_raw_email_controller_spec.rb
+++ b/spec/controllers/admin_raw_email_controller_spec.rb
@@ -52,7 +52,7 @@
event_type: 'response',
info_request: InfoRequest.holding_pen_request,
incoming_message: incoming_message,
- params: {rejected_reason: 'Too dull'}
+ params: { rejected_reason: 'Too dull' }
)
end
diff --git a/spec/controllers/alaveteli_pro/info_request_batches_controller_spec.rb b/spec/controllers/alaveteli_pro/info_request_batches_controller_spec.rb
index 18d6811202..f6a5f95f09 100644
--- a/spec/controllers/alaveteli_pro/info_request_batches_controller_spec.rb
+++ b/spec/controllers/alaveteli_pro/info_request_batches_controller_spec.rb
@@ -127,7 +127,7 @@
public_bodies: bodies,
user: user)
end
- let(:params) { {draft_id: draft.id} }
+ let(:params) { { draft_id: draft.id } }
before do
sign_in user
@@ -197,7 +197,7 @@
describe "#create" do
- let(:params) { {draft_id: draft.id} }
+ let(:params) { { draft_id: draft.id } }
let(:action) { post :create, params: params }
shared_examples "when batch is created" do
diff --git a/spec/controllers/general_controller_spec.rb b/spec/controllers/general_controller_spec.rb
index 76ba24baff..a624d25926 100644
--- a/spec/controllers/general_controller_spec.rb
+++ b/spec/controllers/general_controller_spec.rb
@@ -85,7 +85,7 @@
info_request: info_request,
described_at: Time.zone.now,
search_text_main: 'example text')
- xapian_result = double('xapian result', results: [{model: info_request_event}])
+ xapian_result = double('xapian result', results: [{ model: info_request_event }])
allow(controller).to receive(:perform_search).and_return(xapian_result)
end
diff --git a/spec/controllers/info_request_batch_controller_spec.rb b/spec/controllers/info_request_batch_controller_spec.rb
index 97c73563da..408b27346e 100644
--- a/spec/controllers/info_request_batch_controller_spec.rb
+++ b/spec/controllers/info_request_batch_controller_spec.rb
@@ -10,7 +10,7 @@
body: 'Matched body',
public_bodies: bodies)
end
- let(:params) { {id: info_request_batch.id} }
+ let(:params) { { id: info_request_batch.id } }
let(:action) { get :show, params: params }
let(:pro_user) { FactoryBot.create(:pro_user) }
diff --git a/spec/controllers/public_body_change_requests_controller_spec.rb b/spec/controllers/public_body_change_requests_controller_spec.rb
index 4feba9297b..8d3daeaa01 100644
--- a/spec/controllers/public_body_change_requests_controller_spec.rb
+++ b/spec/controllers/public_body_change_requests_controller_spec.rb
@@ -27,7 +27,7 @@
before do
@email = "test@example.com"
name = "Test User"
- @change_request_params = {user_email: @email,
+ @change_request_params = { user_email: @email,
user_name: name,
public_body_name: 'New Body',
public_body_email: 'new_body@example.com',
@@ -115,7 +115,7 @@
@email = "test@example.com"
name = "Test User"
@public_body = FactoryBot.create(:public_body)
- @change_request_params = {user_email: @email,
+ @change_request_params = { user_email: @email,
user_name: name,
public_body_id: @public_body.id,
public_body_email: 'new_body@example.com',
diff --git a/spec/controllers/request_controller_spec.rb b/spec/controllers/request_controller_spec.rb
index d1fef1160e..2fa0495b94 100644
--- a/spec/controllers/request_controller_spec.rb
+++ b/spec/controllers/request_controller_spec.rb
@@ -918,7 +918,7 @@ def send_request
title: 'Why Geraldine?',
tag_string: ''
},
- outgoing_message: { body: 'This is a silly letter.'},
+ outgoing_message: { body: 'This is a silly letter.' },
submitted_new_request: 1,
preview: 1
}
From 6259563b9ed6ed215fe0d3b61b4d1223b60fa696 Mon Sep 17 00:00:00 2001
From: Alexander Griffen
Date: Sun, 23 Apr 2023 22:01:54 +0100
Subject: [PATCH 009/265] style: Layout/SpaceInsideHashLiteralBraces RuboCop
Automatic correction to cop in model specs
---
spec/models/holiday_import_spec.rb | 4 +--
.../info_request/state/transitions_spec.rb | 4 +--
spec/models/info_request_event_spec.rb | 28 +++++++++----------
spec/models/info_request_spec.rb | 16 +++++------
.../category_collection_spec.rb | 4 +--
spec/models/statistics_spec.rb | 4 +--
spec/models/xapian_spec.rb | 2 +-
7 files changed, 31 insertions(+), 31 deletions(-)
diff --git a/spec/models/holiday_import_spec.rb b/spec/models/holiday_import_spec.rb
index f6a6c2f0e9..6416cd3ef2 100644
--- a/spec/models/holiday_import_spec.rb
+++ b/spec/models/holiday_import_spec.rb
@@ -21,10 +21,10 @@
it 'validates that all holidays create from attributes are valid' do
holiday_import = HolidayImport.new(source: 'suggestions',
- holidays_attributes: {"0" => {:description => '',
+ holidays_attributes: { "0" => { :description => '',
"day(1i)"=>"",
"day(2i)"=>"",
- "day(3i)"=>""}})
+ "day(3i)"=>"" } })
expect(holiday_import.valid?).to be false
expect(holiday_import.errors[:base]).to eq(["These holidays could not be imported"])
end
diff --git a/spec/models/info_request/state/transitions_spec.rb b/spec/models/info_request/state/transitions_spec.rb
index 0dd3702245..96c8eb387f 100644
--- a/spec/models/info_request/state/transitions_spec.rb
+++ b/spec/models/info_request/state/transitions_spec.rb
@@ -417,8 +417,8 @@
end
it "returns a hash of labelled states" do
- actual = subject.labelled_hash(['successful'], {is_owning_user: true})
- expected = {"successful" => "I've received all the information"}
+ actual = subject.labelled_hash(['successful'], { is_owning_user: true })
+ expected = { "successful" => "I've received all the information" }
expect(expected).to eq(actual)
end
end
diff --git a/spec/models/info_request_event_spec.rb b/spec/models/info_request_event_spec.rb
index 94549ccacf..7bcb92bc14 100644
--- a/spec/models/info_request_event_spec.rb
+++ b/spec/models/info_request_event_spec.rb
@@ -54,9 +54,9 @@
it "should store the incoming_message, outgoing_messsage and comment ids" do
comment = FactoryBot.create(:comment)
- example_params = {incoming_message_id: 1,
+ example_params = { incoming_message_id: 1,
outgoing_message_id: 2,
- comment_id: comment.id}
+ comment_id: comment.id }
ire.params = example_params
expect(ire.incoming_message_id).to eq(1)
expect(ire.outgoing_message_id).to eq(2)
@@ -166,7 +166,7 @@
let(:ire) { InfoRequestEvent.new }
it "should return old, new and other params" do
- ire.params = {old_foo: 'this is stuff', foo: 'stuff', bar: 84}
+ ire.params = { old_foo: 'this is stuff', foo: 'stuff', bar: 84 }
expected_hash = {
new: { foo: 'stuff' },
old: { foo: 'this is stuff' },
@@ -176,14 +176,14 @@
end
it 'should drop matching old and new values' do
- ire.params = {old_foo: 'stuff', foo: 'stuff', bar: 84}
+ ire.params = { old_foo: 'stuff', foo: 'stuff', bar: 84 }
expected_hash = { new: {}, old: {}, other: { bar: 84 } }
expect(ire.params_diff).to eq(expected_hash)
end
it 'returns a url_name if passed a User' do
user = FactoryBot.create(:user)
- ire.params = {old_foo: "", foo: user}
+ ire.params = { old_foo: "", foo: user }
expected_hash = {
new: { foo: { gid: user.to_global_id.to_s } },
old: { foo: '' },
@@ -427,7 +427,7 @@
end
it "should change type to hidden when only editing prominence to hidden" do
- params = unchanged_params.merge({old_prominence: "normal", prominence: "hidden"})
+ params = unchanged_params.merge({ old_prominence: "normal", prominence: "hidden" })
ire = InfoRequestEvent.create!(info_request: FactoryBot.create(:info_request),
event_type: "edit",
@@ -437,7 +437,7 @@
end
it "should change type to hidden when only editing prominence to requester_only" do
- params = unchanged_params.merge({old_prominence: "normal", prominence: "requester_only"})
+ params = unchanged_params.merge({ old_prominence: "normal", prominence: "requester_only" })
ire = InfoRequestEvent.create!(info_request: FactoryBot.create(:info_request),
event_type: "edit",
@@ -447,7 +447,7 @@
end
it "should change type to hidden when only editing prominence to backpage" do
- params = unchanged_params.merge({old_prominence: "normal", prominence: "backpage"})
+ params = unchanged_params.merge({ old_prominence: "normal", prominence: "backpage" })
ire = InfoRequestEvent.create!(info_request: FactoryBot.create(:info_request),
event_type: "edit",
@@ -655,7 +655,7 @@
end
context "when only editing prominence to hidden" do
- let(:params) { unchanged_params.merge({old_prominence: "normal", prominence: "hidden"}) }
+ let(:params) { unchanged_params.merge({ old_prominence: "normal", prominence: "hidden" }) }
it do
ire = InfoRequestEvent.new(event_type: "edit", params: params)
@@ -665,7 +665,7 @@
end
context "when only editing prominence to requester_only" do
- let(:params) { unchanged_params.merge({old_prominence: "normal", prominence: "requester_only"}) }
+ let(:params) { unchanged_params.merge({ old_prominence: "normal", prominence: "requester_only" }) }
it "should be true if only editing prominence to requester_only" do
ire = InfoRequestEvent.new(event_type: "edit", params: params)
@@ -675,7 +675,7 @@
end
context "when only editing prominence to backpage" do
- let(:params) { unchanged_params.merge({old_prominence: "normal", prominence: "backpage"}) }
+ let(:params) { unchanged_params.merge({ old_prominence: "normal", prominence: "backpage" }) }
it "should be true if only editing prominence to backpage" do
ire = InfoRequestEvent.new(event_type: "edit", params: params)
@@ -685,7 +685,7 @@
end
context "when the old prominence was hidden" do
- let(:params) { unchanged_params.merge({old_prominence: "hidden", prominence: "requester_only"}) }
+ let(:params) { unchanged_params.merge({ old_prominence: "hidden", prominence: "requester_only" }) }
it do
ire = InfoRequestEvent.new(event_type: "edit", params: params)
@@ -695,7 +695,7 @@
end
context "when the old prominence was requester_only" do
- let(:params) { unchanged_params.merge({old_prominence: "requester_only", prominence: "hidden"}) }
+ let(:params) { unchanged_params.merge({ old_prominence: "requester_only", prominence: "hidden" }) }
it do
ire = InfoRequestEvent.new(event_type: "edit", params: params)
@@ -705,7 +705,7 @@
end
context "when the old prominence was backpage" do
- let(:params) { unchanged_params.merge({old_prominence: "backpage", prominence: "hidden"}) }
+ let(:params) { unchanged_params.merge({ old_prominence: "backpage", prominence: "hidden" }) }
it do
ire = InfoRequestEvent.new(event_type: "edit", params: params)
diff --git a/spec/models/info_request_spec.rb b/spec/models/info_request_spec.rb
index 01553af038..6fea565e8f 100644
--- a/spec/models/info_request_spec.rb
+++ b/spec/models/info_request_spec.rb
@@ -358,9 +358,9 @@
@request.update(updated_at: 6.months.ago,
rejected_incoming_count: 3,
allow_new_responses_from: 'nobody')
- @options = {rejection_threshold: 2,
+ @options = { rejection_threshold: 2,
age_in_months: 5,
- dryrun: true}
+ dryrun: true }
end
it 'returns an count of requests updated ' do
@@ -3050,12 +3050,12 @@ def create_old_unclassified_holding_pen
it "returns a hash with the user's name for an external request" do
@info_request = InfoRequest.new(external_url: 'http://www.example.com',
external_user_name: 'External User')
- expect(@info_request.user_json_for_api).to eq({name: 'External User'})
+ expect(@info_request.user_json_for_api).to eq({ name: 'External User' })
end
it 'returns "Anonymous user" for an anonymous external user' do
@info_request = InfoRequest.new(external_url: 'http://www.example.com')
- expect(@info_request.user_json_for_api).to eq({name: 'Anonymous user'})
+ expect(@info_request.user_json_for_api).to eq({ name: 'Anonymous user' })
end
end
@@ -3523,7 +3523,7 @@ def apply_filters(filters)
it "filters requests by date" do
# The semantics of the search are that it finds any InfoRequest
# that has any InfoRequestEvent created in the specified range
- filters = {latest_status: 'all', request_date_before: '13/10/2007'}
+ filters = { latest_status: 'all', request_date_before: '13/10/2007' }
conditions1 = <<-EOF
id IN (SELECT info_request_id
FROM info_request_events
@@ -3532,7 +3532,7 @@ def apply_filters(filters)
expect(apply_filters(filters)).
to match_array(InfoRequest.where(conditions1))
- filters = {latest_status: 'all', request_date_after: '13/10/2007'}
+ filters = { latest_status: 'all', request_date_after: '13/10/2007' }
conditions2 = <<-EOF
id IN (SELECT info_request_id
FROM info_request_events
@@ -3541,9 +3541,9 @@ def apply_filters(filters)
expect(apply_filters(filters)).
to match_array(InfoRequest.where(conditions2))
- filters = {latest_status: 'all',
+ filters = { latest_status: 'all',
request_date_after: '13/10/2007',
- request_date_before: '01/11/2007'}
+ request_date_before: '01/11/2007' }
conditions3 = <<-EOF
id IN (SELECT info_request_id
FROM info_request_events
diff --git a/spec/models/public_body_category/category_collection_spec.rb b/spec/models/public_body_category/category_collection_spec.rb
index da7e067837..c16801a334 100644
--- a/spec/models/public_body_category/category_collection_spec.rb
+++ b/spec/models/public_body_category/category_collection_spec.rb
@@ -38,8 +38,8 @@
describe 'when asked for tags by headings' do
it 'should return a hash of tags keyed by heading' do
- expect(@categories.by_heading).to eq({'Local and regional' => ['local_council'],
- 'Miscellaneous' => ['other']})
+ expect(@categories.by_heading).to eq({ 'Local and regional' => ['local_council'],
+ 'Miscellaneous' => ['other'] })
end
end
diff --git a/spec/models/statistics_spec.rb b/spec/models/statistics_spec.rb
index 830d40ecd4..a935419ec2 100644
--- a/spec/models/statistics_spec.rb
+++ b/spec/models/statistics_spec.rb
@@ -32,12 +32,12 @@
to_draw = Statistics.simplify_stats_for_graphs(raw_count_data,
column='blah_blah',
percentages=false,
- {highest: true} )
+ { highest: true } )
expect(to_draw['id']).to eq("blah_blah-highest")
to_draw = Statistics.simplify_stats_for_graphs(raw_count_data,
column='blah_blah',
percentages=false,
- {highest: false} )
+ { highest: false } )
expect(to_draw['id']).to eq("blah_blah-lowest")
end
diff --git a/spec/models/xapian_spec.rb b/spec/models/xapian_spec.rb
index 60773b98b6..612083f720 100644
--- a/spec/models/xapian_spec.rb
+++ b/spec/models/xapian_spec.rb
@@ -136,7 +136,7 @@
it "should find requests from the user" do
options = { sort_by_prefix: 'created_at',
sort_by_ascending: true,
- limit: 100}
+ limit: 100 }
xapian_object =
ActsAsXapian::Search.
From afb9a65fe2d3e82698e06ac5eb099a7b3e044bb8 Mon Sep 17 00:00:00 2001
From: Alexander Griffen
Date: Sun, 23 Apr 2023 22:03:57 +0100
Subject: [PATCH 010/265] style: Layout/SpaceInsideHashLiteralBraces RuboCop
Automatic correction to cop in migration files
---
.../20140716131107_create_category_translation_tables.rb | 4 ++--
.../20170717141302_drop_public_body_translated_columns.rb | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/db/migrate/20140716131107_create_category_translation_tables.rb b/db/migrate/20140716131107_create_category_translation_tables.rb
index c550dffb61..802b48681c 100644
--- a/db/migrate/20140716131107_create_category_translation_tables.rb
+++ b/db/migrate/20140716131107_create_category_translation_tables.rb
@@ -8,8 +8,8 @@ class PublicBodyHeading < ApplicationRecord
def up
default_locale = AlaveteliLocalization.default_locale
- fields = {title: :text,
- description: :text}
+ fields = { title: :text,
+ description: :text }
PublicBodyCategory.create_translation_table!(fields)
# copy current values across to the default locale
diff --git a/db/migrate/20170717141302_drop_public_body_translated_columns.rb b/db/migrate/20170717141302_drop_public_body_translated_columns.rb
index 46ae9fb9f7..3f000b9d9b 100644
--- a/db/migrate/20170717141302_drop_public_body_translated_columns.rb
+++ b/db/migrate/20170717141302_drop_public_body_translated_columns.rb
@@ -60,7 +60,7 @@ def down
# Create a hash containing the translated column names and their values
attr_names = record.translated_attribute_names
attr_names.inject(fields_to_update={}) do |f, name|
- f.update({name.to_sym => translated[name.to_s]})
+ f.update({ name.to_sym => translated[name.to_s] })
end
# Now, update the actual model's record with the hash (using the
From 3df5870c7b0374313cc823a244cfde5bd80df14b Mon Sep 17 00:00:00 2001
From: Alexander Griffen
Date: Sun, 23 Apr 2023 22:04:51 +0100
Subject: [PATCH 011/265] style: Layout/SpaceInsideHashLiteralBraces RuboCop
Automatic correction to cop in lib specs
---
spec/lib/alaveteli_text_masker_spec.rb | 2 +-
spec/lib/database_collation_spec.rb | 2 +-
spec/lib/graphs_spec.rb | 12 ++++----
spec/lib/mail_handler/mail_handler_spec.rb | 34 +++++++++++-----------
4 files changed, 25 insertions(+), 25 deletions(-)
diff --git a/spec/lib/alaveteli_text_masker_spec.rb b/spec/lib/alaveteli_text_masker_spec.rb
index bbb1e5fb6a..52c178e4e4 100644
--- a/spec/lib/alaveteli_text_masker_spec.rb
+++ b/spec/lib/alaveteli_text_masker_spec.rb
@@ -218,7 +218,7 @@ def pdf_replacement_test(use_ghostscript_compression)
it 'applies extra masks to text' do
data = "here is a mouse"
expected = "here is a cat"
- mask = { to_replace: 'mouse', replacement: 'cat'}
+ mask = { to_replace: 'mouse', replacement: 'cat' }
result = class_instance.apply_masks(data, 'text/html', masks: [mask])
expect(result).to eq(expected)
end
diff --git a/spec/lib/database_collation_spec.rb b/spec/lib/database_collation_spec.rb
index d107651218..06f5a36bce 100644
--- a/spec/lib/database_collation_spec.rb
+++ b/spec/lib/database_collation_spec.rb
@@ -73,7 +73,7 @@ def mock_connection(connection_double_opts = {})
connection = double('ActiveRecord::FakeConnection', connection_double_opts)
installed_collations = [
- { "collname" => "default", "collencoding" => "-1"},
+ { "collname" => "default", "collencoding" => "-1" },
{ "collname" => "C", "collencoding" => "-1" },
{ "collname" => "POSIX", "collencoding" => "-1" },
{ "collname" => "C.UTF-8", "collencoding" => "6" },
diff --git a/spec/lib/graphs_spec.rb b/spec/lib/graphs_spec.rb
index 95d7eb74fa..51738ab3ac 100644
--- a/spec/lib/graphs_spec.rb
+++ b/spec/lib/graphs_spec.rb
@@ -54,32 +54,32 @@
end
it "uses the supplied column references via the 'using' option" do
- result = dummy_class.create_dataset(test_data, {using: "1:3"})
+ result = dummy_class.create_dataset(test_data, { using: "1:3" })
expect(result.using).to eq "1:3"
end
it "sets the key title" do
- result = dummy_class.create_dataset(test_data, {title: "Dataset Title"})
+ result = dummy_class.create_dataset(test_data, { title: "Dataset Title" })
expect(result.title).to eq "Dataset Title"
end
it "sets the plot type for the dataset via the 'with' option" do
- result = dummy_class.create_dataset(test_data, {with: "lines"})
+ result = dummy_class.create_dataset(test_data, { with: "lines" })
expect(result.with).to eq "lines"
end
it "sets the line colour via the 'linecolor' option" do
- result = dummy_class.create_dataset(test_data, {linecolor: 2})
+ result = dummy_class.create_dataset(test_data, { linecolor: 2 })
expect(result.linecolor).to eq 2
end
it "sets the line width via the 'linewidth' option" do
- result = dummy_class.create_dataset(test_data, {linewidth: 10})
+ result = dummy_class.create_dataset(test_data, { linewidth: 10 })
expect(result.linewidth).to eq 10
end
it "sets the axes width via the 'axes' option" do
- result = dummy_class.create_dataset(test_data, {axes: "x1y1"})
+ result = dummy_class.create_dataset(test_data, { axes: "x1y1" })
expect(result.axes).to eq "x1y1"
end
end
diff --git a/spec/lib/mail_handler/mail_handler_spec.rb b/spec/lib/mail_handler/mail_handler_spec.rb
index 6bba6524e1..b3c43e371c 100644
--- a/spec/lib/mail_handler/mail_handler_spec.rb
+++ b/spec/lib/mail_handler/mail_handler_spec.rb
@@ -477,70 +477,70 @@ def expect_header_string(fixture_file, header, header_string)
expected_attributes = [ { content_type: "text/plain",
url_part_number: 1,
within_rfc822_subject: nil,
- filename: nil},
+ filename: nil },
{ content_type: "text/plain",
url_part_number: 2,
within_rfc822_subject: "Re: xxx",
- filename: nil},
+ filename: nil },
{ content_type: "text/html",
url_part_number: 4,
within_rfc822_subject: "example",
- filename: nil},
+ filename: nil },
{ content_type: "image/gif", url_part_number: 5,
within_rfc822_subject: "example",
- filename: "image001.gif"},
+ filename: "image001.gif" },
{ content_type: "application/vnd.ms-excel",
url_part_number: 6,
within_rfc822_subject: "example",
- filename: "particpant list.xls"},
+ filename: "particpant list.xls" },
{ content_type: "text/plain",
url_part_number: 7,
within_rfc822_subject: "RE: example",
- filename: nil},
+ filename: nil },
{ content_type: "text/html",
url_part_number: 9,
within_rfc822_subject: "As promised - Masterclass info (example)",
- filename: nil},
+ filename: nil },
{ content_type: "image/gif",
url_part_number: 10,
within_rfc822_subject: "As promised - Masterclass info (example)",
- filename: "image001.gif"},
+ filename: "image001.gif" },
{ content_type: "application/vnd.ms-word",
url_part_number: 11,
within_rfc822_subject: "As promised - Masterclass info (example)",
- filename: "Participant List.doc"},
+ filename: "Participant List.doc" },
{ content_type: "application/vnd.ms-word",
url_part_number: 12,
within_rfc822_subject: "As promised - Masterclass info (example)",
- filename: "Information & Booking Form.doc"},
+ filename: "Information & Booking Form.doc" },
{ content_type: "text/plain",
url_part_number: 13,
within_rfc822_subject: "Re: As promised - info (example)",
- filename: nil},
+ filename: nil },
{ content_type: "text/html",
url_part_number: 15,
within_rfc822_subject: "Thank you from example",
- filename: nil},
+ filename: nil },
{ content_type: "image/gif",
url_part_number: 16,
within_rfc822_subject: "Thank you from example",
- filename: "image001.gif"},
+ filename: "image001.gif" },
{ content_type: "text/plain",
url_part_number: 17,
within_rfc822_subject: "example - Meeting - Tuesday 2nd March",
- filename: nil},
+ filename: nil },
{ content_type: "text/plain",
url_part_number: 18,
within_rfc822_subject: "example - Help needed",
- filename: nil},
+ filename: nil },
{ content_type: "application/pdf",
url_part_number: 19,
within_rfc822_subject: "example - Help needed",
- filename: "Information Pack.pdf"},
+ filename: "Information Pack.pdf" },
{ content_type: "text/plain",
url_part_number: 20,
within_rfc822_subject: "Re: As promised - info (example)",
- filename: nil} ]
+ filename: nil } ]
attributes.each_with_index do |attr, index|
attr.delete(:charset)
From 21496f1a6567149c0880c082c07d411dd9965787 Mon Sep 17 00:00:00 2001
From: Alexander Griffen
Date: Sun, 23 Apr 2023 22:05:48 +0100
Subject: [PATCH 012/265] style: Layout/SpaceInsideHashLiteralBraces RuboCop
Automatic correction to cop in views specs
---
spec/views/admin_request/_params.html.erb_spec.rb | 2 +-
spec/views/request/_describe_state.html.erb_spec.rb | 2 +-
spec/views/user/sign.html.erb_spec.rb | 6 +++---
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/spec/views/admin_request/_params.html.erb_spec.rb b/spec/views/admin_request/_params.html.erb_spec.rb
index d0c88da634..e94c635ef8 100644
--- a/spec/views/admin_request/_params.html.erb_spec.rb
+++ b/spec/views/admin_request/_params.html.erb_spec.rb
@@ -2,7 +2,7 @@
RSpec.describe 'when showing diffs in info_request params' do
def do_render(params)
- render partial: 'admin_request/params', locals: {params: params}
+ render partial: 'admin_request/params', locals: { params: params }
end
it 'should differentiate between old, new and other' do
diff --git a/spec/views/request/_describe_state.html.erb_spec.rb b/spec/views/request/_describe_state.html.erb_spec.rb
index f4902e91c2..41fe601a75 100644
--- a/spec/views/request/_describe_state.html.erb_spec.rb
+++ b/spec/views/request/_describe_state.html.erb_spec.rb
@@ -15,7 +15,7 @@ def expect_no_radio_button(value)
end
def do_render
- render partial: 'request/describe_state', locals: {id_suffix: '1'}
+ render partial: 'request/describe_state', locals: { id_suffix: '1' }
end
before do
diff --git a/spec/views/user/sign.html.erb_spec.rb b/spec/views/user/sign.html.erb_spec.rb
index 9909772456..13d4a6fe61 100644
--- a/spec/views/user/sign.html.erb_spec.rb
+++ b/spec/views/user/sign.html.erb_spec.rb
@@ -26,10 +26,10 @@
before do
redirect = PostRedirect.create(uri: 'http://bad.place.com/admin',
- post_params: {'controller' => 'admin_general'},
- reason_params: {web: '',
+ post_params: { 'controller' => 'admin_general' },
+ reason_params: { web: '',
user_name: 'Admin user',
- user_url: 'users/admin_user'})
+ user_url: 'users/admin_user' })
receive(:disable_emergency_user).and_return(false)
assign :post_redirect, redirect
end
From fe46f6305f1513a2a0ae3a4167b0d8dbff605c2e Mon Sep 17 00:00:00 2001
From: Alexander Griffen
Date: Sun, 23 Apr 2023 22:06:45 +0100
Subject: [PATCH 013/265] style: Layout/SpaceInsideHashLiteralBraces RuboCop
Automatic correction to cop in mailers specs
---
spec/mailers/request_mailer_spec.rb | 4 ++--
spec/mailers/track_mailer_spec.rb | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/spec/mailers/request_mailer_spec.rb b/spec/mailers/request_mailer_spec.rb
index 0006521b2f..dd19c74699 100644
--- a/spec/mailers/request_mailer_spec.rb
+++ b/spec/mailers/request_mailer_spec.rb
@@ -308,10 +308,10 @@ def send_alerts
end
def sent_alert_params(request, type)
- {info_request_id: request.id,
+ { info_request_id: request.id,
user_id: request.user.id,
info_request_event_id: request.get_last_public_response_event_id,
- alert_type: type}
+ alert_type: type }
end
it 'should raise an error if a request does not have a last response event id' do
diff --git a/spec/mailers/track_mailer_spec.rb b/spec/mailers/track_mailer_spec.rb
index 4d4d9195fd..24a4121e68 100644
--- a/spec/mailers/track_mailer_spec.rb
+++ b/spec/mailers/track_mailer_spec.rb
@@ -84,7 +84,7 @@
allow(TrackThingsSentEmail).to receive(:new).and_return(@track_things_sent_email)
@xapian_search = double('xapian search', results: [])
@found_event = mock_model(InfoRequestEvent, described_at: @track_thing.created_at + 1.day)
- @search_result = {model: @found_event}
+ @search_result = { model: @found_event }
allow(ActsAsXapian::Search).to receive(:new).and_return(@xapian_search)
end
@@ -120,7 +120,7 @@
end
it 'should raise an error if a non-event class is returned by the tracking query' do
- allow(@xapian_search).to receive(:results).and_return([{model: 'string class'}])
+ allow(@xapian_search).to receive(:results).and_return([{ model: 'string class' }])
expect { TrackMailer.alert_tracks }.to raise_error('need to add other types to TrackMailer.alert_tracks (unalerted)')
end
From cc9a14a88f8dc18fa508abd51e233a981b12f0ef Mon Sep 17 00:00:00 2001
From: Alexander Griffen
Date: Sun, 23 Apr 2023 22:07:43 +0100
Subject: [PATCH 014/265] style: Layout/SpaceInsideHashLiteralBraces RuboCop
Automatic correction to cop in specs
---
spec/helpers/info_request_helper_spec.rb | 4 ++--
spec/helpers/link_to_helper_spec.rb | 2 +-
spec/validators/contact_validator_spec.rb | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/spec/helpers/info_request_helper_spec.rb b/spec/helpers/info_request_helper_spec.rb
index a14bbfe689..7455ebe966 100644
--- a/spec/helpers/info_request_helper_spec.rb
+++ b/spec/helpers/info_request_helper_spec.rb
@@ -20,14 +20,14 @@
it 'delegates the options for a valid status' do
allow(info_request).to receive(:calculate_status).and_return('successful')
- opts = {is_owning_user: false}
+ opts = { is_owning_user: false }
expect(self).to receive(:send).with('status_text_successful', info_request, opts)
status_text(info_request, opts)
end
it 'delegates to the custom partial for an unknown status' do
allow(info_request).to receive(:calculate_status).and_return('unknown')
- opts = {is_owning_user: false}
+ opts = { is_owning_user: false }
expect(self).to receive(:custom_state_description).with(info_request, opts)
status_text(info_request, opts)
end
diff --git a/spec/helpers/link_to_helper_spec.rb b/spec/helpers/link_to_helper_spec.rb
index 323d400a7b..f3c76971cb 100644
--- a/spec/helpers/link_to_helper_spec.rb
+++ b/spec/helpers/link_to_helper_spec.rb
@@ -13,7 +13,7 @@
it 'should return a path including any extra parameters passed' do
expected = "/request/#{info_request.url_title}?update_status=1"
- actual = request_path(info_request, {update_status: 1})
+ actual = request_path(info_request, { update_status: 1 })
expect(actual).to eq(expected)
end
end
diff --git a/spec/validators/contact_validator_spec.rb b/spec/validators/contact_validator_spec.rb
index befd7408a5..9e54db0f00 100644
--- a/spec/validators/contact_validator_spec.rb
+++ b/spec/validators/contact_validator_spec.rb
@@ -31,7 +31,7 @@
end
it 'validates email format' do
- valid_params.merge!({email: 'not-an-email'})
+ valid_params.merge!({ email: 'not-an-email' })
validator = ContactValidator.new(valid_params)
validator.valid?
expect(validator.errors[:email]).to include("Email doesn't look like a valid address")
From 5b017861b7ee39d4daccf393e965126d354216b7 Mon Sep 17 00:00:00 2001
From: Gareth Rees
Date: Fri, 14 Apr 2023 16:14:15 +0100
Subject: [PATCH 015/265] Extract FoiAttachment::CONTENT_TYPE_NAMES
Aids file comprehension by reducing noise within method definitions.
---
app/models/foi_attachment.rb | 46 +++++++++++++++++++-----------
spec/models/foi_attachment_spec.rb | 22 ++++++++++++++
2 files changed, 51 insertions(+), 17 deletions(-)
diff --git a/app/models/foi_attachment.rb b/app/models/foi_attachment.rb
index 5f841462c2..85a09a02e4 100644
--- a/app/models/foi_attachment.rb
+++ b/app/models/foi_attachment.rb
@@ -49,6 +49,32 @@ class FoiAttachment < ApplicationRecord
BODY_MAX_TRIES = 3
BODY_MAX_DELAY = 5
+ # rubocop:disable Style/LineLength
+ CONTENT_TYPE_NAMES = {
+ # Plain Text
+ "text/plain" => 'Text file',
+ 'application/rtf' => 'RTF file',
+
+ # Binary Documents
+ 'application/pdf' => 'PDF file',
+
+ # Images
+ 'image/tiff' => 'TIFF image',
+
+ # Word Processing
+ 'application/vnd.ms-word' => 'Word document',
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'Word document',
+
+ # Presentation
+ 'application/vnd.ms-powerpoint' => 'PowerPoint presentation',
+ 'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'PowerPoint presentation',
+
+ # Spreadsheet
+ 'application/vnd.ms-excel' => 'Excel spreadsheet',
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'Excel spreadsheet'
+ }.freeze
+ # rubocop:enable Style/LineLength
+
def delete_cached_file!
@cached_body = nil
file.purge if file.attached?
@@ -253,24 +279,10 @@ def has_body_as_html?
].include?(content_type) || has_google_docs_viewer?
end
- # Name of type of attachment type - only valid for things that has_body_as_html?
+ # Name of type of attachment type - only valid for things that
+ # has_body_as_html?
def name_of_content_type
- {
- "text/plain" => "Text file",
- 'application/rtf' => "RTF file",
-
- 'application/pdf' => "PDF file",
- 'image/tiff' => "TIFF image",
-
- 'application/vnd.ms-word' => "Word document",
- 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => "Word document",
-
- 'application/vnd.ms-powerpoint' => "PowerPoint presentation",
- 'application/vnd.openxmlformats-officedocument.presentationml.presentation' => "PowerPoint presentation",
-
- 'application/vnd.ms-excel' => "Excel spreadsheet",
- 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => "Excel spreadsheet"
- }[content_type]
+ CONTENT_TYPE_NAMES[content_type]
end
# For "View as HTML" of attachment
diff --git a/spec/models/foi_attachment_spec.rb b/spec/models/foi_attachment_spec.rb
index b0b0bb8c8d..d429797eea 100644
--- a/spec/models/foi_attachment_spec.rb
+++ b/spec/models/foi_attachment_spec.rb
@@ -205,4 +205,26 @@
end
+ describe '#name_of_content_type' do
+ subject { foi_attachment.name_of_content_type }
+
+ before do
+ stub = { 'content/named' => 'Named content' }
+ stub_const("#{described_class}::CONTENT_TYPE_NAMES", stub)
+ end
+
+ let(:foi_attachment) do
+ FactoryBot.build(:foi_attachment, content_type: content_type)
+ end
+
+ context 'when the content_type has a name' do
+ let(:content_type) { 'content/named' }
+ it { is_expected.to eq('Named content') }
+ end
+
+ context 'when the content_type has no name' do
+ let(:content_type) { 'content/unnamed' }
+ it { is_expected.to be_nil }
+ end
+ end
end
From 2556d24fb717a70d7130158d1bd8d880e31510e2 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 1 May 2023 05:55:35 +0000
Subject: [PATCH 016/265] Build(deps): Bump active_model_otp from 2.3.1 to
2.3.2
Bumps [active_model_otp](https://github.com/heapsource/active_model_otp) from 2.3.1 to 2.3.2.
- [Release notes](https://github.com/heapsource/active_model_otp/releases)
- [Commits](https://github.com/heapsource/active_model_otp/compare/v2.3.1...v2.3.2)
---
updated-dependencies:
- dependency-name: active_model_otp
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
---
Gemfile.lock | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Gemfile.lock b/Gemfile.lock
index b61e4f8c4a..e1b477069a 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -90,7 +90,7 @@ GEM
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
- active_model_otp (2.3.1)
+ active_model_otp (2.3.2)
activemodel
rotp (~> 6.2.0)
activejob (7.0.4.3)
@@ -408,7 +408,7 @@ GEM
retriable (3.1.2)
rexml (3.2.5)
rolify (6.0.1)
- rotp (6.2.0)
+ rotp (6.2.2)
routing-filter (0.7.0)
actionpack (>= 6.1)
activesupport (>= 6.1)
From 68beaf1006a179623b35a8e0b6ef15c75a8c5300 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 1 May 2023 06:02:31 +0000
Subject: [PATCH 017/265] Build(deps): Bump gettext_i18n_rails from 1.10.0 to
1.10.1
Bumps [gettext_i18n_rails](https://github.com/grosser/gettext_i18n_rails) from 1.10.0 to 1.10.1.
- [Release notes](https://github.com/grosser/gettext_i18n_rails/releases)
- [Commits](https://github.com/grosser/gettext_i18n_rails/compare/v1.10.0...v1.10.1)
---
updated-dependencies:
- dependency-name: gettext_i18n_rails
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
---
Gemfile | 2 +-
Gemfile.lock | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/Gemfile b/Gemfile
index 4f7a46777b..767557b383 100644
--- a/Gemfile
+++ b/Gemfile
@@ -135,7 +135,7 @@ gem 'gender_detector', '~> 2.0.0'
# Gems related to internationalisation
gem 'i18n', '~> 1.12.0'
gem 'rails-i18n', '~> 7.0.5'
-gem 'gettext_i18n_rails', '~> 1.10.0'
+gem 'gettext_i18n_rails', '~> 1.10.1'
gem 'fast_gettext', '~> 2.3.0'
gem 'gettext', '~> 3.4.3'
gem 'globalize', '~> 6.2.1'
diff --git a/Gemfile.lock b/Gemfile.lock
index b61e4f8c4a..ea2dcdb9b4 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -214,7 +214,7 @@ GEM
locale (>= 2.0.5)
prime
text (>= 1.3.0)
- gettext_i18n_rails (1.10.0)
+ gettext_i18n_rails (1.10.1)
fast_gettext (>= 0.9.0)
globalid (1.1.0)
activesupport (>= 5.0)
@@ -563,7 +563,7 @@ DEPENDENCIES
fivemat (~> 1.3.7)
gender_detector (~> 2.0.0)
gettext (~> 3.4.3)
- gettext_i18n_rails (~> 1.10.0)
+ gettext_i18n_rails (~> 1.10.1)
globalize (~> 6.2.1)
gnuplot (~> 2.6.0)
google-cloud-storage (~> 1.44)
From 952db9fb4a8000f93570debf07a86b776cff53cf Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 1 May 2023 06:04:59 +0000
Subject: [PATCH 018/265] Build(deps): Bump i18n from 1.12.0 to 1.13.0
Bumps [i18n](https://github.com/ruby-i18n/i18n) from 1.12.0 to 1.13.0.
- [Release notes](https://github.com/ruby-i18n/i18n/releases)
- [Changelog](https://github.com/ruby-i18n/i18n/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ruby-i18n/i18n/compare/v1.12.0...v1.13.0)
---
updated-dependencies:
- dependency-name: i18n
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
---
Gemfile | 2 +-
Gemfile.lock | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/Gemfile b/Gemfile
index 4f7a46777b..1deedf2815 100644
--- a/Gemfile
+++ b/Gemfile
@@ -133,7 +133,7 @@ gem 'zip_tricks', '~> 5.6.0'
gem 'gender_detector', '~> 2.0.0'
# Gems related to internationalisation
-gem 'i18n', '~> 1.12.0'
+gem 'i18n', '~> 1.13.0'
gem 'rails-i18n', '~> 7.0.5'
gem 'gettext_i18n_rails', '~> 1.10.0'
gem 'fast_gettext', '~> 2.3.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index b61e4f8c4a..d74c3fe1aa 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -263,7 +263,7 @@ GEM
holidays (8.6.0)
htmlentities (4.3.4)
httpclient (2.8.3)
- i18n (1.12.0)
+ i18n (1.13.0)
concurrent-ruby (~> 1.0)
icalendar (2.8.0)
ice_cube (~> 0.16)
@@ -569,7 +569,7 @@ DEPENDENCIES
google-cloud-storage (~> 1.44)
holidays (~> 8.6.0)
htmlentities (~> 4.3.0)
- i18n (~> 1.12.0)
+ i18n (~> 1.13.0)
icalendar (~> 2.8.0)
iso_country_codes (~> 0.7.8)
jquery-rails (~> 4.5.1)
From 3f3d693f3ce4371c3fd86fee95c88fbdb0411d41 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 1 May 2023 06:08:45 +0000
Subject: [PATCH 019/265] Build(deps): Bump rack from 2.2.6.4 to 2.2.7
Bumps [rack](https://github.com/rack/rack) from 2.2.6.4 to 2.2.7.
- [Release notes](https://github.com/rack/rack/releases)
- [Changelog](https://github.com/rack/rack/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rack/rack/compare/v2.2.6.4...v2.2.7)
---
updated-dependencies:
- dependency-name: rack
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
---
Gemfile | 2 +-
Gemfile.lock | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/Gemfile b/Gemfile
index 4f7a46777b..59cc9789c7 100644
--- a/Gemfile
+++ b/Gemfile
@@ -106,7 +106,7 @@ gem 'maxmind-db', '~> 1.0.0'
gem 'mahoro', '~> 0.5'
gem 'nokogiri', '~> 1.14.3'
gem 'open4', '~> 1.3.0'
-gem 'rack', '~> 2.2.6'
+gem 'rack', '~> 2.2.7'
gem 'rack-utf8_sanitizer', '~> 1.8.0'
gem 'recaptcha', '~> 5.14.0', require: 'recaptcha/rails'
gem 'matrix', '~> 0.4.2'
diff --git a/Gemfile.lock b/Gemfile.lock
index b61e4f8c4a..4f81d80f17 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -356,7 +356,7 @@ GEM
method_source (~> 1.0)
public_suffix (5.0.1)
racc (1.6.2)
- rack (2.2.6.4)
+ rack (2.2.7)
rack-test (2.1.0)
rack (>= 1.3)
rack-utf8_sanitizer (1.8.0)
@@ -592,7 +592,7 @@ DEPENDENCIES
open4 (~> 1.3.0)
pg (~> 1.4.6)
pry (~> 0.14.2)
- rack (~> 2.2.6)
+ rack (~> 2.2.7)
rack-utf8_sanitizer (~> 1.8.0)
rails (~> 7.0.4)
rails-controller-testing
From 79030e010692905fee93d9bd58a71ffa96b3b75f Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 1 May 2023 06:11:00 +0000
Subject: [PATCH 020/265] Build(deps): Bump pg from 1.4.6 to 1.5.3
Bumps [pg](https://github.com/ged/ruby-pg) from 1.4.6 to 1.5.3.
- [Release notes](https://github.com/ged/ruby-pg/releases)
- [Changelog](https://github.com/ged/ruby-pg/blob/master/History.md)
- [Commits](https://github.com/ged/ruby-pg/compare/v1.4.6...v1.5.3)
---
updated-dependencies:
- dependency-name: pg
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
---
Gemfile | 2 +-
Gemfile.lock | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/Gemfile b/Gemfile
index 4f7a46777b..267e480c76 100644
--- a/Gemfile
+++ b/Gemfile
@@ -81,7 +81,7 @@ source 'https://rubygems.org'
gem 'rails', '~> 7.0.4'
-gem 'pg', '~> 1.4.6'
+gem 'pg', '~> 1.5.3'
# New gem releases aren't being done. master is newer and supports Rails > 3.0
gem 'acts_as_versioned', git: 'https://github.com/mysociety/acts_as_versioned.git',
diff --git a/Gemfile.lock b/Gemfile.lock
index b61e4f8c4a..2f0ae13307 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -347,7 +347,7 @@ GEM
parallel (1.23.0)
parser (3.2.2.0)
ast (~> 2.4.1)
- pg (1.4.6)
+ pg (1.5.3)
prime (0.1.2)
forwardable
singleton
@@ -590,7 +590,7 @@ DEPENDENCIES
nokogiri (~> 1.14.3)
oink (~> 0.10.1)
open4 (~> 1.3.0)
- pg (~> 1.4.6)
+ pg (~> 1.5.3)
pry (~> 0.14.2)
rack (~> 2.2.6)
rack-utf8_sanitizer (~> 1.8.0)
From a343c27e6370b000ffca2a28203eeecde53bea6a Mon Sep 17 00:00:00 2001
From: Graeme Porteous
Date: Thu, 4 May 2023 14:33:22 +0100
Subject: [PATCH 021/265] Fix POP poller timeouts
Pin net-protocol to older 0.1.3 version. In 0.2.0 their was some
optimisation which is causing timeouts when polling for POP mail.
Fixes: https://github.com/mysociety/alaveteli/issues/7562
---
Gemfile | 1 +
Gemfile.lock | 3 ++-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/Gemfile b/Gemfile
index 4f7a46777b..8bf1497053 100644
--- a/Gemfile
+++ b/Gemfile
@@ -111,6 +111,7 @@ gem 'rack-utf8_sanitizer', '~> 1.8.0'
gem 'recaptcha', '~> 5.14.0', require: 'recaptcha/rails'
gem 'matrix', '~> 0.4.2'
gem 'mini_magick', '~> 4.12.0'
+gem 'net-protocol', '~> 0.1.3'
gem 'redis', '~> 4.8.1'
gem 'rolify', '~> 6.0.1'
gem 'ruby-msg', '~> 1.5.0', git: 'https://github.com/mysociety/ruby-msg.git', branch: 'ascii-encoding'
diff --git a/Gemfile.lock b/Gemfile.lock
index b61e4f8c4a..b185ad53ce 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -316,7 +316,7 @@ GEM
net-protocol
net-pop (0.1.2)
net-protocol
- net-protocol (0.2.1)
+ net-protocol (0.1.3)
timeout
net-scp (1.2.1)
net-ssh (>= 2.6.5)
@@ -585,6 +585,7 @@ DEPENDENCIES
mini_magick (~> 4.12.0)
mini_racer (~> 0.6.3)
money (~> 6.16.0)
+ net-protocol (~> 0.1.3)
net-ssh (~> 7.1.0)
net-ssh-gateway (>= 1.1.0, < 3.0.0)
nokogiri (~> 1.14.3)
From 6a3f98615b0386a79ae3cbee8b8c47e5bc1d60bf Mon Sep 17 00:00:00 2001
From: Graeme Porteous
Date: Thu, 4 May 2023 17:12:00 +0100
Subject: [PATCH 022/265] Update counter caches of seeded data
Steps followed: https://github.com/mysociety/alaveteli/wiki/Updating-fixture-data-counter-caches-columns
---
spec/controllers/statistics_controller_spec.rb | 18 +++++++++---------
spec/fixtures/info_requests.yml | 5 +++++
spec/fixtures/public_bodies.yml | 16 ++++++++--------
spec/fixtures/users.yml | 3 +++
spec/models/public_body_spec.rb | 4 ++--
5 files changed, 27 insertions(+), 19 deletions(-)
diff --git a/spec/controllers/statistics_controller_spec.rb b/spec/controllers/statistics_controller_spec.rb
index 9336fe027e..985ae34c3e 100644
--- a/spec/controllers/statistics_controller_spec.rb
+++ b/spec/controllers/statistics_controller_spec.rb
@@ -37,15 +37,15 @@
assigns[:public_bodies].each_with_index do |graph, index|
if index == 0
expect(graph['errorbars']).to be false
- expect(graph['x_values'].length).to eq(4)
- expect(graph['x_values']).to eq([0, 1, 2, 3])
- expect(graph['y_values']).to eq([1, 2, 2, 4])
+ expect(graph['x_values'].length).to eq(5)
+ expect(graph['x_values']).to eq([0, 1, 2, 3, 4])
+ expect(graph['y_values']).to eq([1, 1, 2, 2, 4])
else
expect(graph['errorbars']).to be true
# Just check the first one:
if index == 1
- expect(graph['x_values']).to eq([0, 1, 2, 3])
- expect(graph['y_values']).to eq([0, 50, 100, 100])
+ expect(graph['x_values']).to eq([0, 1, 2, 3, 4])
+ expect(graph['y_values']).to eq([0, 0, 50, 100, 100])
end
# Check that at least every confidence interval value is
# a Float (rather than NilClass, say):
@@ -62,13 +62,13 @@
expect(json['public_bodies']).to be_an(Array)
expect(json['public_bodies'][0]).to include(
'errorbars' => false,
- 'y_values' => [1, 2, 2, 4],
- 'x_values' => [0, 1, 2, 3]
+ 'y_values' => [1, 1, 2, 2, 4],
+ 'x_values' => [0, 1, 2, 3, 4]
)
expect(json['public_bodies'][1]).to include(
'errorbars' => true,
- 'x_values' => [0, 1, 2, 3],
- 'y_values' => [0, 50, 100, 100]
+ 'x_values' => [0, 1, 2, 3, 4],
+ 'y_values' => [0, 0, 50, 100, 100]
)
expect(json['public_bodies'][2]).to include(
'errorbars' => true
diff --git a/spec/fixtures/info_requests.yml b/spec/fixtures/info_requests.yml
index 178acb5179..a9ce6ccfae 100644
--- a/spec/fixtures/info_requests.yml
+++ b/spec/fixtures/info_requests.yml
@@ -50,6 +50,7 @@ fancy_dog_request:
last_public_response_at: 2007-11-13 18:09:20.042061
idhash: 50929748
use_notifications: false
+ incoming_messages_count: 1
naughty_chicken_request:
id: 103
title: How much public money is wasted on breeding naughty chickens?
@@ -90,6 +91,7 @@ boring_request:
last_public_response_at: 2007-11-13 18:00:20
idhash: 173fd003
use_notifications: false
+ incoming_messages_count: 1
another_boring_request:
id: 106
title: The cost of boring
@@ -104,6 +106,7 @@ another_boring_request:
last_public_response_at: 2007-11-13 18:09:20.042061
idhash: 173fd004
use_notifications: false
+ incoming_messages_count: 1
# A pair of identical requests (with url_title differing only in the numeric suffix)
# used to test the request de-duplication features.
@@ -121,6 +124,7 @@ spam_1_request:
last_public_response_at: 2001-01-03 01:23:45.6789100
idhash: 173fd005
use_notifications: false
+ incoming_messages_count: 1
spam_2_request:
id: 108
title: Cheap v1agra
@@ -134,6 +138,7 @@ spam_2_request:
comments_allowed: true
idhash: 173fd006
use_notifications: false
+ incoming_messages_count: 1
external_request:
id: 109
title: Balalas
diff --git a/spec/fixtures/public_bodies.yml b/spec/fixtures/public_bodies.yml
index de6edb1960..4ad64ca3bc 100644
--- a/spec/fixtures/public_bodies.yml
+++ b/spec/fixtures/public_bodies.yml
@@ -36,10 +36,10 @@ geraldine_public_body:
created_at: 2007-10-24 10:51:01.161639
api_key: 1
info_requests_count: 4
- info_requests_visible_classified_count: 4
info_requests_successful_count: 0
info_requests_not_held_count: 0
info_requests_overdue_count: 3
+ info_requests_visible_classified_count: 3
info_requests_visible_count: 4
humpadink_public_body:
updated_at: 2007-10-25 10:51:01.161639
@@ -50,10 +50,10 @@ humpadink_public_body:
created_at: 2007-10-25 10:51:01.161639
api_key: 2
info_requests_count: 2
- info_requests_visible_classified_count: 2
info_requests_successful_count: 1
info_requests_not_held_count: 0
info_requests_overdue_count: 1
+ info_requests_visible_classified_count: 2
info_requests_visible_count: 2
forlorn_public_body:
updated_at: 2011-01-26 14:11:02.12345
@@ -64,10 +64,10 @@ forlorn_public_body:
created_at: 2011-01-26 14:11:02.12345
api_key: 3
info_requests_count: 0
- info_requests_visible_classified_count: 0
info_requests_successful_count: 0
info_requests_not_held_count: 0
info_requests_overdue_count: 0
+ info_requests_visible_classified_count: 0
info_requests_visible_count: 0
silly_walks_public_body:
id: 5
@@ -78,10 +78,10 @@ silly_walks_public_body:
created_at: 2007-10-25 10:51:01.161639
api_key: 4
info_requests_count: 2
- info_requests_visible_classified_count: 2
info_requests_successful_count: 2
info_requests_not_held_count: 0
info_requests_overdue_count: 0
+ info_requests_visible_classified_count: 2
info_requests_visible_count: 2
sensible_walks_public_body:
id: 6
@@ -92,10 +92,10 @@ sensible_walks_public_body:
created_at: 2008-10-25 10:51:01.161639
api_key: 5
info_requests_count: 1
- info_requests_visible_classified_count: 1
info_requests_successful_count: 1
info_requests_not_held_count: 0
info_requests_overdue_count: 0
+ info_requests_visible_classified_count: 1
info_requests_visible_count: 1
other_public_body:
id: 7
@@ -105,9 +105,9 @@ other_public_body:
last_edit_editor: louise
created_at: 2008-10-25 10:51:01.161639
api_key: 6
- info_requests_count: 0
- info_requests_visible_classified_count: 0
+ info_requests_count: 1
info_requests_successful_count: 0
info_requests_not_held_count: 0
info_requests_overdue_count: 0
- info_requests_visible_count: 0
+ info_requests_visible_classified_count: 1
+ info_requests_visible_count: 1
diff --git a/spec/fixtures/users.yml b/spec/fixtures/users.yml
index a9eda3156c..8284fee0f9 100644
--- a/spec/fixtures/users.yml
+++ b/spec/fixtures/users.yml
@@ -56,6 +56,7 @@ bob_smith_user:
locale: 'en'
about_me: 'I like making requests about fancy dogs and naughty chickens and stuff.'
receive_email_alerts: true
+ info_requests_count: 5
silly_name_user:
id: "2"
name: "Silly Name"
@@ -110,6 +111,7 @@ robin_user:
ban_text: ''
about_me: 'I am the best'
receive_email_alerts: true
+ info_requests_count: 2
another_user:
id: 6
name: Another User
@@ -123,6 +125,7 @@ another_user:
ban_text: ''
about_me: 'Just another user'
receive_email_alerts: true
+ info_requests_count: 1
paul_pro_user:
id: 7
name: Paul Pro
diff --git a/spec/models/public_body_spec.rb b/spec/models/public_body_spec.rb
index 6d708f06d2..4476341ae4 100644
--- a/spec/models/public_body_spec.rb
+++ b/spec/models/public_body_spec.rb
@@ -2045,7 +2045,7 @@ def set_default_attributes(public_body)
minimum_requests = 1
with_enough_info_requests = PublicBody.where(["info_requests_count >= ?",
minimum_requests]).length
- all_data = PublicBody.get_request_totals 4, true, minimum_requests
+ all_data = PublicBody.get_request_totals 5, true, minimum_requests
expect(all_data['public_bodies'].length).to eq(with_enough_info_requests)
end
@@ -2077,7 +2077,7 @@ def set_default_attributes(public_body)
minimum_requests = 1
with_enough_info_requests = PublicBody.where(["info_requests_count >= ?", minimum_requests])
all_data = PublicBody.get_request_totals 4, true, minimum_requests
- expect(all_data['public_bodies'].length).to eq(3)
+ expect(all_data['public_bodies'].length).to eq(4)
ensure
hpb.tag_string = original_tag_string
end
From c5cc977c076ec9aa520b93074bc9d893e81f5924 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 5 May 2023 08:37:48 +0000
Subject: [PATCH 023/265] Build(deps): Bump aws-sdk-s3 from 1.121.0 to 1.122.0
Bumps [aws-sdk-s3](https://github.com/aws/aws-sdk-ruby) from 1.121.0 to 1.122.0.
- [Release notes](https://github.com/aws/aws-sdk-ruby/releases)
- [Changelog](https://github.com/aws/aws-sdk-ruby/blob/version-3/gems/aws-sdk-s3/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-ruby/commits)
---
updated-dependencies:
- dependency-name: aws-sdk-s3
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
---
Gemfile.lock | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/Gemfile.lock b/Gemfile.lock
index b185ad53ce..eb0557f3b4 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -120,16 +120,16 @@ GEM
rake (>= 10.4, < 14.0)
ast (2.4.2)
aws-eventstream (1.2.0)
- aws-partitions (1.751.0)
- aws-sdk-core (3.171.0)
+ aws-partitions (1.760.0)
+ aws-sdk-core (3.171.1)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.651.0)
aws-sigv4 (~> 1.5)
jmespath (~> 1, >= 1.6.1)
- aws-sdk-kms (1.63.0)
+ aws-sdk-kms (1.64.0)
aws-sdk-core (~> 3, >= 3.165.0)
aws-sigv4 (~> 1.1)
- aws-sdk-s3 (1.121.0)
+ aws-sdk-s3 (1.122.0)
aws-sdk-core (~> 3, >= 3.165.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.4)
From bdd89143c7715ba0b30337ddc11c8b4a0cddeaba Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 5 May 2023 08:40:36 +0000
Subject: [PATCH 024/265] Build(deps): Bump mime-types from 2.99.3 to 3.4.1
Bumps [mime-types](https://github.com/mime-types/ruby-mime-types) from 2.99.3 to 3.4.1.
- [Changelog](https://github.com/mime-types/ruby-mime-types/blob/main/History.md)
- [Commits](https://github.com/mime-types/ruby-mime-types/compare/v2.99.3...v3.4.1)
---
updated-dependencies:
- dependency-name: mime-types
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot]
---
Gemfile | 2 +-
Gemfile.lock | 15 +++++++++------
.../alaveteli_features/alaveteli_features.gemspec | 2 +-
3 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/Gemfile b/Gemfile
index 8bf1497053..75df5c04bc 100644
--- a/Gemfile
+++ b/Gemfile
@@ -147,7 +147,7 @@ gem 'unidecoder', '~> 1.1.0'
gem 'money', '~> 6.16.0'
# mime-types 3.0.0 requires Ruby 2.0.0, and _something_ is trying to update it
-gem 'mime-types', '< 3.0.0', require: false
+gem 'mime-types', '< 4.0.0', require: false
# Assets
gem 'bootstrap-sass', '~> 2.3.2.2'
diff --git a/Gemfile.lock b/Gemfile.lock
index b185ad53ce..1cf0da5ca6 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -39,7 +39,7 @@ PATH
alaveteli_features (0.0.1)
flipper (~> 0.10)
flipper-active_record (~> 0.10)
- mime-types (< 3.0.0)
+ mime-types (< 4.0.0)
rails (~> 7.0.4)
GEM
@@ -203,10 +203,11 @@ GEM
faraday (>= 0.7.4, < 1.0)
fast_gettext (2.3.0)
fivemat (1.3.7)
- flipper (0.24.1)
- flipper-active_record (0.24.1)
+ flipper (0.28.0)
+ concurrent-ruby (< 2)
+ flipper-active_record (0.28.0)
activerecord (>= 4.2, < 8)
- flipper (~> 0.24.1)
+ flipper (~> 0.28.0)
forwardable (1.3.3)
gender_detector (2.0.0)
gettext (3.4.3)
@@ -300,7 +301,9 @@ GEM
maxmind-db (1.0.0)
memoist (0.16.2)
method_source (1.0.0)
- mime-types (2.99.3)
+ mime-types (3.4.1)
+ mime-types-data (~> 3.2015)
+ mime-types-data (3.2023.0218.1)
mini_magick (4.12.0)
mini_mime (1.1.2)
mini_portile2 (2.8.1)
@@ -581,7 +584,7 @@ DEPENDENCIES
mail (~> 2.8.1)
matrix (~> 0.4.2)
maxmind-db (~> 1.0.0)
- mime-types (< 3.0.0)
+ mime-types (< 4.0.0)
mini_magick (~> 4.12.0)
mini_racer (~> 0.6.3)
money (~> 6.16.0)
diff --git a/gems/alaveteli_features/alaveteli_features.gemspec b/gems/alaveteli_features/alaveteli_features.gemspec
index 68a338bdb3..6daf884b44 100644
--- a/gems/alaveteli_features/alaveteli_features.gemspec
+++ b/gems/alaveteli_features/alaveteli_features.gemspec
@@ -23,7 +23,7 @@ Gem::Specification.new do |spec|
spec.add_dependency "flipper-active_record", "~> 0.10"
# Mime types 3 needs Ruby 2.0.0 or greater, but we need to support 1.9.3 so
# force a lower version
- spec.add_dependency "mime-types", "< 3.0.0"
+ spec.add_dependency "mime-types", "< 4.0.0"
spec.add_development_dependency "bundler", "~> 1.3"
spec.add_development_dependency "rake", "~> 12.3"
From 530d78f9a8d5ef051fbb0af6728f6fffa65053c5 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 5 May 2023 08:41:06 +0000
Subject: [PATCH 025/265] Build(deps-dev): Bump rspec-rails from 6.0.1 to 6.0.2
Bumps [rspec-rails](https://github.com/rspec/rspec-rails) from 6.0.1 to 6.0.2.
- [Release notes](https://github.com/rspec/rspec-rails/releases)
- [Changelog](https://github.com/rspec/rspec-rails/blob/main/Changelog.md)
- [Commits](https://github.com/rspec/rspec-rails/compare/v6.0.1...v6.0.2)
---
updated-dependencies:
- dependency-name: rspec-rails
dependency-type: direct:development
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
---
Gemfile | 2 +-
Gemfile.lock | 32 +++++++++----------
.../alaveteli_features.gemspec | 2 +-
3 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/Gemfile b/Gemfile
index 8bf1497053..da0a9345e8 100644
--- a/Gemfile
+++ b/Gemfile
@@ -179,7 +179,7 @@ group :test, :development do
gem 'factory_bot_rails', '~> 6.2.0'
gem 'oink', '~> 0.10.1'
gem 'rspec-activemodel-mocks', '~> 1.1.0'
- gem 'rspec-rails', '~> 6.0.0'
+ gem 'rspec-rails', '~> 6.0.2'
gem 'pry', '~> 0.14.2'
end
diff --git a/Gemfile.lock b/Gemfile.lock
index b185ad53ce..91afbdf095 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -286,7 +286,7 @@ GEM
libv8-node (16.10.0.0-x86_64-darwin)
libv8-node (16.10.0.0-x86_64-linux)
locale (2.1.3)
- loofah (2.19.1)
+ loofah (2.20.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mahoro (0.5)
@@ -303,7 +303,7 @@ GEM
mime-types (2.99.3)
mini_magick (4.12.0)
mini_mime (1.1.2)
- mini_portile2 (2.8.1)
+ mini_portile2 (2.8.2)
mini_racer (0.6.3)
libv8-node (~> 16.10.0.0)
minitest (5.18.0)
@@ -416,23 +416,23 @@ GEM
activemodel (>= 3.0)
activesupport (>= 3.0)
rspec-mocks (>= 2.99, < 4.0)
- rspec-core (3.11.0)
- rspec-support (~> 3.11.0)
- rspec-expectations (3.11.1)
+ rspec-core (3.12.2)
+ rspec-support (~> 3.12.0)
+ rspec-expectations (3.12.3)
diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.11.0)
- rspec-mocks (3.11.1)
+ rspec-support (~> 3.12.0)
+ rspec-mocks (3.12.5)
diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.11.0)
- rspec-rails (6.0.1)
+ rspec-support (~> 3.12.0)
+ rspec-rails (6.0.2)
actionpack (>= 6.1)
activesupport (>= 6.1)
railties (>= 6.1)
- rspec-core (~> 3.11)
- rspec-expectations (~> 3.11)
- rspec-mocks (~> 3.11)
- rspec-support (~> 3.11)
- rspec-support (3.11.1)
+ rspec-core (~> 3.12)
+ rspec-expectations (~> 3.12)
+ rspec-mocks (~> 3.12)
+ rspec-support (~> 3.12)
+ rspec-support (3.12.0)
rubocop (1.50.2)
json (~> 2.3)
parallel (~> 1.10)
@@ -531,7 +531,7 @@ GEM
rexml
xpath (3.2.0)
nokogiri (~> 1.8)
- zeitwerk (2.6.7)
+ zeitwerk (2.6.8)
zip_tricks (5.6.0)
PLATFORMS
@@ -603,7 +603,7 @@ DEPENDENCIES
rolify (~> 6.0.1)
routing-filter (~> 0.7.0)
rspec-activemodel-mocks (~> 1.1.0)
- rspec-rails (~> 6.0.0)
+ rspec-rails (~> 6.0.2)
rubocop (~> 1.50.2)
rubocop-performance
rubocop-rails
diff --git a/gems/alaveteli_features/alaveteli_features.gemspec b/gems/alaveteli_features/alaveteli_features.gemspec
index 68a338bdb3..1578914dcd 100644
--- a/gems/alaveteli_features/alaveteli_features.gemspec
+++ b/gems/alaveteli_features/alaveteli_features.gemspec
@@ -28,5 +28,5 @@ Gem::Specification.new do |spec|
spec.add_development_dependency "bundler", "~> 1.3"
spec.add_development_dependency "rake", "~> 12.3"
spec.add_development_dependency "rspec", "~> 3.7"
- spec.add_development_dependency "rspec-rails", "~> 3.7"
+ spec.add_development_dependency "rspec-rails", "~> 6.0"
end
From b0e875568789aabc3ac041b62a78a983beeaa874 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 5 May 2023 11:01:51 +0000
Subject: [PATCH 026/265] Build(deps): Bump i18n from 1.12.0 to 1.13.0
Bumps [i18n](https://github.com/ruby-i18n/i18n) from 1.12.0 to 1.13.0.
- [Release notes](https://github.com/ruby-i18n/i18n/releases)
- [Changelog](https://github.com/ruby-i18n/i18n/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ruby-i18n/i18n/compare/v1.12.0...v1.13.0)
---
updated-dependencies:
- dependency-name: i18n
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
---
Gemfile | 2 +-
Gemfile.lock | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/Gemfile b/Gemfile
index f2f6107ec1..27f60d9401 100644
--- a/Gemfile
+++ b/Gemfile
@@ -134,7 +134,7 @@ gem 'zip_tricks', '~> 5.6.0'
gem 'gender_detector', '~> 2.0.0'
# Gems related to internationalisation
-gem 'i18n', '~> 1.12.0'
+gem 'i18n', '~> 1.13.0'
gem 'rails-i18n', '~> 7.0.5'
gem 'gettext_i18n_rails', '~> 1.10.1'
gem 'fast_gettext', '~> 2.3.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index 4d06be4a05..b84ea4160b 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -263,7 +263,7 @@ GEM
holidays (8.6.0)
htmlentities (4.3.4)
httpclient (2.8.3)
- i18n (1.12.0)
+ i18n (1.13.0)
concurrent-ruby (~> 1.0)
icalendar (2.8.0)
ice_cube (~> 0.16)
@@ -569,7 +569,7 @@ DEPENDENCIES
google-cloud-storage (~> 1.44)
holidays (~> 8.6.0)
htmlentities (~> 4.3.0)
- i18n (~> 1.12.0)
+ i18n (~> 1.13.0)
icalendar (~> 2.8.0)
iso_country_codes (~> 0.7.8)
jquery-rails (~> 4.5.1)
From 18b4921894eb21756f0c04a68d20cc77445cecc2 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 8 May 2023 05:08:40 +0000
Subject: [PATCH 027/265] Build(deps): Bump rack from 2.2.6.4 to 2.2.7
Bumps [rack](https://github.com/rack/rack) from 2.2.6.4 to 2.2.7.
- [Release notes](https://github.com/rack/rack/releases)
- [Changelog](https://github.com/rack/rack/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rack/rack/compare/v2.2.6.4...v2.2.7)
---
updated-dependencies:
- dependency-name: rack
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
---
Gemfile | 2 +-
Gemfile.lock | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/Gemfile b/Gemfile
index f2f6107ec1..9e67fd516e 100644
--- a/Gemfile
+++ b/Gemfile
@@ -106,7 +106,7 @@ gem 'maxmind-db', '~> 1.0.0'
gem 'mahoro', '~> 0.5'
gem 'nokogiri', '~> 1.14.3'
gem 'open4', '~> 1.3.0'
-gem 'rack', '~> 2.2.6'
+gem 'rack', '~> 2.2.7'
gem 'rack-utf8_sanitizer', '~> 1.8.0'
gem 'recaptcha', '~> 5.14.0', require: 'recaptcha/rails'
gem 'matrix', '~> 0.4.2'
diff --git a/Gemfile.lock b/Gemfile.lock
index 4d06be4a05..f20d101f0b 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -356,7 +356,7 @@ GEM
method_source (~> 1.0)
public_suffix (5.0.1)
racc (1.6.2)
- rack (2.2.6.4)
+ rack (2.2.7)
rack-test (2.1.0)
rack (>= 1.3)
rack-utf8_sanitizer (1.8.0)
@@ -593,7 +593,7 @@ DEPENDENCIES
open4 (~> 1.3.0)
pg (~> 1.4.6)
pry (~> 0.14.2)
- rack (~> 2.2.6)
+ rack (~> 2.2.7)
rack-utf8_sanitizer (~> 1.8.0)
rails (~> 7.0.4)
rails-controller-testing
From bfcc5ac3bd1c2cd6df821432a1dc6a0e34d764d7 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 15 May 2023 05:10:42 +0000
Subject: [PATCH 028/265] Build(deps-dev): Bump capybara from 3.39.0 to 3.39.1
Bumps [capybara](https://github.com/teamcapybara/capybara) from 3.39.0 to 3.39.1.
- [Changelog](https://github.com/teamcapybara/capybara/blob/master/History.md)
- [Commits](https://github.com/teamcapybara/capybara/compare/3.39.0...3.39.1)
---
updated-dependencies:
- dependency-name: capybara
dependency-type: direct:development
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
---
Gemfile | 2 +-
Gemfile.lock | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/Gemfile b/Gemfile
index 4130cb3d79..44c642084a 100644
--- a/Gemfile
+++ b/Gemfile
@@ -168,7 +168,7 @@ group :test do
gem 'webmock', '~> 3.18.1'
gem 'simplecov', '~> 0.22.0'
gem 'simplecov-lcov', '~> 0.7.0'
- gem 'capybara', '~> 3.39.0'
+ gem 'capybara', '~> 3.39.1'
gem 'stripe-ruby-mock', git: 'https://github.com/stripe-ruby-mock/stripe-ruby-mock',
ref: '6ceea96'
gem 'rails-controller-testing'
diff --git a/Gemfile.lock b/Gemfile.lock
index e4fda63120..06a4a2abcf 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -113,7 +113,7 @@ GEM
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
- addressable (2.8.2)
+ addressable (2.8.4)
public_suffix (>= 2.0.2, < 6.0)
annotate (3.2.0)
activerecord (>= 3.2, < 8.0)
@@ -159,7 +159,7 @@ GEM
net-sftp (>= 2.0.0)
net-ssh (>= 2.0.14)
net-ssh-gateway (>= 1.1.0)
- capybara (3.39.0)
+ capybara (3.39.1)
addressable
matrix
mini_mime (>= 0.1.3)
@@ -556,7 +556,7 @@ DEPENDENCIES
bullet (~> 7.0.7)
cancancan (~> 3.5.0)
capistrano (~> 2.15.0, < 3.0.0)
- capybara (~> 3.39.0)
+ capybara (~> 3.39.1)
charlock_holmes (~> 0.7.7)
dalli (~> 3.2.4)
exception_notification (~> 4.5.0)
From 94cb3680cc6fa229894626be93a5ae23907edbe0 Mon Sep 17 00:00:00 2001
From: Alexander Griffen
Date: Thu, 11 May 2023 17:57:31 +0100
Subject: [PATCH 029/265] Layout/LineLength ignores RSpec.describe lines
This change to the style yaml file makes the Layout/LineLength Cop
ignore the lines near the beginning of spec files, consistent with how
it already ignores 'context', 'it', and 'describe' lines
---
.ruby-style.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.ruby-style.yml b/.ruby-style.yml
index 8c25fcf7c1..d3990c0b15 100644
--- a/.ruby-style.yml
+++ b/.ruby-style.yml
@@ -255,6 +255,7 @@ Layout/LineLength:
- "^\\s*it\\s+.*do$"
- "^\\s*context\\s+.*do$"
- "^\\s*describe\\s+.*do$"
+ - "^RSpec\\.describe(\\s+|\\().*do$"
- "^\\s*class\\s+[A-Z].*<.*"
Exclude:
- bin/setup
From 32abc041c2f6f101e87ec41b6e83711566773c4e Mon Sep 17 00:00:00 2001
From: Gareth Rees
Date: Thu, 18 May 2023 10:23:21 +0100
Subject: [PATCH 030/265] Site-wide announcements are banners
Trivial phrasing tweak just for extra clarity.
Spotted while triaging https://github.com/mysociety/alaveteli/issues/6203.
---
app/views/admin_announcements/_form.html.erb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/views/admin_announcements/_form.html.erb b/app/views/admin_announcements/_form.html.erb
index 32c512d82f..f41c59b247 100644
--- a/app/views/admin_announcements/_form.html.erb
+++ b/app/views/admin_announcements/_form.html.erb
@@ -36,7 +36,7 @@
From 21a945b50f3fe89749062b6a8aa40fdd4d042442 Mon Sep 17 00:00:00 2001
From: Graeme Porteous
Date: Mon, 8 May 2023 22:54:51 +0100
Subject: [PATCH 103/265] Add admin alerts when users' names has changed
When viewing outgoing messages and potentially resending them, it is
important to know if the user's name has changed. This could result in
the outbound email header not matching how the email has been signed
off. This could cause confusion for the authority.
---
app/views/admin_outgoing_message/edit.html.erb | 8 ++++++++
app/views/admin_request/show.html.erb | 7 +++++++
2 files changed, 15 insertions(+)
diff --git a/app/views/admin_outgoing_message/edit.html.erb b/app/views/admin_outgoing_message/edit.html.erb
index 701ed08cdb..cff4725b50 100644
--- a/app/views/admin_outgoing_message/edit.html.erb
+++ b/app/views/admin_outgoing_message/edit.html.erb
@@ -69,6 +69,14 @@
+ <% if @outgoing_message.from_name != @info_request.user_name %>
+
+ The requester's name has changed since this message was last sent
+ to the authority. Resending will use the user's current name, which
+ may cause confusion.
+
From 9e65d69fdbc5b635e079ecfe98437a4fd9f2376b Mon Sep 17 00:00:00 2001
From: Graeme Porteous
Date: Tue, 25 Jul 2023 12:27:08 +0100
Subject: [PATCH 120/265] Minor cleanup
Wrap long lines.
---
spec/script/handle-mail-replies_spec.rb | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/spec/script/handle-mail-replies_spec.rb b/spec/script/handle-mail-replies_spec.rb
index 71663a3ba7..186bfe542a 100644
--- a/spec/script/handle-mail-replies_spec.rb
+++ b/spec/script/handle-mail-replies_spec.rb
@@ -16,15 +16,17 @@ def mail_reply_test(email_filename)
describe "when not in test mode" do
it "should not fail handling a bounce mail" do
- xc = ExternalCommand.new("script/handle-mail-replies",
- { stdin_string: load_file_fixture("track-response-exim-bounce.email") })
+ xc = ExternalCommand.new("script/handle-mail-replies", {
+ stdin_string: load_file_fixture("track-response-exim-bounce.email")
+ })
xc.run
expect(xc.err).to eq("")
end
it 'should not fail handling a UTF8 encoded mail' do
- xc = ExternalCommand.new("script/handle-mail-replies",
- { stdin_string: load_file_fixture("russian.email") })
+ xc = ExternalCommand.new("script/handle-mail-replies", {
+ stdin_string: load_file_fixture("russian.email")
+ })
xc.run
expect(xc.err).to eq("")
end
From 046a59cc354e517dd68c858e9948778a4a8ab88c Mon Sep 17 00:00:00 2001
From: Graeme Porteous
Date: Tue, 25 Jul 2023 12:27:53 +0100
Subject: [PATCH 121/265] Update configuration loading
Extract `#get` into shared method so this can be updated in a single
place allowing the test environment to override configuration by setting
environment variables prefixed with `ALAVETELI_*`.
Requires updating commonlib which includes a fix to ensure environment
variables are restored correctly after external commands have executed.
---
commonlib | 2 +-
lib/configuration.rb | 11 +++++++++--
2 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/commonlib b/commonlib
index 8b638d674b..6149757c74 160000
--- a/commonlib
+++ b/commonlib
@@ -1 +1 @@
-Subproject commit 8b638d674badcb1dc6a4867d9f49571caecc923c
+Subproject commit 6149757c743b7e746aceb650e78a497a46bcc64f
diff --git a/lib/configuration.rb b/lib/configuration.rb
index 14532ef8fc..606874d1ef 100644
--- a/lib/configuration.rb
+++ b/lib/configuration.rb
@@ -136,8 +136,15 @@ module AlaveteliConfiguration
# rubocop:enable Layout/LineLength
end
+ def self.get(key, default)
+ # Don't use the `Rails.env.test?` as this has to work for external commands
+ # when Rails environment isn't loaded.
+ value = ENV["ALAVETELI_#{key}"] if ENV['RAILS_ENV'] == 'test'
+ value || MySociety::Config.get(key, default)
+ end
+
def self.background_jobs
- value = MySociety::Config.get('BACKGROUND_JOBS', DEFAULTS[:BACKGROUND_JOBS])
+ value = get('BACKGROUND_JOBS', DEFAULTS[:BACKGROUND_JOBS])
return value if %w[inline server].include?(value)
raise 'Unknown value for BACKGROUND_JOBS. Please check config/general.yml'
end
@@ -145,7 +152,7 @@ def self.background_jobs
def self.method_missing(name)
key = name.to_s.upcase
if DEFAULTS.key?(key.to_sym)
- MySociety::Config.get(key, DEFAULTS[key.to_sym])
+ get(key, DEFAULTS[key.to_sym])
else
super
end
From bdf7269cb4a6e4ff9996d49e23dfbdad24f356c3 Mon Sep 17 00:00:00 2001
From: Graeme Porteous
Date: Tue, 25 Jul 2023 11:29:14 +0100
Subject: [PATCH 122/265] Fix handle-mail-replies script
Add load for commonlib validate library which is now required as we're
scanning "Received" headers for email addresses.
Fixes #7842
---
script/handle-mail-replies.rb | 1 +
spec/script/handle-mail-replies_spec.rb | 9 +++++++++
2 files changed, 10 insertions(+)
diff --git a/script/handle-mail-replies.rb b/script/handle-mail-replies.rb
index d751772166..94d0a04d56 100755
--- a/script/handle-mail-replies.rb
+++ b/script/handle-mail-replies.rb
@@ -17,6 +17,7 @@
$alaveteli_dir = File.expand_path(File.join(File.dirname(__FILE__), '..'))
$LOAD_PATH.push(File.join($alaveteli_dir, 'commonlib', 'rblib'))
+load 'validate.rb'
load 'config.rb'
MySociety::Config.set_file(File.join($alaveteli_dir, 'config', 'general'), true)
MySociety::Config.load_default
diff --git a/spec/script/handle-mail-replies_spec.rb b/spec/script/handle-mail-replies_spec.rb
index 186bfe542a..ec53a15850 100644
--- a/spec/script/handle-mail-replies_spec.rb
+++ b/spec/script/handle-mail-replies_spec.rb
@@ -30,6 +30,15 @@ def mail_reply_test(email_filename)
xc.run
expect(xc.err).to eq("")
end
+
+ it "should pass on a non-bounce message with Received headers and Pro enabled" do
+ xc = ExternalCommand.new("script/handle-mail-replies", {
+ env: { 'ALAVETELI_ENABLE_ALAVETELI_PRO' => 'true' },
+ stdin_string: load_file_fixture("apple-mail-with-attachments.email")
+ })
+ xc.run
+ expect(xc.err).to eq("")
+ end
end
it "should detect an Exim bounce" do
From 355181745555e6e4f731aaa1303bb84c75f7e609 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 31 Jul 2023 04:52:25 +0000
Subject: [PATCH 123/265] Build(deps-dev): Bump net-ssh from 7.1.0 to 7.2.0
Bumps [net-ssh](https://github.com/net-ssh/net-ssh) from 7.1.0 to 7.2.0.
- [Changelog](https://github.com/net-ssh/net-ssh/blob/master/CHANGES.txt)
- [Commits](https://github.com/net-ssh/net-ssh/compare/v7.1.0...v7.2.0)
---
updated-dependencies:
- dependency-name: net-ssh
dependency-type: direct:development
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
---
Gemfile | 2 +-
Gemfile.lock | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/Gemfile b/Gemfile
index 5a0fa30778..5df3d0f56c 100644
--- a/Gemfile
+++ b/Gemfile
@@ -188,7 +188,7 @@ end
group :development do
gem 'annotate', '< 3.2.1'
gem 'capistrano', '~> 2.15.11'
- gem 'net-ssh', '~> 7.1.0'
+ gem 'net-ssh', '~> 7.2.0'
gem 'net-ssh-gateway', '>= 1.1.0', '< 3.0.0'
gem 'launchy', '< 2.6.0'
gem 'web-console', '>= 3.3.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index 1d8d600fba..bca24d78f2 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -340,7 +340,7 @@ GEM
net-ssh (>= 5.0.0, < 8.0.0)
net-smtp (0.3.3)
net-protocol
- net-ssh (7.1.0)
+ net-ssh (7.2.0)
net-ssh-gateway (2.0.0)
net-ssh (>= 4.0.0)
nio4r (2.5.9)
@@ -604,7 +604,7 @@ DEPENDENCIES
mini_racer (~> 0.8.0)
money (~> 6.16.0)
net-protocol (~> 0.1.3)
- net-ssh (~> 7.1.0)
+ net-ssh (~> 7.2.0)
net-ssh-gateway (>= 1.1.0, < 3.0.0)
nokogiri (~> 1.15.3)
oink (~> 0.10.1)
From 7b3807eb11288c00646f81a4d7d86bfa00d94afe Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 31 Jul 2023 04:54:04 +0000
Subject: [PATCH 124/265] Build(deps): Bump aws-sdk-s3 from 1.131.0 to 1.132.0
Bumps [aws-sdk-s3](https://github.com/aws/aws-sdk-ruby) from 1.131.0 to 1.132.0.
- [Release notes](https://github.com/aws/aws-sdk-ruby/releases)
- [Changelog](https://github.com/aws/aws-sdk-ruby/blob/version-3/gems/aws-sdk-s3/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-ruby/commits)
---
updated-dependencies:
- dependency-name: aws-sdk-s3
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
---
Gemfile.lock | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/Gemfile.lock b/Gemfile.lock
index 1d8d600fba..c09e996d16 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -129,8 +129,8 @@ GEM
rake (>= 10.4, < 14.0)
ast (2.4.2)
aws-eventstream (1.2.0)
- aws-partitions (1.791.0)
- aws-sdk-core (3.178.0)
+ aws-partitions (1.794.0)
+ aws-sdk-core (3.180.0)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.651.0)
aws-sigv4 (~> 1.5)
@@ -138,8 +138,8 @@ GEM
aws-sdk-kms (1.71.0)
aws-sdk-core (~> 3, >= 3.177.0)
aws-sigv4 (~> 1.1)
- aws-sdk-s3 (1.131.0)
- aws-sdk-core (~> 3, >= 3.177.0)
+ aws-sdk-s3 (1.132.0)
+ aws-sdk-core (~> 3, >= 3.179.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.6)
aws-sigv4 (1.6.0)
From 48e7a2a7734034cdc6d1771d6307cbe97ae9323a Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 31 Jul 2023 05:02:07 +0000
Subject: [PATCH 125/265] Build(deps-dev): Bump rubocop from 1.54.2 to 1.55.0
Bumps [rubocop](https://github.com/rubocop/rubocop) from 1.54.2 to 1.55.0.
- [Release notes](https://github.com/rubocop/rubocop/releases)
- [Changelog](https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop/compare/v1.54.2...v1.55.0)
---
updated-dependencies:
- dependency-name: rubocop
dependency-type: direct:development
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
---
Gemfile | 2 +-
Gemfile.lock | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/Gemfile b/Gemfile
index 5a0fa30778..011be9a533 100644
--- a/Gemfile
+++ b/Gemfile
@@ -192,7 +192,7 @@ group :development do
gem 'net-ssh-gateway', '>= 1.1.0', '< 3.0.0'
gem 'launchy', '< 2.6.0'
gem 'web-console', '>= 3.3.0'
- gem 'rubocop', '~> 1.54.2', require: false
+ gem 'rubocop', '~> 1.55.0', require: false
gem 'rubocop-performance', require: false
gem 'rubocop-rails', require: false
end
diff --git a/Gemfile.lock b/Gemfile.lock
index 1d8d600fba..eee43dc70b 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -425,7 +425,7 @@ GEM
request_store (1.5.1)
rack (>= 1.4)
retriable (3.1.2)
- rexml (3.2.5)
+ rexml (3.2.6)
rolify (6.0.1)
rotp (6.2.2)
routing-filter (0.7.0)
@@ -452,7 +452,7 @@ GEM
rspec-mocks (~> 3.12)
rspec-support (~> 3.12)
rspec-support (3.12.0)
- rubocop (1.54.2)
+ rubocop (1.55.0)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
@@ -460,7 +460,7 @@ GEM
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0)
- rubocop-ast (>= 1.28.0, < 2.0)
+ rubocop-ast (>= 1.28.1, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.29.0)
@@ -622,7 +622,7 @@ DEPENDENCIES
routing-filter (~> 0.7.0)
rspec-activemodel-mocks (~> 1.1.0)
rspec-rails (~> 6.0.3)
- rubocop (~> 1.54.2)
+ rubocop (~> 1.55.0)
rubocop-performance
rubocop-rails
ruby-msg (~> 1.5.0)!
From aa0a61aab9571204877952a98bf0007a801c5551 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 31 Jul 2023 05:05:12 +0000
Subject: [PATCH 126/265] Build(deps): Bump rack from 2.2.7 to 2.2.8
Bumps [rack](https://github.com/rack/rack) from 2.2.7 to 2.2.8.
- [Release notes](https://github.com/rack/rack/releases)
- [Changelog](https://github.com/rack/rack/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rack/rack/compare/v2.2.7...v2.2.8)
---
updated-dependencies:
- dependency-name: rack
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
---
Gemfile | 2 +-
Gemfile.lock | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/Gemfile b/Gemfile
index 5a0fa30778..90c02201ad 100644
--- a/Gemfile
+++ b/Gemfile
@@ -107,7 +107,7 @@ gem 'maxmind-db', '~> 1.0.0'
gem 'mahoro', '~> 0.5'
gem 'nokogiri', '~> 1.15.3'
gem 'open4', '~> 1.3.0'
-gem 'rack', '~> 2.2.7'
+gem 'rack', '~> 2.2.8'
gem 'rack-utf8_sanitizer', '~> 1.9.0'
gem 'recaptcha', '~> 5.14.0', require: 'recaptcha/rails'
gem 'matrix', '~> 0.4.2'
diff --git a/Gemfile.lock b/Gemfile.lock
index 1d8d600fba..3935c2d6b1 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -373,7 +373,7 @@ GEM
method_source (~> 1.0)
public_suffix (5.0.1)
racc (1.7.1)
- rack (2.2.7)
+ rack (2.2.8)
rack-test (2.1.0)
rack (>= 1.3)
rack-utf8_sanitizer (1.9.0)
@@ -611,7 +611,7 @@ DEPENDENCIES
open4 (~> 1.3.0)
pg (~> 1.5.3)
pry (~> 0.14.2)
- rack (~> 2.2.7)
+ rack (~> 2.2.8)
rack-utf8_sanitizer (~> 1.9.0)
rails (~> 7.0.6)
rails-controller-testing
From 86f1178a19b627f8f01db27d14c2b46a2fc32b49 Mon Sep 17 00:00:00 2001
From: Graeme Porteous
Date: Tue, 28 Mar 2023 21:59:46 +0100
Subject: [PATCH 127/265] Refactor attachment controller specs
Combined lets and variables for `info_request`, `incoming_message` and
`attachment` so that they are declared once per context.
This is so we can make changes easier to all specs. For example, this
will be useful for, adding a `masked` trait to the `FoiAttachment`
factory. In coming commits we will be updating the controller flow to
work differently if an attachment isn't maksed, adding this trait will
keep the original behaviour and mean we won't need to update specs on
mass.
Also minor refactoring to:
- Use `show` and `show_as_html` action helpers throughout
- Move specs into a single describe block for each action
- Remove blank lines inside describe and context blocks
- Don't wrap describe or it labels
- Fix linting; indentation, string quotes, etc...
---
.../attachments_controller_spec.rb | 994 +++++++-----------
spec/factories/foi_attchments.rb | 2 +
2 files changed, 388 insertions(+), 608 deletions(-)
diff --git a/spec/controllers/attachments_controller_spec.rb b/spec/controllers/attachments_controller_spec.rb
index 61c83a2235..3fc6f04036 100644
--- a/spec/controllers/attachments_controller_spec.rb
+++ b/spec/controllers/attachments_controller_spec.rb
@@ -1,46 +1,47 @@
require 'spec_helper'
RSpec.describe AttachmentsController, type: :controller do
-
before do
allow(@controller).to receive(:foi_fragment_cache_write)
end
- describe 'GET show' do
-
- let(:info_request) do
- FactoryBot.create(
- :info_request_with_incoming_attachments, public_token: 'ABC'
- )
- end
-
- let(:default_params) do
- { incoming_message_id: info_request.incoming_messages.first.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf' }
- end
-
- def show(params = {})
- get :show, params: default_params.merge(params)
- end
-
- it 'should be able to find the request using public token' do
- expect(InfoRequest).to receive(:find_by!).with(public_token: 'ABC').
- and_return(info_request)
+ let(:request_prominence) { 'normal' }
+ let(:message_prominence) { 'normal' }
+ let(:attachment_prominence) { 'normal' }
- show(public_token: 'ABC', id: nil)
+ let(:info_request) do
+ FactoryBot.create(:info_request, prominence: request_prominence)
+ end
- expect(assigns(:info_request)).to eq(info_request)
- end
+ let(:message) do
+ FactoryBot.create(
+ :incoming_message,
+ info_request: info_request,
+ prominence: message_prominence
+ )
+ end
- it 'adds noindex header when using public token' do
- expect(InfoRequest).to receive(:find_by!).with(public_token: 'ABC').
- and_return(info_request)
+ let(:attachment) do
+ FactoryBot.create(
+ :body_text, incoming_message: message, prominence: attachment_prominence
+ )
+ end
- show(public_token: 'ABC', id: nil)
+ def expect_hidden(hidden_template)
+ expect(response.media_type).to eq('text/html')
+ expect(response).to render_template(hidden_template)
+ expect(response.code).to eq('403')
+ end
- expect(response.headers['X-Robots-Tag']).to eq 'noindex'
+ describe 'GET show' do
+ def show(params = {})
+ default_params = {
+ incoming_message_id: message.id,
+ part: attachment.url_part_number,
+ file_name: attachment.display_filename
+ }
+ default_params[:id] = info_request.id unless params[:public_token]
+ get :show, params: default_params.merge(params)
end
it 'should cache an attachment on a request with normal prominence' do
@@ -57,160 +58,146 @@ def show(params = {})
# check the file permissions
key_path = @controller.send(:cache_key_path)
- octal_stat = format("%o", File.stat(key_path).mode)[-4..-1]
+ octal_stat = format('%o', File.stat(key_path).mode)[-4..-1]
expect(octal_stat).to eq('0644')
# clean up and remove the file
File.delete(key_path)
end
- # This is a regression test for a bug where URLs of this form were causing 500 errors
- # instead of 404s.
+ # This is a regression test for a bug where URLs of this form were causing
+ # 500 errors instead of 404s.
#
- # (Note that in fact only the integer-prefix of the URL part is used, so there are
- # *some* “ugly URLs containing a request id that isn't an integer” that actually return
- # a 200 response. The point is that IDs of this sort were triggering an error in the
- # error-handling path, causing the wrong sort of error response to be returned in the
- # case where the integer prefix referred to the wrong request.)
+ # (Note that in fact only the integer-prefix of the URL part is used, so
+ # there are *some* “ugly URLs containing a request id that isn\'t an
+ # integer” that actually return a 200 response. The point is that IDs of
+ # this sort were triggering an error in the error-handling path, causing
+ # the wrong sort of error response to be returned in the case where the
+ # integer prefix referred to the wrong request.)
#
# https://github.com/mysociety/alaveteli/issues/351
- it "should return 404 for ugly URLs containing a request id that isn't an integer" do
- ugly_id = "55195"
+ it 'should return 404 for ugly URLs containing a request id that isn\'t an integer' do
+ ugly_id = '55195'
expect { show(id: ugly_id) }
.to raise_error(ActiveRecord::RecordNotFound)
end
- it "should return 404 when incoming message and request ids
- don't match" do
+ it 'should return 404 when incoming message and request ids don\'t match' do
expect { show(id: info_request.id + 1) }
.to raise_error(ActiveRecord::RecordNotFound)
end
- it "should return 404 for ugly URLs contain a request id that isn't an
- integer, even if the integer prefix refers to an actual request" do
- ugly_id = "#{FactoryBot.create(:info_request).id}95"
+ it 'should return 404 for ugly URLs contain a request id that isn\'t an integer, even if the integer prefix refers to an actual request' do
+ ugly_id = '#{FactoryBot.create(:info_request).id}95'
expect { show(id: ugly_id) }
.to raise_error(ActiveRecord::RecordNotFound)
end
- it "should redirect to the incoming message if there's a wrong part number
- and an ambiguous filename" do
- incoming_message = info_request.incoming_messages.first
- attachment = IncomingMessage.
- get_attachment_by_url_part_number_and_filename!(
- incoming_message.get_attachments_for_display,
- 5,
- 'interesting.pdf'
- )
- expect(attachment).to be_nil
- show(part: 5)
+ it 'should redirect to the incoming message if there\'s a wrong part number and an ambiguous filename' do
+ show(
+ part: attachment.url_part_number + 1,
+ file_name: 'invalid-#{attachment.display_filename}'
+ )
expect(response.status).to eq(303)
- new_location = response.header['Location']
- expect(new_location)
- .to match incoming_message_path(incoming_message)
- end
-
- it "should find a uniquely named filename even if the URL part number was wrong" do
- info_request = FactoryBot.create(:info_request_with_html_attachment)
- get :show,
- params: {
- incoming_message_id: info_request.incoming_messages.first.id,
- id: info_request.id,
- part: 5,
- file_name: 'interesting.html',
- skip_cache: 1
- }
- expect(response.body).to match('dull')
- end
-
- it "should not download attachments with wrong file name" do
- info_request = FactoryBot.create(:info_request_with_html_attachment)
- get :show,
- params: {
- incoming_message_id: info_request.incoming_messages.first.id,
- id: info_request.id,
- part: 2,
- file_name: 'http://trying.to.hack',
- skip_cache: 1
- }
+ expect(response).to redirect_to(incoming_message_path(message))
+ end
+
+ it 'should find a uniquely named filename even if the URL part number was wrong' do
+ show(part: 5)
+ expect(response.body).to match('hereisthetext')
+ end
+
+ it 'should not download attachments with wrong file name' do
+ show(file_name: 'http://trying.to.hack')
expect(response.status).to eq(303)
end
- it "should sanitise HTML attachments" do
- info_request = FactoryBot.create(:info_request_with_html_attachment)
- get :show,
- params: {
- incoming_message_id: info_request.incoming_messages.first.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.html',
- skip_cache: 1
- }
-
- # Nokogiri adds the meta tag; see
- # https://github.com/sparklemotion/nokogiri/issues/1008
- expected = <<-EOF.squish
-
-
-
-
-
- dull
-
-
- EOF
-
- expect(response.body.squish).to eq(expected)
- end
-
- it "censors attachments downloaded directly" do
- info_request = FactoryBot.create(:info_request_with_html_attachment)
- info_request.censor_rules.create!(text: 'dull',
- replacement: "Mouse",
- last_edit_editor: 'unknown',
- last_edit_comment: 'none')
- get :show,
- params: {
- incoming_message_id: info_request.incoming_messages.first.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.html',
- skip_cache: 1
- }
- expect(response.media_type).to eq('text/html')
- expect(response.body).to have_content "Mouse"
- end
-
- it "should censor with rules on the user (rather than the request)" do
- info_request = FactoryBot.create(:info_request_with_html_attachment)
- info_request.user.censor_rules.create!(text: 'dull',
- replacement: "Mouse",
- last_edit_editor: 'unknown',
- last_edit_comment: 'none')
- get :show,
- params: {
- incoming_message_id: info_request.incoming_messages.first.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.html',
- skip_cache: 1
- }
- expect(response.media_type).to eq('text/html')
- expect(response.body).to have_content "Mouse"
- end
-
- it 'returns an ActiveRecord::RecordNotFound error for an embargoed request' do
- info_request = FactoryBot.create(:embargoed_request)
- expect {
- get :show,
- params: {
- incoming_message_id: info_request.incoming_messages.first.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf',
- skip_cache: 1
- }
- }.to raise_error ActiveRecord::RecordNotFound
+ context 'when attachment is a HTML file' do
+ let(:attachment) do
+ FactoryBot.create(
+ :html_attachment,
+ incoming_message: message,
+ prominence: attachment_prominence
+ )
+ end
+
+ it 'should sanitise the output' do
+ show
+
+ # Nokogiri adds the meta tag; see
+ # https://github.com/sparklemotion/nokogiri/issues/1008
+ expected = <<-EOF.squish
+
+
+
+
+
+ dull
+
+
+ EOF
+
+ expect(response.body.squish).to eq(expected)
+ end
+ end
+
+ it 'censors attachments downloaded directly' do
+ info_request.censor_rules.create!(
+ text: 'hereisthetext', replacement: 'Mouse',
+ last_edit_editor: 'unknown', last_edit_comment: 'none'
+ )
+ show
+ expect(response.media_type).to eq('text/plain')
+ expect(response.body).to have_content 'Mouse'
+ end
+
+ it 'should censor with rules on the user (rather than the request)' do
+ info_request.user.censor_rules.create!(
+ text: 'hereisthetext', replacement: 'Mouse',
+ last_edit_editor: 'unknown', last_edit_comment: 'none'
+ )
+ show
+ expect(response.media_type).to eq('text/plain')
+ expect(response.body).to have_content 'Mouse'
+ end
+
+ context 'when request is embargoed' do
+ let(:info_request) { FactoryBot.create(:embargoed_request) }
+
+ it 'returns an ActiveRecord::RecordNotFound error for an embargoed request' do
+ expect { show }.to raise_error ActiveRecord::RecordNotFound
+ end
+ end
+
+ context 'when request is embargoed but shared with public token' do
+ let(:info_request) do
+ FactoryBot.create(:info_request, :embargoed, public_token: 'ABC')
+ end
+
+ it 'should be able to find the request using public token' do
+ expect(InfoRequest).to receive(:find_by!).with(public_token: 'ABC').
+ and_return(info_request)
+
+ show(public_token: 'ABC', id: nil)
+
+ expect(assigns(:info_request)).to eq(info_request)
+ end
+
+ it 'adds noindex header when using public token' do
+ expect(InfoRequest).to receive(:find_by!).with(public_token: 'ABC').
+ and_return(info_request)
+
+ show(public_token: 'ABC', id: nil)
+
+ expect(response.headers['X-Robots-Tag']).to eq 'noindex'
+ end
+
+ it 'passes public token to current ability' do
+ expect(Ability).to receive(:new).with(
+ nil, project: nil, public_token: true
+ ).and_call_original
+ show(public_token: 'ABC', id: nil)
+ end
end
context 'with project_id params and logged in project member' do
@@ -257,508 +244,299 @@ def show(params = {})
end
end
- context 'with public_token params and logged out' do
- it 'passes project to current ability' do
- expect(Ability).to receive(:new).with(
- nil, project: nil, public_token: true
- ).and_call_original
- show(public_token: 'ABC')
+ context 'when the request is hidden' do
+ let(:request_prominence) { 'hidden' }
+
+ it 'does not download attachments' do
+ show
+ expect_hidden('request/hidden')
end
end
- end
- describe 'GET show_as_html' do
- let(:info_request) { FactoryBot.create(:info_request_with_incoming_attachments) }
+ context 'when the request is requester_only' do
+ let(:request_prominence) { 'requester_only' }
- def get_html_attachment(params = {})
- default_params = { incoming_message_id: info_request.incoming_messages.first.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf.html' }
- get :show_as_html, params: default_params.merge(params)
+ it 'does not cache an attachment when showing an attachment to the requester' do
+ sign_in info_request.user
+ expect(@controller).not_to receive(:foi_fragment_cache_write)
+ show
+ end
+
+ it 'does not cache an attachment when showing an attachment to the admin' do
+ sign_in FactoryBot.create(:admin_user)
+ expect(@controller).not_to receive(:foi_fragment_cache_write)
+ show
+ end
end
- it 'should be able to find the request using public token' do
- expect(InfoRequest).to receive(:find_by!).with(public_token: '123').
- and_return(info_request)
+ context 'when the request is backpage' do
+ let(:request_prominence) { 'backpage' }
- get_html_attachment(public_token: '123', id: nil)
+ it 'sets a noindex header when viewing' do
+ show
+ expect(response.headers['X-Robots-Tag']).to eq 'noindex'
+ end
- expect(assigns(:info_request)).to eq(info_request)
- end
+ it 'sets a noindex header when viewing a cached copy' do
+ show
+ expect(response.headers['X-Robots-Tag']).to eq 'noindex'
+ end
- it 'adds noindex header when using public token' do
- expect(InfoRequest).to receive(:find_by!).with(public_token: '123').
- and_return(info_request)
+ context 'when logged in as requester' do
+ before { sign_in info_request.user }
- get_html_attachment(public_token: '123', id: nil)
+ it 'attachment is viewable' do
+ show
+ expect(response.body).to include('hereisthetext')
+ end
- expect(response.headers['X-Robots-Tag']).to eq 'noindex'
+ it 'does not cache an attachment' do
+ expect(@controller).not_to receive(:foi_fragment_cache_write)
+ show
+ end
+ end
end
- it "should return 404 for ugly URLs containing a request id that isn't an integer" do
- ugly_id = "55195"
- expect { get_html_attachment(id: ugly_id) }
- .to raise_error(ActiveRecord::RecordNotFound)
- end
+ context 'when the incoming message has prominence hidden' do
+ let(:message_prominence) { 'hidden' }
- it "should return 404 for ugly URLs contain a request id that isn't an
- integer, even if the integer prefix refers to an actual request" do
- ugly_id = "#{FactoryBot.create(:info_request).id}95"
- expect { get_html_attachment(id: ugly_id) }
- .to raise_error(ActiveRecord::RecordNotFound)
- end
+ it 'does not download attachments for a non-logged in user' do
+ show
+ expect_hidden('request/hidden_correspondence')
+ end
+
+ it 'does not download attachments for the request owner' do
+ sign_in info_request.user
+ show
+ expect_hidden('request/hidden_correspondence')
+ end
- it 'returns an ActiveRecord::RecordNotFound error for an embargoed request' do
- info_request = FactoryBot.create(:embargoed_request)
- expect {
- get :show_as_html,
- params: {
- incoming_message_id: info_request.incoming_messages.first.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf.html'
- }
- }.to raise_error ActiveRecord::RecordNotFound
+ it 'downloads attachments for an admin user' do
+ sign_in FactoryBot.create(:admin_user)
+ show
+ expect(response.media_type).to eq('text/plain')
+ expect(response).to be_successful
+ end
+
+ it 'does not cache an attachment when showing an attachment to the requester' do
+ sign_in info_request.user
+ expect(@controller).not_to receive(:foi_fragment_cache_write)
+ show
+ end
+
+ it 'does not cache an attachment when showing an attachment to the admin' do
+ sign_in FactoryBot.create(:admin_user)
+ expect(@controller).not_to receive(:foi_fragment_cache_write)
+ show
+ end
end
- end
+ context 'when the incoming message has prominence requester_only' do
+ let(:message_prominence) { 'requester_only' }
-end
+ it 'does not download attachments for a non-logged in user' do
+ show
+ expect_hidden('request/hidden_correspondence')
+ end
-RSpec.describe AttachmentsController, 'when handling prominence',
- type: :controller do
+ it 'downloads attachments for the request owner' do
+ sign_in info_request.user
+ show
+ expect(response.media_type).to eq('text/plain')
+ expect(response).to be_successful
+ end
- def expect_hidden(hidden_template)
- expect(response.media_type).to eq('text/html')
- expect(response).to render_template(hidden_template)
- expect(response.code).to eq('403')
- end
+ it 'downloads attachments for an admin user' do
+ sign_in FactoryBot.create(:admin_user)
+ show
+ expect(response.media_type).to eq('text/plain')
+ expect(response).to be_successful
+ end
+ end
- let(:info_request) do
- FactoryBot.
- create(:info_request_with_incoming_attachments, prominence: prominence)
- end
+ context 'when the attachment has prominence hidden' do
+ let(:attachment_prominence) { 'hidden' }
- let(:incoming_message) do
- FactoryBot.create(:incoming_message_with_attachments,
- prominence: prominence)
- end
+ it 'does not download attachments for a non-logged in user' do
+ show
+ expect_hidden('request/hidden_attachment')
+ end
- let(:attachment) do
- FactoryBot.create(:pdf_attachment,
- prominence: prominence,
- incoming_message: FactoryBot.build(:incoming_message))
- end
+ it 'does not download attachments for the request owner' do
+ sign_in info_request.user
+ show
+ expect_hidden('request/hidden_attachment')
+ end
- context 'when the request is hidden' do
- let(:prominence) { 'hidden' }
- let(:incoming_message) { info_request.incoming_messages.first }
-
- it 'does not download attachments' do
- get :show,
- params: {
- incoming_message_id: incoming_message.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf',
- skip_cache: 1
- }
- expect_hidden('request/hidden')
- end
-
- it 'does not generate an HTML version of an attachment for a request whose prominence is hidden even for an admin but should return a 404' do
- sign_in FactoryBot.create(:admin_user)
- expect do
- get :show_as_html,
- params: {
- incoming_message_id: incoming_message.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf'
- }
- end.to raise_error(ActiveRecord::RecordNotFound)
+ it 'downloads attachments for an admin user' do
+ sign_in FactoryBot.create(:admin_user)
+ show
+ expect(response.media_type).to eq('text/plain')
+ expect(response).to be_successful
+ end
+
+ it 'does not cache an attachment when showing an attachment to the requester' do
+ sign_in info_request.user
+ expect(@controller).not_to receive(:foi_fragment_cache_write)
+ show
+ end
+
+ it 'does not cache an attachment when showing an attachment to the admin' do
+ sign_in FactoryBot.create(:admin_user)
+ expect(@controller).not_to receive(:foi_fragment_cache_write)
+ show
+ end
end
- end
+ context 'when the attachment has prominence requester_only' do
+ let(:attachment_prominence) { 'requester_only' }
- context 'when the request is requester_only' do
- let(:prominence) { 'requester_only' }
- let(:incoming_message) { info_request.incoming_messages.first }
-
- it 'does not cache an attachment when showing an attachment to the requester' do
- sign_in info_request.user
- expect(@controller).not_to receive(:foi_fragment_cache_write)
- get :show,
- params: {
- incoming_message_id: incoming_message.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf'
- }
- end
-
- it 'does not cache an attachment when showing an attachment to the admin' do
- sign_in FactoryBot.create(:admin_user)
- expect(@controller).not_to receive(:foi_fragment_cache_write)
- get :show,
- params: {
- incoming_message_id: incoming_message.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf'
- }
+ it 'does not download attachments for a non-logged in user' do
+ show
+ expect_hidden('request/hidden_attachment')
+ end
+
+ it 'downloads attachments for the request owner' do
+ sign_in info_request.user
+ show
+ expect(response.media_type).to eq('text/plain')
+ expect(response).to be_successful
+ end
+
+ it 'downloads attachments for an admin user' do
+ sign_in FactoryBot.create(:admin_user)
+ show
+ expect(response.media_type).to eq('text/plain')
+ expect(response).to be_successful
+ end
end
end
- context 'when the request is backpage' do
- let(:prominence) { 'backpage' }
- let(:incoming_message) { info_request.incoming_messages.first }
-
- it 'sets a noindex header when viewing' do
- get :show,
- params: {
- incoming_message_id: incoming_message.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf',
- skip_cache: 1
- }
- expect(response.headers['X-Robots-Tag']).to eq 'noindex'
+ describe 'GET show_as_html' do
+ def show_as_html(params = {})
+ default_params = {
+ incoming_message_id: message.id,
+ part: attachment.url_part_number,
+ file_name: attachment.display_filename
+ }
+ default_params[:id] = info_request.id unless params[:public_token]
+ get :show_as_html, params: default_params.merge(params)
end
- it 'sets a noindex header when viewing a cached copy' do
- get :show,
- params: {
- incoming_message_id: incoming_message.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf'
- }
- expect(response.headers['X-Robots-Tag']).to eq 'noindex'
+ it 'should be able to find the request using public token' do
+ expect(InfoRequest).to receive(:find_by!).with(public_token: '123').
+ and_return(info_request)
+
+ show_as_html(public_token: '123', id: nil)
+
+ expect(assigns(:info_request)).to eq(info_request)
end
- it 'sets a noindex header when viewing a HTML version' do
- get :show_as_html,
- params: {
- incoming_message_id: incoming_message.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf',
- skip_cache: 1
- }
+ it 'adds noindex header when using public token' do
+ expect(InfoRequest).to receive(:find_by!).with(public_token: '123').
+ and_return(info_request)
+
+ show_as_html(public_token: '123', id: nil)
+
expect(response.headers['X-Robots-Tag']).to eq 'noindex'
end
- it 'sets a noindex header when viewing a cached HTML version' do
- get :show_as_html,
- params: {
- incoming_message_id: incoming_message.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf'
- }
- expect(response.headers['X-Robots-Tag']).to eq 'noindex'
+ it 'should return 404 for ugly URLs containing a request id that isn\'t an integer' do
+ ugly_id = '55195'
+ expect { show_as_html(id: ugly_id) }
+ .to raise_error(ActiveRecord::RecordNotFound)
end
- it 'does not cache an attachment' do
- sign_in info_request.user
- expect(@controller).not_to receive(:foi_fragment_cache_write)
- get :show,
- params: {
- incoming_message_id: incoming_message.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf'
- }
+ it 'should return 404 for ugly URLs contain a request id that isn\'t an integer, even if the integer prefix refers to an actual request' do
+ ugly_id = FactoryBot.create(:info_request).id.to_s + '95'
+ expect { show_as_html(id: ugly_id) }
+ .to raise_error(ActiveRecord::RecordNotFound)
end
- end
- context 'when the incoming message has prominence hidden' do
- let(:prominence) { 'hidden' }
- let(:info_request) { incoming_message.info_request }
-
- it 'does not download attachments for a non-logged in user' do
- get :show,
- params: {
- incoming_message_id: incoming_message.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf',
- skip_cache: 1
- }
- expect_hidden('request/hidden_correspondence')
- end
-
- it 'does not download attachments for the request owner' do
- sign_in info_request.user
- get :show,
- params: {
- incoming_message_id: incoming_message.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf',
- skip_cache: 1
- }
- expect_hidden('request/hidden_correspondence')
- end
-
- it 'downloads attachments for an admin user' do
- sign_in FactoryBot.create(:admin_user)
- get :show,
- params: {
- incoming_message_id: incoming_message.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf',
- skip_cache: 1
- }
- expect(response.media_type).to eq('application/pdf')
- expect(response).to be_successful
- end
-
- it 'should not generate an HTML version of an attachment for a request whose prominence is hidden even for an admin but should return a 404' do
- sign_in FactoryBot.create(:admin_user)
- expect do
- get :show_as_html,
- params: {
- incoming_message_id: incoming_message.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf',
- skip_cache: 1
- }
- end.to raise_error(ActiveRecord::RecordNotFound)
- end
-
- it 'does not cache an attachment when showing an attachment to the requester or admin' do
- sign_in info_request.user
- expect(@controller).not_to receive(:foi_fragment_cache_write)
- get :show,
- params: {
- incoming_message_id: incoming_message.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf'
- }
+ context 'when request is embargoed' do
+ let(:info_request) { FactoryBot.create(:embargoed_request) }
+
+ it 'returns an ActiveRecord::RecordNotFound error' do
+ expect { show_as_html }.to raise_error(ActiveRecord::RecordNotFound)
+ end
end
- end
- context 'when the incoming message has prominence requester_only' do
- let(:prominence) { 'requester_only' }
- let(:info_request) { incoming_message.info_request }
-
- it 'does not download attachments for a non-logged in user' do
- get :show,
- params: {
- incoming_message_id: incoming_message.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf',
- skip_cache: 1
- }
- expect_hidden('request/hidden_correspondence')
- end
-
- it 'downloads attachments for the request owner' do
- sign_in info_request.user
- get :show,
- params: {
- incoming_message_id: incoming_message.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf',
- skip_cache: 1
- }
- expect(response.media_type).to eq('application/pdf')
- expect(response).to be_successful
- end
-
- it 'downloads attachments for an admin user' do
- sign_in FactoryBot.create(:admin_user)
- get :show,
- params: {
- incoming_message_id: incoming_message.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf',
- skip_cache: 1
- }
- expect(response.media_type).to eq('application/pdf')
- expect(response).to be_successful
- end
-
- it 'should not generate an HTML version of an attachment for a request whose prominence is hidden even for an admin but should return a 404' do
- sign_in FactoryBot.create(:admin_user)
- expect do
- get :show_as_html,
- params: {
- incoming_message_id: incoming_message.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf',
- skip_cache: 1
- }
- end.to raise_error(ActiveRecord::RecordNotFound)
+ context 'when attachment has a long filename' do
+ let(:long_name) { 'blah' * 150 + '.pdf' }
+
+ let(:attachment) do
+ FactoryBot.create(
+ :pdf_attachment, filename: long_name, incoming_message: message
+ )
+ end
+
+ it 'should be successful' do
+ show_as_html(file_name: long_name)
+ expect(response).to be_successful
+ end
end
- end
- context 'when the attachment has prominence hidden' do
- let(:prominence) { 'hidden' }
- let(:info_request) { incoming_message.info_request }
- let(:incoming_message) { attachment.incoming_message }
-
- it 'does not download attachments for a non-logged in user' do
- get :show,
- params: {
- incoming_message_id: incoming_message.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf',
- skip_cache: 1
- }
- expect_hidden('request/hidden_attachment')
- end
-
- it 'does not download attachments for the request owner' do
- sign_in info_request.user
- get :show,
- params: {
- incoming_message_id: incoming_message.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf',
- skip_cache: 1
- }
- expect_hidden('request/hidden_attachment')
- end
-
- it 'downloads attachments for an admin user' do
- sign_in FactoryBot.create(:admin_user)
- get :show,
- params: {
- incoming_message_id: incoming_message.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf',
- skip_cache: 1
- }
- expect(response.media_type).to eq('application/pdf')
- expect(response).to be_successful
- end
-
- it 'should not generate an HTML version of an attachment whose prominence is hidden even for an admin but should return a 404' do
- sign_in FactoryBot.create(:admin_user)
- expect do
- get :show_as_html,
- params: {
- incoming_message_id: incoming_message.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf',
- skip_cache: 1
- }
- end.to raise_error(ActiveRecord::RecordNotFound)
- end
-
- it 'does not cache an attachment when showing an attachment to the requester or admin' do
- sign_in info_request.user
- expect(@controller).not_to receive(:foi_fragment_cache_write)
- get :show,
- params: {
- incoming_message_id: incoming_message.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf'
- }
+ context 'when the request is hidden' do
+ let(:request_prominence) { 'hidden' }
+
+ it 'does not generate an HTML version of an attachment for a request whose prominence is hidden even for an admin but should return a 404' do
+ sign_in FactoryBot.create(:admin_user)
+ expect { show_as_html }.to raise_error(ActiveRecord::RecordNotFound)
+ end
end
- end
- context 'when the attachment has prominence requester_only' do
- let(:prominence) { 'requester_only' }
- let(:info_request) { incoming_message.info_request }
- let(:incoming_message) { attachment.incoming_message }
-
- it 'does not download attachments for a non-logged in user' do
- get :show,
- params: {
- incoming_message_id: incoming_message.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf',
- skip_cache: 1
- }
- expect_hidden('request/hidden_attachment')
- end
-
- it 'downloads attachments for the request owner' do
- sign_in info_request.user
- get :show,
- params: {
- incoming_message_id: incoming_message.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf',
- skip_cache: 1
- }
- expect(response.media_type).to eq('application/pdf')
- expect(response).to be_successful
- end
-
- it 'downloads attachments for an admin user' do
- sign_in FactoryBot.create(:admin_user)
- get :show,
- params: {
- incoming_message_id: incoming_message.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf',
- skip_cache: 1
- }
- expect(response.media_type).to eq('application/pdf')
- expect(response).to be_successful
- end
-
- it 'should not generate an HTML version of an attachment whose prominence is hidden even for an admin but should return a 404' do
- sign_in FactoryBot.create(:admin_user)
- expect do
- get :show_as_html,
- params: {
- incoming_message_id: incoming_message.id,
- id: info_request.id,
- part: 2,
- file_name: 'interesting.pdf',
- skip_cache: 1
- }
- end.to raise_error(ActiveRecord::RecordNotFound)
+ context 'when the request is requester_only' do
+ let(:request_prominence) { 'requester_only' }
end
- end
-end
-RSpec.describe AttachmentsController, "when caching fragments",
- type: :controller do
+ context 'when the request is backpage' do
+ let(:request_prominence) { 'backpage' }
- let(:info_request) { FactoryBot.create(:info_request_with_incoming) }
- let(:incoming_message) { info_request.incoming_messages.first }
+ it 'sets a noindex header when viewing a HTML version' do
+ show_as_html
+ expect(response.headers['X-Robots-Tag']).to eq 'noindex'
+ end
- it "should not fail with long filenames" do
- long_name = 'blah' * 150 + '.pdf'
+ it 'sets a noindex header when viewing a cached HTML version' do
+ show_as_html
+ expect(response.headers['X-Robots-Tag']).to eq 'noindex'
+ end
+ end
- attachment = FactoryBot.create(:pdf_attachment,
- filename: long_name,
- incoming_message: incoming_message,
- url_part_number: 2)
+ context 'when the incoming message has prominence hidden' do
+ let(:message_prominence) { 'hidden' }
- params = { file_name: long_name,
- controller: 'request',
- action: 'show_as_html',
- id: info_request.id,
- incoming_message_id: incoming_message.id,
- part: '2' }
+ it 'should not generate an HTML version of an attachment for a request whose prominence is hidden even for an admin but should return a 404' do
+ sign_in FactoryBot.create(:admin_user)
+ expect { show_as_html }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
- get :show_as_html, params: params
+ context 'when the incoming message has prominence requester_only' do
+ let(:message_prominence) { 'requester_only' }
- expect(response).to be_successful
- end
+ it 'should not generate an HTML version of an attachment for a request whose prominence is hidden even for an admin but should return a 404' do
+ sign_in FactoryBot.create(:admin_user)
+ expect { show_as_html }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+ context 'when the attachment has prominence hidden' do
+ let(:attachment_prominence) { 'hidden' }
+
+ it 'should not generate an HTML version of an attachment whose prominence is hidden even for an admin but should return a 404' do
+ sign_in FactoryBot.create(:admin_user)
+ expect { show_as_html }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+
+ context 'when the attachment has prominence requester_only' do
+ let(:attachment_prominence) { 'requester_only' }
+
+ it 'should not generate an HTML version of an attachment whose prominence is hidden even for an admin but should return a 404' do
+ sign_in FactoryBot.create(:admin_user)
+ expect { show_as_html }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+ end
end
diff --git a/spec/factories/foi_attchments.rb b/spec/factories/foi_attchments.rb
index 69fc82a6c2..888928b8a3 100644
--- a/spec/factories/foi_attchments.rb
+++ b/spec/factories/foi_attchments.rb
@@ -1,6 +1,8 @@
FactoryBot.define do
factory :foi_attachment do
+ sequence(:url_part_number) { |n| n + 1 }
+
factory :body_text do
content_type { 'text/plain' }
body { 'hereisthetext' }
From bcfaeebb56f11f33ea2e61571be23b4934ef979c Mon Sep 17 00:00:00 2001
From: Graeme Porteous
Date: Tue, 28 Mar 2023 01:40:42 +0100
Subject: [PATCH 128/265] Active Job uniqueness
Being able to ensure the same job isn't being worked on at the same time
more than once will be useful. For example attachment processing doesn't
need to happen more than once every time a censor rule is created or
updated.
---
Gemfile | 1 +
Gemfile.lock | 6 +++++
config/initializers/active_job_uniqueness.rb | 5 ++++
config/initializers/sidekiq.rb | 23 +++-------------
lib/redis_connection.rb | 28 ++++++++++++++++++++
5 files changed, 43 insertions(+), 20 deletions(-)
create mode 100644 config/initializers/active_job_uniqueness.rb
create mode 100644 lib/redis_connection.rb
diff --git a/Gemfile b/Gemfile
index 84157b80bf..4318e19a79 100644
--- a/Gemfile
+++ b/Gemfile
@@ -87,6 +87,7 @@ gem 'pg', '~> 1.5.3'
gem 'acts_as_versioned', git: 'https://github.com/mysociety/acts_as_versioned.git',
ref: '13e928b'
gem 'active_model_otp'
+gem 'activejob-uniqueness'
gem 'bcrypt', '~> 3.1.19'
gem 'cancancan', '~> 3.5.0'
gem 'charlock_holmes', '~> 0.7.7'
diff --git a/Gemfile.lock b/Gemfile.lock
index a607009f26..03163ad3cb 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -105,6 +105,9 @@ GEM
activejob (7.0.6)
activesupport (= 7.0.6)
globalid (>= 0.3.6)
+ activejob-uniqueness (0.2.5)
+ activejob (>= 4.2, < 7.1)
+ redlock (>= 1.2, < 2)
activemodel (7.0.6)
activesupport (= 7.0.6)
activerecord (7.0.6)
@@ -417,6 +420,8 @@ GEM
rake (13.0.6)
recaptcha (5.14.0)
redis (4.8.1)
+ redlock (1.3.2)
+ redis (>= 3.0.0, < 6.0)
regexp_parser (2.8.1)
representable (3.2.0)
declarative (< 0.1.0)
@@ -560,6 +565,7 @@ PLATFORMS
DEPENDENCIES
active_model_otp
+ activejob-uniqueness
acts_as_versioned!
alaveteli_features!
annotate (< 3.2.1)
diff --git a/config/initializers/active_job_uniqueness.rb b/config/initializers/active_job_uniqueness.rb
new file mode 100644
index 0000000000..d4a9cc5399
--- /dev/null
+++ b/config/initializers/active_job_uniqueness.rb
@@ -0,0 +1,5 @@
+require 'redis_connection'
+
+ActiveJob::Uniqueness.configure do |config|
+ config.redlock_servers = [RedisConnection.instance]
+end
diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb
index 171e7d8c8e..11f1fef025 100644
--- a/config/initializers/sidekiq.rb
+++ b/config/initializers/sidekiq.rb
@@ -1,26 +1,9 @@
-require File.expand_path('../load_env.rb', __dir__)
-
-def redis_config
- { url: ENV['REDIS_URL'], password: ENV['REDIS_PASSWORD'] }.
- merge(redis_sentinel_config)
-end
-
-def redis_sentinel_config
- return {} unless ENV['REDIS_SENTINELS']
-
- sentinels = ENV['REDIS_SENTINELS'].split(',').map do |ip_and_port|
- ip, port = ip_and_port.split(/:(\d+)$/)
- ip = Regexp.last_match[1] if ip =~ /\[(.*?)\]/
- { host: ip, port: port&.to_i || 26_379 }
- end
-
- { sentinels: sentinels, role: :master }
-end
+require 'redis_connection'
Sidekiq.configure_client do |config|
- config.redis = redis_config
+ config.redis = RedisConnection.configuration
end
Sidekiq.configure_server do |config|
- config.redis = redis_config
+ config.redis = RedisConnection.configuration
end
diff --git a/lib/redis_connection.rb b/lib/redis_connection.rb
new file mode 100644
index 0000000000..68ffc53a2c
--- /dev/null
+++ b/lib/redis_connection.rb
@@ -0,0 +1,28 @@
+require File.expand_path('../config/load_env.rb', __dir__)
+
+##
+# Module to parse Redis ENV variables into usable configuration for Sidekiq and
+# ActiveJob::Uniqueness gems.
+#
+module RedisConnection
+ def self.instance
+ Redis.new(configuration)
+ end
+
+ def self.configuration
+ { url: ENV['REDIS_URL'], password: ENV['REDIS_PASSWORD'] }.
+ merge(sentinel_configuration)
+ end
+
+ def self.sentinel_configuration
+ return {} unless ENV['REDIS_SENTINELS']
+
+ sentinels = ENV['REDIS_SENTINELS'].split(',').map do |ip_and_port|
+ ip, port = ip_and_port.split(/:(\d+)$/)
+ ip = Regexp.last_match[1] if ip =~ /\[(.*?)\]/
+ { host: ip, port: port&.to_i || 26_379 }
+ end
+
+ { sentinels: sentinels, role: :master }
+ end
+end
From 9974cf0f3941cde8f4767a2b92f0bf1204faabeb Mon Sep 17 00:00:00 2001
From: Graeme Porteous
Date: Tue, 28 Mar 2023 01:46:35 +0100
Subject: [PATCH 129/265] Add FoiAttachmentMaskJob
Move all logic of censoring an attachment in this new job.
Job is currently performed straight away but this will change coming
commits.
---
app/controllers/attachments_controller.rb | 15 +----
app/jobs/foi_attachment_mask_job.rb | 44 +++++++++++++
.../attachments_controller_spec.rb | 51 ++--------------
spec/jobs/foi_attachment_mask_job_spec.rb | 61 +++++++++++++++++++
4 files changed, 111 insertions(+), 60 deletions(-)
create mode 100644 app/jobs/foi_attachment_mask_job.rb
create mode 100644 spec/jobs/foi_attachment_mask_job_spec.rb
diff --git a/app/controllers/attachments_controller.rb b/app/controllers/attachments_controller.rb
index 0dc2a2b747..9b96410f5c 100644
--- a/app/controllers/attachments_controller.rb
+++ b/app/controllers/attachments_controller.rb
@@ -19,20 +19,7 @@ class AttachmentsController < ApplicationController
around_action :cache_attachments
def show
- # Prevent spam to magic request address. Note that the binary
- # substitution method used depends on the content type
- body = @incoming_message.apply_masks(
- @attachment.default_body,
- @attachment.content_type
- )
-
- if content_type == 'text/html'
- body =
- Loofah.scrub_document(body, :prune).
- to_html(encoding: 'UTF-8').
- try(:html_safe)
- end
-
+ body = FoiAttachmentMaskJob.perform_now(@attachment)
render body: body, content_type: content_type
end
diff --git a/app/jobs/foi_attachment_mask_job.rb b/app/jobs/foi_attachment_mask_job.rb
new file mode 100644
index 0000000000..4bbd08e840
--- /dev/null
+++ b/app/jobs/foi_attachment_mask_job.rb
@@ -0,0 +1,44 @@
+##
+# Job to apply masks and censor rules to FoiAttachment objects. Masked file will
+# be stored as FoiAttachment#file ActiveStorage association.
+#
+# Example:
+# FoiAttachmentMaskJob.perform(FoiAttachment.first)
+#
+class FoiAttachmentMaskJob < ApplicationJob
+ queue_as :default
+ unique :until_and_while_executing, on_conflict: :log
+
+ attr_reader :attachment
+
+ delegate :incoming_message, to: :attachment
+ delegate :info_request, to: :incoming_message
+
+ def perform(attachment)
+ @attachment = attachment
+
+ body = AlaveteliTextMasker.apply_masks(
+ attachment.default_body,
+ attachment.content_type,
+ masks
+ )
+
+ if attachment.content_type == 'text/html'
+ body =
+ Loofah.scrub_document(body, :prune).
+ to_html(encoding: 'UTF-8').
+ try(:html_safe)
+ end
+
+ body
+ end
+
+ private
+
+ def masks
+ {
+ censor_rules: info_request.applicable_censor_rules,
+ masks: info_request.masks
+ }
+ end
+end
diff --git a/spec/controllers/attachments_controller_spec.rb b/spec/controllers/attachments_controller_spec.rb
index 3fc6f04036..8cb5a6c3e4 100644
--- a/spec/controllers/attachments_controller_spec.rb
+++ b/spec/controllers/attachments_controller_spec.rb
@@ -112,53 +112,12 @@ def show(params = {})
expect(response.status).to eq(303)
end
- context 'when attachment is a HTML file' do
- let(:attachment) do
- FactoryBot.create(
- :html_attachment,
- incoming_message: message,
- prominence: attachment_prominence
- )
- end
-
- it 'should sanitise the output' do
- show
-
- # Nokogiri adds the meta tag; see
- # https://github.com/sparklemotion/nokogiri/issues/1008
- expected = <<-EOF.squish
-
-
-
-
-
- dull
-
-
- EOF
-
- expect(response.body.squish).to eq(expected)
- end
- end
-
- it 'censors attachments downloaded directly' do
- info_request.censor_rules.create!(
- text: 'hereisthetext', replacement: 'Mouse',
- last_edit_editor: 'unknown', last_edit_comment: 'none'
- )
- show
- expect(response.media_type).to eq('text/plain')
- expect(response.body).to have_content 'Mouse'
- end
-
- it 'should censor with rules on the user (rather than the request)' do
- info_request.user.censor_rules.create!(
- text: 'hereisthetext', replacement: 'Mouse',
- last_edit_editor: 'unknown', last_edit_comment: 'none'
- )
+ it 'returns body from FoiAttachmentMaskJob' do
+ expect(FoiAttachmentMaskJob).to receive(:perform_now).
+ with(attachment).
+ and_return('Monkey')
show
- expect(response.media_type).to eq('text/plain')
- expect(response.body).to have_content 'Mouse'
+ expect(response.body).to match('Monkey')
end
context 'when request is embargoed' do
diff --git a/spec/jobs/foi_attachment_mask_job_spec.rb b/spec/jobs/foi_attachment_mask_job_spec.rb
new file mode 100644
index 0000000000..ab144bc702
--- /dev/null
+++ b/spec/jobs/foi_attachment_mask_job_spec.rb
@@ -0,0 +1,61 @@
+require 'spec_helper'
+
+RSpec.describe FoiAttachmentMaskJob, type: :job do
+ let(:info_request) { FactoryBot.create(:info_request_with_html_attachment) }
+ let(:incoming_message) { info_request.incoming_messages.first }
+ let(:attachment) { incoming_message.foi_attachments.last }
+ let(:body) { described_class.new.perform(attachment) }
+
+ it 'sanitises HTML attachments' do
+ # Nokogiri adds the meta tag; see
+ # https://github.com/sparklemotion/nokogiri/issues/1008
+ expected = <<-EOF.squish
+
+
+
+
+
+ dull
+
+
+ EOF
+
+ expect(body.squish).to eq(expected)
+ end
+
+ it 'censors attachments downloaded directly' do
+ info_request.censor_rules.create!(
+ text: 'dull', replacement: 'Boy',
+ last_edit_editor: 'unknown', last_edit_comment: 'none'
+ )
+ expect(body).to_not include 'dull'
+ expect(body).to include 'Boy'
+ end
+
+ it 'censors with rules on the user (rather than the request)' do
+ info_request.user.censor_rules.create!(
+ text: 'dull', replacement: 'Mole',
+ last_edit_editor: 'unknown', last_edit_comment: 'none'
+ )
+ expect(body).to_not include 'dull'
+ expect(body).to include 'Mole'
+ end
+
+ it 'censors with rules on the public body (rather than the request)' do
+ info_request.public_body.censor_rules.create!(
+ text: 'dull', replacement: 'Fox',
+ last_edit_editor: 'unknown', last_edit_comment: 'none'
+ )
+ expect(body).to_not include 'dull'
+ expect(body).to include 'Fox'
+ end
+
+ it 'censors with rules globally (rather than the request)' do
+ CensorRule.create!(
+ text: 'dull', replacement: 'Horse',
+ last_edit_editor: 'unknown', last_edit_comment: 'none'
+ )
+ expect(body).to_not include 'dull'
+ expect(body).to include 'Horse'
+ end
+end
From 321dfe97d00f3f9cfe84958bf63cd3f755968b33 Mon Sep 17 00:00:00 2001
From: Graeme Porteous
Date: Wed, 19 Jul 2023 12:55:26 +0100
Subject: [PATCH 130/265] Update attachment masking
Always start with the unmasked attachment body when applying the masks
and censor rules. We're going to make changes which mean
`FoiAttachment#body` will return masked body, fetch this with
`default_body` could result in attachment with old or superseded censor
rules still applied.
Needed to force HTML attachment into CRLF line endings due to an issue
with the mail gem which results in a different hexdigest after
rebuilding the raw emails from a file on disk in the specs.
Once https://github.com/mikel/mail/pull/1512 is merged we can revert the
FoiAttachment factory change.
---
app/jobs/foi_attachment_mask_job.rb | 2 +-
app/models/foi_attachment.rb | 10 ++++++++
lib/mail_handler/backends/mail_backend.rb | 7 ++++++
.../attachments_controller_spec.rb | 1 +
spec/factories/foi_attchments.rb | 9 ++++++-
.../prominence/viewing_raw_attachment_spec.rb | 2 ++
spec/integration/view_request_spec.rb | 2 ++
spec/jobs/foi_attachment_mask_job_spec.rb | 2 ++
.../backends/mail_backend_spec.rb | 25 +++++++++++++++++++
spec/models/foi_attachment_spec.rb | 15 +++++++++++
spec/support/email_helpers.rb | 19 ++++++++++++++
11 files changed, 92 insertions(+), 2 deletions(-)
diff --git a/app/jobs/foi_attachment_mask_job.rb b/app/jobs/foi_attachment_mask_job.rb
index 4bbd08e840..bca6429bbe 100644
--- a/app/jobs/foi_attachment_mask_job.rb
+++ b/app/jobs/foi_attachment_mask_job.rb
@@ -18,7 +18,7 @@ def perform(attachment)
@attachment = attachment
body = AlaveteliTextMasker.apply_masks(
- attachment.default_body,
+ attachment.unmasked_body,
attachment.content_type,
masks
)
diff --git a/app/models/foi_attachment.rb b/app/models/foi_attachment.rb
index e8ac31e8ae..f13367a756 100644
--- a/app/models/foi_attachment.rb
+++ b/app/models/foi_attachment.rb
@@ -32,6 +32,7 @@ class FoiAttachment < ApplicationRecord
belongs_to :incoming_message,
inverse_of: :foi_attachments
+ has_one :raw_email, through: :incoming_message, source: :raw_email
has_one_attached :file, service: :attachments
@@ -123,6 +124,15 @@ def default_body
text_type? ? body_as_text.string : body
end
+ # return the body as it is in the raw email, unmasked without censor rules
+ # applied
+ def unmasked_body
+ MailHandler.attachment_body_for_hexdigest(
+ raw_email.mail,
+ hexdigest: hexdigest
+ )
+ end
+
def main_body_part?
self == incoming_message.get_main_body_text_part
end
diff --git a/lib/mail_handler/backends/mail_backend.rb b/lib/mail_handler/backends/mail_backend.rb
index 9354f9ff88..f20b99a8df 100644
--- a/lib/mail_handler/backends/mail_backend.rb
+++ b/lib/mail_handler/backends/mail_backend.rb
@@ -380,6 +380,13 @@ def get_attachment_attributes(mail)
end
end
+ def attachment_body_for_hexdigest(mail, hexdigest:)
+ attributes = get_attachment_attributes(mail).find do |attrs|
+ attrs[:hexdigest] == hexdigest
+ end
+ attributes&.fetch(:body)
+ end
+
# Format
def address_from_name_and_email(name, email)
unless MySociety::Validate.is_valid_email(email)
diff --git a/spec/controllers/attachments_controller_spec.rb b/spec/controllers/attachments_controller_spec.rb
index 8cb5a6c3e4..6000a8652c 100644
--- a/spec/controllers/attachments_controller_spec.rb
+++ b/spec/controllers/attachments_controller_spec.rb
@@ -41,6 +41,7 @@ def show(params = {})
file_name: attachment.display_filename
}
default_params[:id] = info_request.id unless params[:public_token]
+ rebuild_raw_emails(info_request)
get :show, params: default_params.merge(params)
end
diff --git a/spec/factories/foi_attchments.rb b/spec/factories/foi_attchments.rb
index 888928b8a3..5268c83eb1 100644
--- a/spec/factories/foi_attchments.rb
+++ b/spec/factories/foi_attchments.rb
@@ -21,7 +21,14 @@
factory :html_attachment do
content_type { 'text/html' }
filename { 'interesting.html' }
- body { load_file_fixture('interesting.html') }
+ body {
+ # Needed to force HTML attachment into CRLF line endings due to an issue
+ # with the mail gem which results in a different hexdigest after
+ # rebuilding the raw emails.
+ # Once https://github.com/mikel/mail/pull/1512 is merged we can revert
+ # the FoiAttachment factory change.
+ Mail::Utilities.to_crlf(load_file_fixture('interesting.html'))
+ }
end
factory :jpeg_attachment do
content_type { 'image/jpeg' }
diff --git a/spec/integration/prominence/viewing_raw_attachment_spec.rb b/spec/integration/prominence/viewing_raw_attachment_spec.rb
index fef97f5f0a..a432f31c45 100644
--- a/spec/integration/prominence/viewing_raw_attachment_spec.rb
+++ b/spec/integration/prominence/viewing_raw_attachment_spec.rb
@@ -7,6 +7,8 @@
let(:within_session) do
-> {
+ rebuild_raw_emails(info_request)
+
visit get_attachment_url(
incoming_message_id: attachment.incoming_message_id,
part: attachment.url_part_number,
diff --git a/spec/integration/view_request_spec.rb b/spec/integration/view_request_spec.rb
index 350f1db628..931b1f2f22 100644
--- a/spec/integration/view_request_spec.rb
+++ b/spec/integration/view_request_spec.rb
@@ -41,6 +41,8 @@
info_request = FactoryBot.create(:info_request_with_incoming_attachments)
incoming_message = info_request.incoming_messages.first
attachment_url = "/es/request/#{info_request.id}/response/#{incoming_message.id}/attach/2/interesting.pdf"
+ rebuild_raw_emails(info_request)
+
using_session(non_owner) { visit(attachment_url) }
expect(cache_directories_exist?(info_request)).to be true
diff --git a/spec/jobs/foi_attachment_mask_job_spec.rb b/spec/jobs/foi_attachment_mask_job_spec.rb
index ab144bc702..b916acb11c 100644
--- a/spec/jobs/foi_attachment_mask_job_spec.rb
+++ b/spec/jobs/foi_attachment_mask_job_spec.rb
@@ -6,6 +6,8 @@
let(:attachment) { incoming_message.foi_attachments.last }
let(:body) { described_class.new.perform(attachment) }
+ before { rebuild_raw_emails(info_request) }
+
it 'sanitises HTML attachments' do
# Nokogiri adds the meta tag; see
# https://github.com/sparklemotion/nokogiri/issues/1008
diff --git a/spec/lib/mail_handler/backends/mail_backend_spec.rb b/spec/lib/mail_handler/backends/mail_backend_spec.rb
index 9a161e061d..97c0c12594 100644
--- a/spec/lib/mail_handler/backends/mail_backend_spec.rb
+++ b/spec/lib/mail_handler/backends/mail_backend_spec.rb
@@ -406,4 +406,29 @@
to eq(['aperson@domain.abc'])
end
end
+
+ describe 'attachment_body_for_hexdigest' do
+ let(:mail) do
+ Mail.new do
+ add_file filename: 'file.txt', content: 'hereisthetext'
+ end
+ end
+
+ context 'matching hexdigest' do
+ it 'returns the body of the attachment' do
+ body = attachment_body_for_hexdigest(
+ mail, hexdigest: Digest::MD5.hexdigest('hereisthetext')
+ )
+
+ expect(body).to eq('hereisthetext')
+ end
+ end
+
+ context 'non-matching hexdigest' do
+ it 'returns nil' do
+ body = attachment_body_for_hexdigest(mail, hexdigest: 'incorrect')
+ expect(body).to be_nil
+ end
+ end
+ end
end
diff --git a/spec/models/foi_attachment_spec.rb b/spec/models/foi_attachment_spec.rb
index a9555a84dc..c6b6bf3221 100644
--- a/spec/models/foi_attachment_spec.rb
+++ b/spec/models/foi_attachment_spec.rb
@@ -144,6 +144,21 @@
end
+ describe '#unmasked_body' do
+
+ it 'returns the attachment body from the raw email' do
+ foi_attachment = FactoryBot.build(:body_text)
+
+ allow(foi_attachment).to receive(:raw_email).
+ and_return(double.as_null_object)
+ allow(MailHandler).to receive(:attachment_body_for_hexdigest).
+ and_return('hereistheunmaskedtext')
+
+ expect(foi_attachment.unmasked_body).to eq('hereistheunmaskedtext')
+ end
+
+ end
+
describe '#main_body_part?' do
subject { attachment.main_body_part? }
diff --git a/spec/support/email_helpers.rb b/spec/support/email_helpers.rb
index 03dbed0e99..29d46222d9 100644
--- a/spec/support/email_helpers.rb
+++ b/spec/support/email_helpers.rb
@@ -49,3 +49,22 @@ def gsub_addresses(content, **kargs)
end
content
end
+
+def rebuild_raw_emails(info_request)
+ info_request.incoming_messages.each do |im|
+ mail = Mail.new
+
+ mail.to = info_request.incoming_email
+ mail.from = "#{im.from_name} <#{im.from_email}>"
+ mail.subject = im.subject
+ mail.date = im.sent_at
+ mail.body = im.cached_main_body_text_unfolded
+
+ im.foi_attachments.each do |a|
+ mail.add_file filename: a.filename, content: a.file.download
+ end
+
+ im.raw_email.data = mail
+ im.raw_email.save!
+ end
+end
From 1dea0034493ea5dcb896dc0649365b9df39dfb35 Mon Sep 17 00:00:00 2001
From: Graeme Porteous
Date: Mon, 31 Jul 2023 10:53:52 +0100
Subject: [PATCH 131/265] Add FoiAttachment#masked_at column
This column will be used to store when the attachment was last masked.
If this column is null then we know the attachment will need to be
re-masked.
This updated the file attachment stored in `ActiveStorage` with masks
and censor rules applied when running the `FoiAttachmentMaskJob`.
---
app/controllers/attachments_controller.rb | 9 +++-
app/jobs/foi_attachment_mask_job.rb | 2 +-
app/models/foi_attachment.rb | 9 +++-
app/models/info_request.rb | 8 +++
...201410_add_masked_at_to_foi_attachments.rb | 5 ++
.../attachments_controller_spec.rb | 6 +--
spec/jobs/foi_attachment_mask_job_spec.rb | 50 +++++++++++++++----
spec/models/foi_attachment_spec.rb | 38 +++++++++++++-
spec/models/info_request_spec.rb | 21 ++++++++
9 files changed, 128 insertions(+), 20 deletions(-)
create mode 100644 db/migrate/20230717201410_add_masked_at_to_foi_attachments.rb
diff --git a/app/controllers/attachments_controller.rb b/app/controllers/attachments_controller.rb
index 9b96410f5c..b84a40793d 100644
--- a/app/controllers/attachments_controller.rb
+++ b/app/controllers/attachments_controller.rb
@@ -19,8 +19,13 @@ class AttachmentsController < ApplicationController
around_action :cache_attachments
def show
- body = FoiAttachmentMaskJob.perform_now(@attachment)
- render body: body, content_type: content_type
+ FoiAttachmentMaskJob.perform_now(@attachment)
+
+ if @attachment.masked?
+ render body: @attachment.body, content_type: content_type
+ else
+ # TODO: perform job in the background
+ end
end
def show_as_html
diff --git a/app/jobs/foi_attachment_mask_job.rb b/app/jobs/foi_attachment_mask_job.rb
index bca6429bbe..f9939adab3 100644
--- a/app/jobs/foi_attachment_mask_job.rb
+++ b/app/jobs/foi_attachment_mask_job.rb
@@ -30,7 +30,7 @@ def perform(attachment)
try(:html_safe)
end
- body
+ attachment.update(body: body, masked_at: Time.zone.now)
end
private
diff --git a/app/models/foi_attachment.rb b/app/models/foi_attachment.rb
index f13367a756..6ce5a6051a 100644
--- a/app/models/foi_attachment.rb
+++ b/app/models/foi_attachment.rb
@@ -1,5 +1,5 @@
# == Schema Information
-# Schema version: 20220916134847
+# Schema version: 20230717201410
#
# Table name: foi_attachments
#
@@ -16,6 +16,7 @@
# updated_at :datetime
# prominence :string default("normal")
# prominence_reason :text
+# masked_at :datetime
#
# models/foi_attachment.rb:
@@ -82,7 +83,7 @@ def delete_cached_file!
end
def body=(d)
- self.hexdigest = Digest::MD5.hexdigest(d)
+ self.hexdigest ||= Digest::MD5.hexdigest(d)
ensure_filename!
file.attach(
@@ -133,6 +134,10 @@ def unmasked_body
)
end
+ def masked?
+ file.attached? && masked_at.present? && masked_at < Time.zone.now
+ end
+
def main_body_part?
self == incoming_message.get_main_body_text_part
end
diff --git a/app/models/info_request.rb b/app/models/info_request.rb
index 21985469c1..412271f7c3 100644
--- a/app/models/info_request.rb
+++ b/app/models/info_request.rb
@@ -807,6 +807,10 @@ def tag_string=(tag_string)
end
def expire(options={})
+ # Clear any attachment masked_at timestamp, forcing attachments to be
+ # reparsed
+ clear_attachment_masks!
+
# Clear out cached entries, by removing files from disk (the built in
# Rails fragment cache made doing this and other things too hard)
foi_fragment_cache_directories.each { |dir| FileUtils.rm_rf(dir) }
@@ -822,6 +826,10 @@ def expire(options={})
reindex_request_events
end
+ def clear_attachment_masks!
+ foi_attachments.update_all(masked_at: nil)
+ end
+
# Removes anything cached about the object in the database, and saves
def clear_in_database_caches!
incoming_messages.each(&:clear_in_database_caches!)
diff --git a/db/migrate/20230717201410_add_masked_at_to_foi_attachments.rb b/db/migrate/20230717201410_add_masked_at_to_foi_attachments.rb
new file mode 100644
index 0000000000..18ef10c9e9
--- /dev/null
+++ b/db/migrate/20230717201410_add_masked_at_to_foi_attachments.rb
@@ -0,0 +1,5 @@
+class AddMaskedAtToFoiAttachments < ActiveRecord::Migration[7.0]
+ def change
+ add_column :foi_attachments, :masked_at, :datetime
+ end
+end
diff --git a/spec/controllers/attachments_controller_spec.rb b/spec/controllers/attachments_controller_spec.rb
index 6000a8652c..ab0e4d586b 100644
--- a/spec/controllers/attachments_controller_spec.rb
+++ b/spec/controllers/attachments_controller_spec.rb
@@ -113,12 +113,10 @@ def show(params = {})
expect(response.status).to eq(303)
end
- it 'returns body from FoiAttachmentMaskJob' do
+ it 'perfoms a FoiAttachmentMaskJob' do
expect(FoiAttachmentMaskJob).to receive(:perform_now).
- with(attachment).
- and_return('Monkey')
+ with(attachment)
show
- expect(response.body).to match('Monkey')
end
context 'when request is embargoed' do
diff --git a/spec/jobs/foi_attachment_mask_job_spec.rb b/spec/jobs/foi_attachment_mask_job_spec.rb
index b916acb11c..8738054286 100644
--- a/spec/jobs/foi_attachment_mask_job_spec.rb
+++ b/spec/jobs/foi_attachment_mask_job_spec.rb
@@ -4,10 +4,35 @@
let(:info_request) { FactoryBot.create(:info_request_with_html_attachment) }
let(:incoming_message) { info_request.incoming_messages.first }
let(:attachment) { incoming_message.foi_attachments.last }
- let(:body) { described_class.new.perform(attachment) }
+
+ def perform
+ described_class.new.perform(attachment)
+ end
before { rebuild_raw_emails(info_request) }
+ it 'update the attachment body' do
+ info_request.censor_rules.create!(
+ text: 'dull', replacement: 'boring',
+ last_edit_editor: 'unknown', last_edit_comment: 'none'
+ )
+
+ expect(attachment.body).to include('dull')
+ expect(attachment.body).to_not include('boring')
+ expect { perform }.to change { attachment.body }
+ expect(attachment.body).to_not include('dull')
+ expect(attachment.body).to include('boring')
+ end
+
+ it 'update the attachment masked_at' do
+ info_request.censor_rules.create!(
+ text: 'dull', replacement: 'boring',
+ last_edit_editor: 'unknown', last_edit_comment: 'none'
+ )
+
+ expect { perform }.to change { attachment.masked_at }.to(Time)
+ end
+
it 'sanitises HTML attachments' do
# Nokogiri adds the meta tag; see
# https://github.com/sparklemotion/nokogiri/issues/1008
@@ -22,7 +47,8 @@