From 6e55ff964325694c9a06914e59733babfc4854c7 Mon Sep 17 00:00:00 2001 From: Filippo Giunchedi Date: Thu, 30 Nov 2023 11:46:06 +0100 Subject: [PATCH 01/17] Change Vagrant to install Node 20 (#28100) Co-authored-by: Filippo Giunchedi --- Vagrantfile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Vagrantfile b/Vagrantfile index e2c66a476edc3a..6f0f5110952aed 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -10,7 +10,11 @@ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - sudo apt-add-repository 'deb https://dl.yarnpkg.com/debian/ stable main' # Add repo for NodeJS -curl -sL https://deb.nodesource.com/setup_16.x | sudo bash - +sudo mkdir -p /etc/apt/keyrings +curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg +NODE_MAJOR=20 +echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list +sudo apt-get update # Add firewall rule to redirect 80 to PORT and save sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port #{ENV["PORT"]} From b696ca6b1a0fee1e56fcf70f4c561ff2661ad81d Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 30 Nov 2023 05:48:46 -0500 Subject: [PATCH 02/17] Move self destruct CLI command definition code to module (#28131) --- lib/mastodon/cli/federation.rb | 74 ++++++++++++++++++++++++++++++++++ lib/mastodon/cli/main.rb | 62 +--------------------------- 2 files changed, 76 insertions(+), 60 deletions(-) create mode 100644 lib/mastodon/cli/federation.rb diff --git a/lib/mastodon/cli/federation.rb b/lib/mastodon/cli/federation.rb new file mode 100644 index 00000000000000..1b4cb467a571bb --- /dev/null +++ b/lib/mastodon/cli/federation.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true + +require 'tty-prompt' + +module Mastodon::CLI + module Federation + extend ActiveSupport::Concern + + included do + desc 'self-destruct', 'Erase the server from the federation' + long_desc <<~LONG_DESC + Erase the server from the federation by broadcasting account delete + activities to all known other servers. This allows a "clean exit" from + running a Mastodon server, as it leaves next to no cache behind on + other servers. + + This command is always interactive and requires confirmation twice. + + No local data is actually deleted, because emptying the + database or removing files is much faster through other, external + means, such as e.g. deleting the entire VPS. However, because other + servers will delete data about local users, but no local data will be + updated (such as e.g. followers), there will be a state mismatch + that will lead to glitches and issues if you then continue to run and use + the server. + + So either you know exactly what you are doing, or you are starting + from a blank slate afterwards by manually clearing out all the local + data! + LONG_DESC + def self_destruct + if SelfDestructHelper.self_destruct? + prompt.ok('Self-destruct mode is already enabled for this Mastodon server') + + pending_accounts = Account.local.without_suspended.count + Account.local.suspended.joins(:deletion_request).count + sidekiq_stats = Sidekiq::Stats.new + + if pending_accounts.positive? + prompt.warn("#{pending_accounts} accounts are still pending deletion.") + elsif sidekiq_stats.enqueued.positive? + prompt.warn('Deletion notices are still being processed') + elsif sidekiq_stats.retry_size.positive? + prompt.warn('At least one delivery attempt for each deletion notice has been made, but some have failed and are scheduled for retry') + else + prompt.ok('Every deletion notice has been sent! You can safely delete all data and decomission your servers!') + end + + exit(0) + end + + exit(1) unless prompt.ask('Type in the domain of the server to confirm:', required: true) == Rails.configuration.x.local_domain + + prompt.warn('This operation WILL NOT be reversible.') + prompt.warn('While the data won\'t be erased locally, the server will be in a BROKEN STATE afterwards.') + prompt.warn('The deletion process itself may take a long time, and will be handled by Sidekiq, so do not shut it down until it has finished (you will be able to re-run this command to see the state of the self-destruct process).') + + exit(1) if prompt.no?('Are you sure you want to proceed?') + + self_destruct_value = Rails.application.message_verifier('self-destruct').generate(Rails.configuration.x.local_domain) + prompt.ok('To switch Mastodon to self-destruct mode, add the following variable to your evironment (e.g. by adding a line to your `.env.production`) and restart all Mastodon processes:') + prompt.ok(" SELF_DESTRUCT=#{self_destruct_value}") + prompt.ok("\nYou can re-run this command to see the state of the self-destruct process.") + rescue TTY::Reader::InputInterrupt + exit(1) + end + + private + + def prompt + @prompt ||= TTY::Prompt.new + end + end + end +end diff --git a/lib/mastodon/cli/main.rb b/lib/mastodon/cli/main.rb index 64f1646f491091..ef40b81f33959c 100644 --- a/lib/mastodon/cli/main.rb +++ b/lib/mastodon/cli/main.rb @@ -8,6 +8,7 @@ require_relative 'domains' require_relative 'email_domain_blocks' require_relative 'emoji' +require_relative 'federation' require_relative 'feeds' require_relative 'ip_blocks' require_relative 'maintenance' @@ -65,66 +66,7 @@ class Main < Base desc 'maintenance SUBCOMMAND ...ARGS', 'Various maintenance utilities' subcommand 'maintenance', Maintenance - desc 'self-destruct', 'Erase the server from the federation' - long_desc <<~LONG_DESC - Erase the server from the federation by broadcasting account delete - activities to all known other servers. This allows a "clean exit" from - running a Mastodon server, as it leaves next to no cache behind on - other servers. - - This command is always interactive and requires confirmation twice. - - No local data is actually deleted, because emptying the - database or removing files is much faster through other, external - means, such as e.g. deleting the entire VPS. However, because other - servers will delete data about local users, but no local data will be - updated (such as e.g. followers), there will be a state mismatch - that will lead to glitches and issues if you then continue to run and use - the server. - - So either you know exactly what you are doing, or you are starting - from a blank slate afterwards by manually clearing out all the local - data! - LONG_DESC - def self_destruct - require 'tty-prompt' - - prompt = TTY::Prompt.new - - if SelfDestructHelper.self_destruct? - prompt.ok('Self-destruct mode is already enabled for this Mastodon server') - - pending_accounts = Account.local.without_suspended.count + Account.local.suspended.joins(:deletion_request).count - sidekiq_stats = Sidekiq::Stats.new - - if pending_accounts.positive? - prompt.warn("#{pending_accounts} accounts are still pending deletion.") - elsif sidekiq_stats.enqueued.positive? - prompt.warn('Deletion notices are still being processed') - elsif sidekiq_stats.retry_size.positive? - prompt.warn('At least one delivery attempt for each deletion notice has been made, but some have failed and are scheduled for retry') - else - prompt.ok('Every deletion notice has been sent! You can safely delete all data and decomission your servers!') - end - - exit(0) - end - - exit(1) unless prompt.ask('Type in the domain of the server to confirm:', required: true) == Rails.configuration.x.local_domain - - prompt.warn('This operation WILL NOT be reversible.') - prompt.warn('While the data won\'t be erased locally, the server will be in a BROKEN STATE afterwards.') - prompt.warn('The deletion process itself may take a long time, and will be handled by Sidekiq, so do not shut it down until it has finished (you will be able to re-run this command to see the state of the self-destruct process).') - - exit(1) if prompt.no?('Are you sure you want to proceed?') - - self_destruct_value = Rails.application.message_verifier('self-destruct').generate(Rails.configuration.x.local_domain) - prompt.ok('To switch Mastodon to self-destruct mode, add the following variable to your evironment (e.g. by adding a line to your `.env.production`) and restart all Mastodon processes:') - prompt.ok(" SELF_DESTRUCT=#{self_destruct_value}") - prompt.ok("\nYou can re-run this command to see the state of the self-destruct process.") - rescue TTY::Reader::InputInterrupt - exit(1) - end + include Federation map %w(--version -v) => :version From c761cc4738c74519c65a99c5ab24874584605d2d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 30 Nov 2023 11:53:49 +0100 Subject: [PATCH 03/17] fix(deps): update babel monorepo to v7.23.5 (#28122) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 260 +++++++++++++++++++++++++++--------------------------- 1 file changed, 130 insertions(+), 130 deletions(-) diff --git a/yarn.lock b/yarn.lock index 11c2724d59c911..69464dfa2f28cd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -42,55 +42,55 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.22.13": - version: 7.22.13 - resolution: "@babel/code-frame@npm:7.22.13" +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/code-frame@npm:7.23.5" dependencies: - "@babel/highlight": "npm:^7.22.13" + "@babel/highlight": "npm:^7.23.4" chalk: "npm:^2.4.2" - checksum: f4cc8ae1000265677daf4845083b72f88d00d311adb1a93c94eb4b07bf0ed6828a81ae4ac43ee7d476775000b93a28a9cddec18fbdc5796212d8dcccd5de72bd + checksum: a10e843595ddd9f97faa99917414813c06214f4d9205294013e20c70fbdf4f943760da37dec1d998bf3e6fc20fa2918a47c0e987a7e458663feb7698063ad7c6 languageName: node linkType: hard -"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.22.9, @babel/compat-data@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/compat-data@npm:7.23.3" - checksum: c6af331753c34ee8a5678bc94404320826cb56b1dda3efc1311ec8fb0774e78225132f3c1acc988440ace667f14a838e297a822692b95758aa63da406e1f97a1 +"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.22.9, @babel/compat-data@npm:^7.23.3, @babel/compat-data@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/compat-data@npm:7.23.5" + checksum: 081278ed46131a890ad566a59c61600a5f9557bd8ee5e535890c8548192532ea92590742fd74bd9db83d74c669ef8a04a7e1c85cdea27f960233e3b83c3a957c languageName: node linkType: hard "@babel/core@npm:^7.10.4, @babel/core@npm:^7.11.1, @babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.22.1": - version: 7.23.3 - resolution: "@babel/core@npm:7.23.3" + version: 7.23.5 + resolution: "@babel/core@npm:7.23.5" dependencies: "@ampproject/remapping": "npm:^2.2.0" - "@babel/code-frame": "npm:^7.22.13" - "@babel/generator": "npm:^7.23.3" + "@babel/code-frame": "npm:^7.23.5" + "@babel/generator": "npm:^7.23.5" "@babel/helper-compilation-targets": "npm:^7.22.15" "@babel/helper-module-transforms": "npm:^7.23.3" - "@babel/helpers": "npm:^7.23.2" - "@babel/parser": "npm:^7.23.3" + "@babel/helpers": "npm:^7.23.5" + "@babel/parser": "npm:^7.23.5" "@babel/template": "npm:^7.22.15" - "@babel/traverse": "npm:^7.23.3" - "@babel/types": "npm:^7.23.3" + "@babel/traverse": "npm:^7.23.5" + "@babel/types": "npm:^7.23.5" convert-source-map: "npm:^2.0.0" debug: "npm:^4.1.0" gensync: "npm:^1.0.0-beta.2" json5: "npm:^2.2.3" semver: "npm:^6.3.1" - checksum: 08d43b749e24052d12713a7fb1f0c0d1275d4fb056d00846faeb8da79ecf6d0ba91a11b6afec407b8b0f9388d00e2c2f485f282bef0ade4d6d0a17de191a4287 + checksum: 311a512a870ee330a3f9a7ea89e5df790b2b5af0b1bd98b10b4edc0de2ac440f0df4d69ea2c0ee38a4b89041b9a495802741d93603be7d4fd834ec8bb6970bd2 languageName: node linkType: hard -"@babel/generator@npm:^7.23.3, @babel/generator@npm:^7.7.2": - version: 7.23.3 - resolution: "@babel/generator@npm:7.23.3" +"@babel/generator@npm:^7.23.5, @babel/generator@npm:^7.7.2": + version: 7.23.5 + resolution: "@babel/generator@npm:7.23.5" dependencies: - "@babel/types": "npm:^7.23.3" + "@babel/types": "npm:^7.23.5" "@jridgewell/gen-mapping": "npm:^0.3.2" "@jridgewell/trace-mapping": "npm:^0.3.17" jsesc: "npm:^2.5.1" - checksum: d5fff1417eecfada040e01a7c77a4968e81c436aeb35815ce85b4e80cd01e731423613d61033044a6cb5563bb8449ee260e3379b63eb50b38ec0a9ea9c00abfd + checksum: 14c6e874f796c4368e919bed6003bb0adc3ce837760b08f9e646d20aeb5ae7d309723ce6e4f06bcb4a2b5753145446c8e4425851380f695e40e71e1760f49e7b languageName: node linkType: hard @@ -310,10 +310,10 @@ __metadata: languageName: node linkType: hard -"@babel/helper-string-parser@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-string-parser@npm:7.22.5" - checksum: 6b0ff8af724377ec41e5587fffa7605198da74cb8e7d8d48a36826df0c0ba210eb9fedb3d9bef4d541156e0bd11040f021945a6cbb731ccec4aefb4affa17aa4 +"@babel/helper-string-parser@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/helper-string-parser@npm:7.23.4" + checksum: f348d5637ad70b6b54b026d6544bd9040f78d24e7ec245a0fc42293968181f6ae9879c22d89744730d246ce8ec53588f716f102addd4df8bbc79b73ea10004ac languageName: node linkType: hard @@ -324,10 +324,10 @@ __metadata: languageName: node linkType: hard -"@babel/helper-validator-option@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/helper-validator-option@npm:7.22.15" - checksum: e9661bf80ba18e2dd978217b350fb07298e57ac417f4f1ab9fa011505e20e4857f2c3b4b538473516a9dc03af5ce3a831e5ed973311c28326f4c330b6be981c2 +"@babel/helper-validator-option@npm:^7.22.15, @babel/helper-validator-option@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/helper-validator-option@npm:7.23.5" + checksum: af45d5c0defb292ba6fd38979e8f13d7da63f9623d8ab9ededc394f67eb45857d2601278d151ae9affb6e03d5d608485806cd45af08b4468a0515cf506510e94 languageName: node linkType: hard @@ -342,34 +342,34 @@ __metadata: languageName: node linkType: hard -"@babel/helpers@npm:^7.23.2": - version: 7.23.2 - resolution: "@babel/helpers@npm:7.23.2" +"@babel/helpers@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/helpers@npm:7.23.5" dependencies: "@babel/template": "npm:^7.22.15" - "@babel/traverse": "npm:^7.23.2" - "@babel/types": "npm:^7.23.0" - checksum: 3a6a939c5277a27486e7c626812f0643b35d1c053ac2eb66911f5ae6c0a4e4bcdd40750eba36b766b0ee8a753484287f50ae56232a5f8f2947116723e44b9e35 + "@babel/traverse": "npm:^7.23.5" + "@babel/types": "npm:^7.23.5" + checksum: a37e2728eb4378a4888e5d614e28de7dd79b55ac8acbecd0e5c761273e2a02a8f33b34b1932d9069db55417ace2937cbf8ec37c42f1030ce6d228857d7ccaa4f languageName: node linkType: hard -"@babel/highlight@npm:^7.22.13": - version: 7.22.20 - resolution: "@babel/highlight@npm:7.22.20" +"@babel/highlight@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/highlight@npm:7.23.4" dependencies: "@babel/helper-validator-identifier": "npm:^7.22.20" chalk: "npm:^2.4.2" js-tokens: "npm:^4.0.0" - checksum: f3c3a193afad23434297d88e81d1d6c0c2cf02423de2139ada7ce0a7fc62d8559abf4cc996533c1a9beca7fc990010eb8d544097f75e818ac113bf39ed810aa2 + checksum: fbff9fcb2f5539289c3c097d130e852afd10d89a3a08ac0b5ebebbc055cc84a4bcc3dcfed463d488cde12dd0902ef1858279e31d7349b2e8cee43913744bda33 languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/parser@npm:7.23.3" +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/parser@npm:7.23.5" bin: parser: ./bin/babel-parser.js - checksum: 0fe11eadd4146a9155305b5bfece0f8223a3b1b97357ffa163c0156940de92e76cd0e7a173de819b8692767147e62f33389b312d1537f84cede51092672df6ef + checksum: 3356aa90d7bafb4e2c7310e7c2c3d443c4be4db74913f088d3d577a1eb914ea4188e05fd50a47ce907a27b755c4400c4e3cbeee73dbeb37761f6ca85954f5a20 languageName: node linkType: hard @@ -661,9 +661,9 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-async-generator-functions@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-async-generator-functions@npm:7.23.3" +"@babel/plugin-transform-async-generator-functions@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-async-generator-functions@npm:7.23.4" dependencies: "@babel/helper-environment-visitor": "npm:^7.22.20" "@babel/helper-plugin-utils": "npm:^7.22.5" @@ -671,7 +671,7 @@ __metadata: "@babel/plugin-syntax-async-generators": "npm:^7.8.4" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: e846f282658e097fce4fccf3ee29289bf05f0654846a5994727a36f0cdc2e47abdffd4be4fa65787e94aa975824fae894c90afbfdc8caacd46c12c7f43e99d7f + checksum: f2eef4de609975a3f7da7832576b5ffc93e43c80f87e1a99e886b0f8591096cfc4c37e2d5f52fdeaa2a9c09a25a59f3e621159abaca75d3193922a5c0e4cbe0c languageName: node linkType: hard @@ -699,14 +699,14 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-block-scoping@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-block-scoping@npm:7.23.3" +"@babel/plugin-transform-block-scoping@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-block-scoping@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: ccaeded7954c196811d22a35322579254cda52676e823682b6234885a3aaf88fe0d5152dacaec43db9031dcf35a050a5343e36028e5905b0ba9c02d36b30a57f + checksum: 83006804dddf980ab1bcd6d67bc381e24b58c776507c34f990468f820d0da71dba3697355ca4856532fa2eeb2a1e3e73c780f03760b5507a511cbedb0308e276 languageName: node linkType: hard @@ -722,22 +722,22 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-class-static-block@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-class-static-block@npm:7.23.3" +"@babel/plugin-transform-class-static-block@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-class-static-block@npm:7.23.4" dependencies: "@babel/helper-create-class-features-plugin": "npm:^7.22.15" "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-class-static-block": "npm:^7.14.5" peerDependencies: "@babel/core": ^7.12.0 - checksum: 89cdb66d7bc834cd51659eb7286a6bee23add0bc114943d68c4b6c0c834178cf0d55183df0cf508fec9c55ed4155641360e6f55a91c16fe826ccaf1adf381922 + checksum: fdca96640ef29d8641a7f8de106f65f18871b38cc01c0f7b696d2b49c76b77816b30a812c08e759d06dd10b4d9b3af6b5e4ac22a2017a88c4077972224b77ab0 languageName: node linkType: hard -"@babel/plugin-transform-classes@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-classes@npm:7.23.3" +"@babel/plugin-transform-classes@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/plugin-transform-classes@npm:7.23.5" dependencies: "@babel/helper-annotate-as-pure": "npm:^7.22.5" "@babel/helper-compilation-targets": "npm:^7.22.15" @@ -750,7 +750,7 @@ __metadata: globals: "npm:^11.1.0" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 88bfd332db0ba5cbfb8557a2ba5a7185151aebc9cfe3035b014aa6d795556acbe672bb8c78da3c9fd1d23f55a333d14b5daa127ef037f5ced5198b6d79a146d6 + checksum: 07988f52b4893151887d1ea6ff79e5fe834078c5731bd09babd5659edbbae21ea4e2de326a02443a63fd776b4c945da6177f07875b56fe66e0b7899e830a9e92 languageName: node linkType: hard @@ -800,15 +800,15 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-dynamic-import@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-dynamic-import@npm:7.23.3" +"@babel/plugin-transform-dynamic-import@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-dynamic-import@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-dynamic-import": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: df3fd130312dc53d068fa76333991dce5e86987b023af8c3b502bd7d36a8e67da6f718e61dc838576a9fbacd06628e29607ee22d9bae30705485c14130eab201 + checksum: 19ae4a4a2ca86d35224734c41c48b2aa6a13139f3cfa1cbd18c0e65e461de8b65687dec7e52b7a72bb49db04465394c776aa1b13a2af5dc975b2a0cde3dcab67 languageName: node linkType: hard @@ -824,15 +824,15 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-export-namespace-from@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-export-namespace-from@npm:7.23.3" +"@babel/plugin-transform-export-namespace-from@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-export-namespace-from@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-export-namespace-from": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 390c6626dcda99023629049d92090242b4575351a4a7b47f97febabd2381f2cd0f624de661d8de8d1f715fedd63753cfd1feddead19e5960c27b88e447465b81 + checksum: 38bf04f851e36240bbe83ace4169da626524f4107bfb91f05b4ad93a5fb6a36d5b3d30b8883c1ba575ccfc1bac7938e90ca2e3cb227f7b3f4a9424beec6fd4a7 languageName: node linkType: hard @@ -860,15 +860,15 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-json-strings@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-json-strings@npm:7.23.3" +"@babel/plugin-transform-json-strings@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-json-strings@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-json-strings": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: e1cef6a485b9da32aba9449fb459dac062dfc401f3d6ad48e7fbdcb73bbe470c995cc15ce5c421b95efe1e9a90d5507eb606360fe10b6d8cb869dd5dae7a2562 + checksum: 39e82223992a9ad857722ae051291935403852ad24b0dd64c645ca1c10517b6bf9822377d88643fed8b3e61a4e3f7e5ae41cf90eb07c40a786505d47d5970e54 languageName: node linkType: hard @@ -883,15 +883,15 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-logical-assignment-operators@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.23.3" +"@babel/plugin-transform-logical-assignment-operators@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-logical-assignment-operators": "npm:^7.10.4" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 23b7588b26d420c8b132bd08916d49871ca0c8db892f6b58637b10e2a0d918163d413c505db880a9157fc2e61d089040f139298a60d837ccbd0efca0474ac7ca + checksum: 87b034dd13143904e405887e6125d76c27902563486efc66b7d9a9d8f9406b76c6ac42d7b37224014af5783d7edb465db0cdecd659fa3227baad0b3a6a35deff languageName: node linkType: hard @@ -980,7 +980,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.22.3, @babel/plugin-transform-nullish-coalescing-operator@npm:^7.23.3": +"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.22.3, @babel/plugin-transform-nullish-coalescing-operator@npm:^7.23.4": version: 7.23.4 resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.23.4" dependencies: @@ -992,21 +992,21 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-numeric-separator@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-numeric-separator@npm:7.23.3" +"@babel/plugin-transform-numeric-separator@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-numeric-separator@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-numeric-separator": "npm:^7.10.4" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: d3748cce20e8752e61dfda55e275c699459a3ff8d0bb46585da813136e04066b1ce70b71beef504fcdc8d4cca3c955112cea96d5e9fd5a42a5bc8956d05236c2 + checksum: e34902da4f5588dc4812c92cb1f6a5e3e3647baf7b4623e30942f551bf1297621abec4e322ebfa50b320c987c0f34d9eb4355b3d289961d9035e2126e3119c12 languageName: node linkType: hard -"@babel/plugin-transform-object-rest-spread@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-object-rest-spread@npm:7.23.3" +"@babel/plugin-transform-object-rest-spread@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-object-rest-spread@npm:7.23.4" dependencies: "@babel/compat-data": "npm:^7.23.3" "@babel/helper-compilation-targets": "npm:^7.22.15" @@ -1015,7 +1015,7 @@ __metadata: "@babel/plugin-transform-parameters": "npm:^7.23.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 31ab631aaba945c118662943e5f1f54a21f07d64f06e06b25d55871168c460f3eeeccdf7b05aa74a1340e2cfbe781ad3c7ceccd0c2585d39f7b73ba11ebaa9d0 + checksum: b56017992ffe7fcd1dd9a9da67c39995a141820316266bcf7d77dc912980d228ccbd3f36191d234f5cc389b09157b5d2a955e33e8fb368319534affd1c72b262 languageName: node linkType: hard @@ -1031,28 +1031,28 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-optional-catch-binding@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-optional-catch-binding@npm:7.23.3" +"@babel/plugin-transform-optional-catch-binding@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-optional-catch-binding@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-optional-catch-binding": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 85ac1e94ee8f21648816151628ff931cc16143ec8c904649a1ecfd8960160290eccc5a197b4ae3ee7a1c7a27a7c4189e61b4de24483d5bad4040784afe2d206f + checksum: 4ef61812af0e4928485e28301226ce61139a8b8cea9e9a919215ebec4891b9fea2eb7a83dc3090e2679b7d7b2c8653da601fbc297d2addc54a908b315173991e languageName: node linkType: hard -"@babel/plugin-transform-optional-chaining@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-optional-chaining@npm:7.23.3" +"@babel/plugin-transform-optional-chaining@npm:^7.23.3, @babel/plugin-transform-optional-chaining@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-optional-chaining@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" "@babel/plugin-syntax-optional-chaining": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 2b358962169d871392aa292a67527e5335909438da0ddbb0d19e7838c0f8a2081cc751a49e6e534ac4d6c932254531a205ac22b197f64fc4c89f41bf9f595497 + checksum: 305b773c29ad61255b0e83ec1e92b2f7af6aa58be4cba1e3852bddaa14f7d2afd7b4438f41c28b179d6faac7eb8d4fb5530a17920294f25d459b8f84406bfbfb languageName: node linkType: hard @@ -1079,9 +1079,9 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-private-property-in-object@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-private-property-in-object@npm:7.23.3" +"@babel/plugin-transform-private-property-in-object@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-private-property-in-object@npm:7.23.4" dependencies: "@babel/helper-annotate-as-pure": "npm:^7.22.5" "@babel/helper-create-class-features-plugin": "npm:^7.22.15" @@ -1089,7 +1089,7 @@ __metadata: "@babel/plugin-syntax-private-property-in-object": "npm:^7.14.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 9211dd25a6e87a01535f2d97a663fa6de3472b963c8dcfaacce229a2e3fa6500f2e9fc690bc100a540fc7b66c8364faf7ef19b32e9c9b9791e4561b742c15ed3 + checksum: 8d31b28f24204b4d13514cd3a8f3033abf575b1a6039759ddd6e1d82dd33ba7281f9bc85c9f38072a665d69bfa26dc40737eefaf9d397b024654a483d2357bf5 languageName: node linkType: hard @@ -1333,13 +1333,13 @@ __metadata: linkType: hard "@babel/preset-env@npm:^7.11.0, @babel/preset-env@npm:^7.12.1, @babel/preset-env@npm:^7.22.4": - version: 7.23.3 - resolution: "@babel/preset-env@npm:7.23.3" + version: 7.23.5 + resolution: "@babel/preset-env@npm:7.23.5" dependencies: - "@babel/compat-data": "npm:^7.23.3" + "@babel/compat-data": "npm:^7.23.5" "@babel/helper-compilation-targets": "npm:^7.22.15" "@babel/helper-plugin-utils": "npm:^7.22.5" - "@babel/helper-validator-option": "npm:^7.22.15" + "@babel/helper-validator-option": "npm:^7.23.5" "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "npm:^7.23.3" "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "npm:^7.23.3" "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "npm:^7.23.3" @@ -1363,25 +1363,25 @@ __metadata: "@babel/plugin-syntax-top-level-await": "npm:^7.14.5" "@babel/plugin-syntax-unicode-sets-regex": "npm:^7.18.6" "@babel/plugin-transform-arrow-functions": "npm:^7.23.3" - "@babel/plugin-transform-async-generator-functions": "npm:^7.23.3" + "@babel/plugin-transform-async-generator-functions": "npm:^7.23.4" "@babel/plugin-transform-async-to-generator": "npm:^7.23.3" "@babel/plugin-transform-block-scoped-functions": "npm:^7.23.3" - "@babel/plugin-transform-block-scoping": "npm:^7.23.3" + "@babel/plugin-transform-block-scoping": "npm:^7.23.4" "@babel/plugin-transform-class-properties": "npm:^7.23.3" - "@babel/plugin-transform-class-static-block": "npm:^7.23.3" - "@babel/plugin-transform-classes": "npm:^7.23.3" + "@babel/plugin-transform-class-static-block": "npm:^7.23.4" + "@babel/plugin-transform-classes": "npm:^7.23.5" "@babel/plugin-transform-computed-properties": "npm:^7.23.3" "@babel/plugin-transform-destructuring": "npm:^7.23.3" "@babel/plugin-transform-dotall-regex": "npm:^7.23.3" "@babel/plugin-transform-duplicate-keys": "npm:^7.23.3" - "@babel/plugin-transform-dynamic-import": "npm:^7.23.3" + "@babel/plugin-transform-dynamic-import": "npm:^7.23.4" "@babel/plugin-transform-exponentiation-operator": "npm:^7.23.3" - "@babel/plugin-transform-export-namespace-from": "npm:^7.23.3" + "@babel/plugin-transform-export-namespace-from": "npm:^7.23.4" "@babel/plugin-transform-for-of": "npm:^7.23.3" "@babel/plugin-transform-function-name": "npm:^7.23.3" - "@babel/plugin-transform-json-strings": "npm:^7.23.3" + "@babel/plugin-transform-json-strings": "npm:^7.23.4" "@babel/plugin-transform-literals": "npm:^7.23.3" - "@babel/plugin-transform-logical-assignment-operators": "npm:^7.23.3" + "@babel/plugin-transform-logical-assignment-operators": "npm:^7.23.4" "@babel/plugin-transform-member-expression-literals": "npm:^7.23.3" "@babel/plugin-transform-modules-amd": "npm:^7.23.3" "@babel/plugin-transform-modules-commonjs": "npm:^7.23.3" @@ -1389,15 +1389,15 @@ __metadata: "@babel/plugin-transform-modules-umd": "npm:^7.23.3" "@babel/plugin-transform-named-capturing-groups-regex": "npm:^7.22.5" "@babel/plugin-transform-new-target": "npm:^7.23.3" - "@babel/plugin-transform-nullish-coalescing-operator": "npm:^7.23.3" - "@babel/plugin-transform-numeric-separator": "npm:^7.23.3" - "@babel/plugin-transform-object-rest-spread": "npm:^7.23.3" + "@babel/plugin-transform-nullish-coalescing-operator": "npm:^7.23.4" + "@babel/plugin-transform-numeric-separator": "npm:^7.23.4" + "@babel/plugin-transform-object-rest-spread": "npm:^7.23.4" "@babel/plugin-transform-object-super": "npm:^7.23.3" - "@babel/plugin-transform-optional-catch-binding": "npm:^7.23.3" - "@babel/plugin-transform-optional-chaining": "npm:^7.23.3" + "@babel/plugin-transform-optional-catch-binding": "npm:^7.23.4" + "@babel/plugin-transform-optional-chaining": "npm:^7.23.4" "@babel/plugin-transform-parameters": "npm:^7.23.3" "@babel/plugin-transform-private-methods": "npm:^7.23.3" - "@babel/plugin-transform-private-property-in-object": "npm:^7.23.3" + "@babel/plugin-transform-private-property-in-object": "npm:^7.23.4" "@babel/plugin-transform-property-literals": "npm:^7.23.3" "@babel/plugin-transform-regenerator": "npm:^7.23.3" "@babel/plugin-transform-reserved-words": "npm:^7.23.3" @@ -1418,7 +1418,7 @@ __metadata: semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 36b02a86817ab5474bb74a8d62a110723b0b05904a52ddc5627cf89457525b8d5ac0739b8e435a6ae12ef8b90cd5fc191169898c3dc2ac9d2c84026b02f2580a + checksum: 2a0e1274dec045186e131c6433659b75492583290e8d41633c616f6bff829cb2e4b2f9a57f556283a54db3bd6aa697911e56a36f607911a29b731c445a5b5a06 languageName: node linkType: hard @@ -1502,32 +1502,32 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:7, @babel/traverse@npm:^7.23.2, @babel/traverse@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/traverse@npm:7.23.3" +"@babel/traverse@npm:7, @babel/traverse@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/traverse@npm:7.23.5" dependencies: - "@babel/code-frame": "npm:^7.22.13" - "@babel/generator": "npm:^7.23.3" + "@babel/code-frame": "npm:^7.23.5" + "@babel/generator": "npm:^7.23.5" "@babel/helper-environment-visitor": "npm:^7.22.20" "@babel/helper-function-name": "npm:^7.23.0" "@babel/helper-hoist-variables": "npm:^7.22.5" "@babel/helper-split-export-declaration": "npm:^7.22.6" - "@babel/parser": "npm:^7.23.3" - "@babel/types": "npm:^7.23.3" + "@babel/parser": "npm:^7.23.5" + "@babel/types": "npm:^7.23.5" debug: "npm:^4.1.0" globals: "npm:^11.1.0" - checksum: 3c2784f4765185126d64fd5eebce0413b7aee6d54f779998594a343a7f973a9693a441ba27533df84e7ab7ce22f1239c6837f35e903132a1b25f7fc7a67bc30f + checksum: c5ea793080ca6719b0a1612198fd25e361cee1f3c14142d7a518d2a1eeb5c1d21f7eec1b26c20ea6e1ddd8ed12ab50b960ff95ffd25be353b6b46e1b54d6f825 languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.0.0-beta.49, @babel/types@npm:^7.12.11, @babel/types@npm:^7.12.6, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.10, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.3, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": - version: 7.23.3 - resolution: "@babel/types@npm:7.23.3" +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.0.0-beta.49, @babel/types@npm:^7.12.11, @babel/types@npm:^7.12.6, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.10, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.5, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": + version: 7.23.5 + resolution: "@babel/types@npm:7.23.5" dependencies: - "@babel/helper-string-parser": "npm:^7.22.5" + "@babel/helper-string-parser": "npm:^7.23.4" "@babel/helper-validator-identifier": "npm:^7.22.20" to-fast-properties: "npm:^2.0.0" - checksum: 371a10dd9c8d8ebf48fc5d9e1b327dafd74453f8ea582dcbddd1cee5ae34e8881b743e783a86c08c04dcd1849b1842455472a911ae8a1c185484fe9b7b5f1595 + checksum: 7dd5e2f59828ed046ad0b06b039df2524a8b728d204affb4fc08da2502b9dd3140b1356b5166515d229dc811539a8b70dcd4bc507e06d62a89f4091a38d0b0fb languageName: node linkType: hard From e6fd9a59e6f7a37fcd1276c75aadfddd79c784ca Mon Sep 17 00:00:00 2001 From: Filippo Giunchedi Date: Thu, 30 Nov 2023 11:58:40 +0100 Subject: [PATCH 04/17] Fix FamiliarFollowersController test response comparison (#28121) Co-authored-by: Filippo Giunchedi --- .../api/v1/accounts/familiar_followers_controller_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/controllers/api/v1/accounts/familiar_followers_controller_spec.rb b/spec/controllers/api/v1/accounts/familiar_followers_controller_spec.rb index 22617730945e57..3c7c7e8b84c297 100644 --- a/spec/controllers/api/v1/accounts/familiar_followers_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/familiar_followers_controller_spec.rb @@ -28,7 +28,7 @@ account_ids = [account_a, account_b, account_b, account_a, account_a].map { |a| a.id.to_s } get :index, params: { id: account_ids } - expect(body_as_json.pluck(:id)).to eq [account_a.id.to_s, account_b.id.to_s] + expect(body_as_json.pluck(:id)).to contain_exactly(account_a.id.to_s, account_b.id.to_s) end end end From ce78a9c9ac3e579d9de1c410d005860a80774a3c Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 30 Nov 2023 06:44:42 -0500 Subject: [PATCH 05/17] Clean up `two_factor_authentication/confirmations` controller spec (#28128) --- .../confirmations_controller_spec.rb | 122 +++++++++--------- 1 file changed, 62 insertions(+), 60 deletions(-) diff --git a/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb b/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb index a5a35e91d05cdf..1b3b0cb0aeebaa 100644 --- a/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb +++ b/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb @@ -20,37 +20,30 @@ [true, false].each do |with_otp_secret| let(:user) { Fabricate(:user, email: 'local-part@domain', otp_secret: with_otp_secret ? 'oldotpsecret' : nil) } - describe 'GET #new' do - context 'when signed in and a new otp secret has been set in the session' do - subject do - sign_in user, scope: :user - get :new, session: { challenge_passed_at: Time.now.utc, new_otp_secret: 'thisisasecretforthespecofnewview' } - end + context 'when signed in' do + before { sign_in user, scope: :user } - include_examples 'renders :new' - end + describe 'GET #new' do + context 'when a new otp secret has been set in the session' do + subject do + get :new, session: { challenge_passed_at: Time.now.utc, new_otp_secret: 'thisisasecretforthespecofnewview' } + end - it 'redirects if not signed in' do - get :new - expect(response).to redirect_to('/auth/sign_in') - end + include_examples 'renders :new' + end - it 'redirects if a new otp_secret has not been set in the session' do - sign_in user, scope: :user - get :new, session: { challenge_passed_at: Time.now.utc } - expect(response).to redirect_to('/settings/otp_authentication') - end - end + it 'redirects if a new otp_secret has not been set in the session' do + get :new, session: { challenge_passed_at: Time.now.utc } - describe 'POST #create' do - context 'when signed in' do - before do - sign_in user, scope: :user + expect(response).to redirect_to('/settings/otp_authentication') end + end + describe 'POST #create' do describe 'when form_two_factor_confirmation parameter is not provided' do it 'raises ActionController::ParameterMissing' do post :create, params: {}, session: { challenge_passed_at: Time.now.utc, new_otp_secret: 'thisisasecretforthespecofnewview' } + expect(response).to have_http_status(400) end end @@ -58,69 +51,78 @@ describe 'when creation succeeds' do let!(:otp_backup_codes) { user.generate_otp_backup_codes! } - it 'renders page with success' do + before do prepare_user_otp_generation - prepare_user_otp_consumption + prepare_user_otp_consumption_response(true) allow(controller).to receive(:current_user).and_return(user) + end - expect do - post :create, - params: { form_two_factor_confirmation: { otp_attempt: '123456' } }, - session: { challenge_passed_at: Time.now.utc, new_otp_secret: 'thisisasecretforthespecofnewview' } - end.to change { user.reload.otp_secret }.to 'thisisasecretforthespecofnewview' + it 'renders page with success' do + expect { post_create_with_options } + .to change { user.reload.otp_secret }.to 'thisisasecretforthespecofnewview' expect(assigns(:recovery_codes)).to eq otp_backup_codes expect(flash[:notice]).to eq 'Two-factor authentication successfully enabled' expect(response).to have_http_status(200) expect(response).to render_template('settings/two_factor_authentication/recovery_codes/index') end - - def prepare_user_otp_generation - allow(user) - .to receive(:generate_otp_backup_codes!) - .and_return(otp_backup_codes) - end - - def prepare_user_otp_consumption - options = { otp_secret: 'thisisasecretforthespecofnewview' } - allow(user) - .to receive(:validate_and_consume_otp!) - .with('123456', options) - .and_return(true) - end end describe 'when creation fails' do subject do - options = { otp_secret: 'thisisasecretforthespecofnewview' } - allow(user) - .to receive(:validate_and_consume_otp!) - .with('123456', options) - .and_return(false) - allow(controller).to receive(:current_user).and_return(user) + expect { post_create_with_options } + .to(not_change { user.reload.otp_secret }) + end - expect do - post :create, - params: { form_two_factor_confirmation: { otp_attempt: '123456' } }, - session: { challenge_passed_at: Time.now.utc, new_otp_secret: 'thisisasecretforthespecofnewview' } - end.to(not_change { user.reload.otp_secret }) + before do + prepare_user_otp_consumption_response(false) + allow(controller).to receive(:current_user).and_return(user) end - it 'renders the new view' do + it 'renders page with error message' do subject expect(response.body).to include 'The entered code was invalid! Are server time and device time correct?' end include_examples 'renders :new' end - end - context 'when not signed in' do - it 'redirects if not signed in' do - post :create, params: { form_two_factor_confirmation: { otp_attempt: '123456' } } - expect(response).to redirect_to('/auth/sign_in') + private + + def post_create_with_options + post :create, + params: { form_two_factor_confirmation: { otp_attempt: '123456' } }, + session: { challenge_passed_at: Time.now.utc, new_otp_secret: 'thisisasecretforthespecofnewview' } + end + + def prepare_user_otp_generation + allow(user) + .to receive(:generate_otp_backup_codes!) + .and_return(otp_backup_codes) + end + + def prepare_user_otp_consumption_response(result) + options = { otp_secret: 'thisisasecretforthespecofnewview' } + allow(user) + .to receive(:validate_and_consume_otp!) + .with('123456', options) + .and_return(result) end end end end + + context 'when not signed in' do + it 'redirects on POST to create' do + post :create, params: { form_two_factor_confirmation: { otp_attempt: '123456' } } + + expect(response).to redirect_to('/auth/sign_in') + end + + it 'redirects on GET to new' do + get :new + + expect(response).to redirect_to('/auth/sign_in') + end + end end From 7faa27e17de515b8718075d89a00942c06c0ef48 Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 30 Nov 2023 12:45:54 +0100 Subject: [PATCH 06/17] Change dismissed banners to be stored server-side (#27055) --- .../components/dismissable_banner.tsx | 25 ++++++++++++++++--- app/javascript/mastodon/reducers/settings.js | 9 +++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/app/javascript/mastodon/components/dismissable_banner.tsx b/app/javascript/mastodon/components/dismissable_banner.tsx index 4feb74a3a19ca6..4e6d3bb9a76730 100644 --- a/app/javascript/mastodon/components/dismissable_banner.tsx +++ b/app/javascript/mastodon/components/dismissable_banner.tsx @@ -1,11 +1,18 @@ +/* eslint-disable @typescript-eslint/no-unsafe-call, + @typescript-eslint/no-unsafe-return, + @typescript-eslint/no-unsafe-assignment, + @typescript-eslint/no-unsafe-member-access + -- the settings store is not yet typed */ import type { PropsWithChildren } from 'react'; -import { useCallback, useState } from 'react'; +import { useCallback, useState, useEffect } from 'react'; import { defineMessages, useIntl } from 'react-intl'; import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg'; +import { changeSetting } from 'mastodon/actions/settings'; import { bannerSettings } from 'mastodon/settings'; +import { useAppSelector, useAppDispatch } from 'mastodon/store'; import { IconButton } from './icon_button'; @@ -21,13 +28,25 @@ export const DismissableBanner: React.FC> = ({ id, children, }) => { - const [visible, setVisible] = useState(!bannerSettings.get(id)); + const dismissed = useAppSelector((state) => + state.settings.getIn(['dismissed_banners', id], false), + ); + const dispatch = useAppDispatch(); + + const [visible, setVisible] = useState(!bannerSettings.get(id) && !dismissed); const intl = useIntl(); const handleDismiss = useCallback(() => { setVisible(false); bannerSettings.set(id, true); - }, [id]); + dispatch(changeSetting(['dismissed_banners', id], true)); + }, [id, dispatch]); + + useEffect(() => { + if (!visible && !dismissed) { + dispatch(changeSetting(['dismissed_banners', id], true)); + } + }, [id, dispatch, visible, dismissed]); if (!visible) { return null; diff --git a/app/javascript/mastodon/reducers/settings.js b/app/javascript/mastodon/reducers/settings.js index 07d1bda0f4d08b..a605ecbb8bd62d 100644 --- a/app/javascript/mastodon/reducers/settings.js +++ b/app/javascript/mastodon/reducers/settings.js @@ -100,6 +100,15 @@ const initialState = ImmutableMap({ body: '', }), }), + + dismissed_banners: ImmutableMap({ + 'public_timeline': false, + 'community_timeline': false, + 'home.explore_prompt': false, + 'explore/links': false, + 'explore/statuses': false, + 'explore/tags': false, + }), }); const defaultColumns = fromJS([ From 0212e0cfbfe4b50b5286165ec9887523f82513d1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 30 Nov 2023 14:22:25 +0100 Subject: [PATCH 07/17] fix(deps): update dependency @babel/runtime to v7.23.5 (#28136) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 69464dfa2f28cd..580407f341c876 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1483,11 +1483,11 @@ __metadata: linkType: hard "@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.22.3, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": - version: 7.23.4 - resolution: "@babel/runtime@npm:7.23.4" + version: 7.23.5 + resolution: "@babel/runtime@npm:7.23.5" dependencies: regenerator-runtime: "npm:^0.14.0" - checksum: db2bf183cd0119599b903ca51ca0aeea8e0ab478a16be1aae10dd90473ed614159d3e5adfdd8f8f3d840402428ce0d90b5c01aae95da9e45a2dd83e02d85ca27 + checksum: ca679cc91bb7e424bc2db87bb58cc3b06ade916b9adb21fbbdc43e54cdaacb3eea201ceba2a0464b11d2eb65b9fe6a6ffcf4d7521fa52994f19be96f1af14788 languageName: node linkType: hard From 02a98210e891dff32b1cb958f799213ccfbbc29c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 30 Nov 2023 14:22:40 +0100 Subject: [PATCH 08/17] fix(deps): update dependency jsdom to v23.0.1 (#28135) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index 580407f341c876..ad792d26c5757e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10640,8 +10640,8 @@ __metadata: linkType: hard "jsdom@npm:^23.0.0": - version: 23.0.0 - resolution: "jsdom@npm:23.0.0" + version: 23.0.1 + resolution: "jsdom@npm:23.0.1" dependencies: cssstyle: "npm:^3.0.0" data-urls: "npm:^5.0.0" @@ -10665,11 +10665,11 @@ __metadata: ws: "npm:^8.14.2" xml-name-validator: "npm:^5.0.0" peerDependencies: - canvas: ^3.0.0 + canvas: ^2.11.2 peerDependenciesMeta: canvas: optional: true - checksum: 2c876a02de49e0ed6b667a4eb9b08b8e76ac189a5571ff97791cc9564e713259314deea6d657cc7f59fc30af41b900e7d833c95017e576dfcaf25f32565722af + checksum: 13b2b3693ccb40215d1cce77bac7a295414ee4c0a06e30167f8087c9867145ba23dbd592bd95a801cadd7b3698bfd20b9c3f2c26fd8422607f22609ed2e404ef languageName: node linkType: hard From bb0efe16e62636895079b3a968e444cd6e80b467 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 30 Nov 2023 08:30:35 -0500 Subject: [PATCH 09/17] Remove `default_scope` from `MediaAttachment` class (#28043) --- app/controllers/accounts_controller.rb | 2 +- app/lib/account_statuses_filter.rb | 2 +- app/lib/vacuum/media_attachments_vacuum.rb | 4 ++-- app/models/admin/status_filter.rb | 2 +- app/models/media_attachment.rb | 7 +++---- app/services/backup_service.rb | 2 +- app/services/clear_domain_media_service.rb | 2 +- app/services/delete_account_service.rb | 2 +- app/services/suspend_account_service.rb | 2 +- app/services/unsuspend_account_service.rb | 2 +- .../activitypub/process_status_update_service_spec.rb | 2 +- 11 files changed, 14 insertions(+), 15 deletions(-) diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index 850bf881ffa54d..4e475fe78263b1 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -50,7 +50,7 @@ def default_statuses end def only_media_scope - Status.joins(:media_attachments).merge(@account.media_attachments.reorder(nil)).group(:id) + Status.joins(:media_attachments).merge(@account.media_attachments).group(:id) end def no_replies_scope diff --git a/app/lib/account_statuses_filter.rb b/app/lib/account_statuses_filter.rb index b34ebb47773986..d1365de586e42b 100644 --- a/app/lib/account_statuses_filter.rb +++ b/app/lib/account_statuses_filter.rb @@ -70,7 +70,7 @@ def filtered_reblogs_scope end def only_media_scope - Status.joins(:media_attachments).merge(account.media_attachments.reorder(nil)).group(Status.arel_table[:id]) + Status.joins(:media_attachments).merge(account.media_attachments).group(Status.arel_table[:id]) end def no_replies_scope diff --git a/app/lib/vacuum/media_attachments_vacuum.rb b/app/lib/vacuum/media_attachments_vacuum.rb index 7b21c84bbce6e9..ab7ea4092faa39 100644 --- a/app/lib/vacuum/media_attachments_vacuum.rb +++ b/app/lib/vacuum/media_attachments_vacuum.rb @@ -27,11 +27,11 @@ def vacuum_orphaned_records! end def media_attachments_past_retention_period - MediaAttachment.unscoped.remote.cached.where(MediaAttachment.arel_table[:created_at].lt(@retention_period.ago)).where(MediaAttachment.arel_table[:updated_at].lt(@retention_period.ago)) + MediaAttachment.remote.cached.where(MediaAttachment.arel_table[:created_at].lt(@retention_period.ago)).where(MediaAttachment.arel_table[:updated_at].lt(@retention_period.ago)) end def orphaned_media_attachments - MediaAttachment.unscoped.unattached.where(MediaAttachment.arel_table[:created_at].lt(TTL.ago)) + MediaAttachment.unattached.where(MediaAttachment.arel_table[:created_at].lt(TTL.ago)) end def retention_period? diff --git a/app/models/admin/status_filter.rb b/app/models/admin/status_filter.rb index 645c2e62075535..4708785e7d4b74 100644 --- a/app/models/admin/status_filter.rb +++ b/app/models/admin/status_filter.rb @@ -32,7 +32,7 @@ def results def scope_for(key, _value) case key.to_s when 'media' - Status.joins(:media_attachments).merge(@account.media_attachments.reorder(nil)).group(:id).reorder('statuses.id desc') + Status.joins(:media_attachments).merge(@account.media_attachments).group(:id).reorder('statuses.id desc') else raise Mastodon::InvalidParameterError, "Unknown filter: #{key}" end diff --git a/app/models/media_attachment.rb b/app/models/media_attachment.rb index b567003fb9507e..1f40e5725ebc93 100644 --- a/app/models/media_attachment.rb +++ b/app/models/media_attachment.rb @@ -205,12 +205,11 @@ class MediaAttachment < ApplicationRecord validates :thumbnail, absence: true, if: -> { local? && !audio_or_video? } scope :attached, -> { where.not(status_id: nil).or(where.not(scheduled_status_id: nil)) } - scope :unattached, -> { where(status_id: nil, scheduled_status_id: nil) } + scope :cached, -> { remote.where.not(file_file_name: nil) } scope :local, -> { where(remote_url: '') } + scope :ordered, -> { order(id: :asc) } scope :remote, -> { where.not(remote_url: '') } - scope :cached, -> { remote.where.not(file_file_name: nil) } - - default_scope { order(id: :asc) } + scope :unattached, -> { where(status_id: nil, scheduled_status_id: nil) } attr_accessor :skip_download diff --git a/app/services/backup_service.rb b/app/services/backup_service.rb index 3ef0366c3c5fc9..886bab1ebfe54d 100644 --- a/app/services/backup_service.rb +++ b/app/services/backup_service.rb @@ -72,7 +72,7 @@ def build_archive! end def dump_media_attachments!(zipfile) - MediaAttachment.attached.where(account: account).reorder(nil).find_in_batches do |media_attachments| + MediaAttachment.attached.where(account: account).find_in_batches do |media_attachments| media_attachments.each do |m| path = m.file&.path next unless path diff --git a/app/services/clear_domain_media_service.rb b/app/services/clear_domain_media_service.rb index 7bf2d62fb004e4..d3ad43e707105b 100644 --- a/app/services/clear_domain_media_service.rb +++ b/app/services/clear_domain_media_service.rb @@ -43,7 +43,7 @@ def blocked_domain_accounts end def media_from_blocked_domain - MediaAttachment.joins(:account).merge(blocked_domain_accounts).reorder(nil) + MediaAttachment.joins(:account).merge(blocked_domain_accounts) end def emojis_from_blocked_domains diff --git a/app/services/delete_account_service.rb b/app/services/delete_account_service.rb index 190a72e5c5f178..7c7cb97df2643c 100644 --- a/app/services/delete_account_service.rb +++ b/app/services/delete_account_service.rb @@ -165,7 +165,7 @@ def purge_mentions! end def purge_media_attachments! - @account.media_attachments.reorder(nil).find_each do |media_attachment| + @account.media_attachments.find_each do |media_attachment| next if keep_account_record? && reported_status_ids.include?(media_attachment.status_id) media_attachment.destroy diff --git a/app/services/suspend_account_service.rb b/app/services/suspend_account_service.rb index e79c2d3d81f51b..8d5446f1a88099 100644 --- a/app/services/suspend_account_service.rb +++ b/app/services/suspend_account_service.rb @@ -65,7 +65,7 @@ def unmerge_from_list_timelines! def privatize_media_attachments! attachment_names = MediaAttachment.attachment_definitions.keys - @account.media_attachments.reorder(nil).find_each do |media_attachment| + @account.media_attachments.find_each do |media_attachment| attachment_names.each do |attachment_name| attachment = media_attachment.public_send(attachment_name) styles = MediaAttachment::DEFAULT_STYLES | attachment.styles.keys diff --git a/app/services/unsuspend_account_service.rb b/app/services/unsuspend_account_service.rb index 93cd04a9438a6c..652dd6a84500da 100644 --- a/app/services/unsuspend_account_service.rb +++ b/app/services/unsuspend_account_service.rb @@ -61,7 +61,7 @@ def merge_into_list_timelines! def publish_media_attachments! attachment_names = MediaAttachment.attachment_definitions.keys - @account.media_attachments.reorder(nil).find_each do |media_attachment| + @account.media_attachments.find_each do |media_attachment| attachment_names.each do |attachment_name| attachment = media_attachment.public_send(attachment_name) styles = MediaAttachment::DEFAULT_STYLES | attachment.styles.keys diff --git a/spec/services/activitypub/process_status_update_service_spec.rb b/spec/services/activitypub/process_status_update_service_spec.rb index 9d91f31cc5c2c5..53cbaf4cc1aaaa 100644 --- a/spec/services/activitypub/process_status_update_service_spec.rb +++ b/spec/services/activitypub/process_status_update_service_spec.rb @@ -384,7 +384,7 @@ def poll_option_json(name, votes) end it 'updates the existing media attachment in-place' do - media_attachment = status.media_attachments.reload.first + media_attachment = status.media_attachments.ordered.reload.first expect(media_attachment).to_not be_nil expect(media_attachment.remote_url).to eq 'https://example.com/foo.png' From 85662a5a57531af5402a6777d0b1089e78c56815 Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 30 Nov 2023 14:47:01 +0100 Subject: [PATCH 10/17] Change `img-src` and `media-src` CSP directives to not include `https:` (#28025) --- app/lib/content_security_policy.rb | 4 ++-- config/initializers/content_security_policy.rb | 10 +++++----- spec/lib/content_security_policy_spec.rb | 14 +++++++------- spec/requests/content_security_policy_spec.rb | 6 +++--- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/app/lib/content_security_policy.rb b/app/lib/content_security_policy.rb index e8fcf76a6564d7..966e41f03b3f34 100644 --- a/app/lib/content_security_policy.rb +++ b/app/lib/content_security_policy.rb @@ -9,8 +9,8 @@ def assets_host url_from_configured_asset_host || url_from_base_host end - def media_host - cdn_host_value || assets_host + def media_hosts + [assets_host, cdn_host_value].compact end private diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb index 3fb80bac49ab72..a8b61e356f01ab 100644 --- a/config/initializers/content_security_policy.rb +++ b/config/initializers/content_security_policy.rb @@ -10,7 +10,7 @@ policy = ContentSecurityPolicy.new assets_host = policy.assets_host -media_host = policy.media_host +media_hosts = policy.media_hosts def sso_host return unless ENV['ONE_CLICK_SSO_LOGIN'] == 'true' @@ -35,9 +35,9 @@ def sso_host p.default_src :none p.frame_ancestors :none p.font_src :self, assets_host - p.img_src :self, :https, :data, :blob, assets_host + p.img_src :self, :data, :blob, *media_hosts p.style_src :self, assets_host - p.media_src :self, :https, :data, assets_host + p.media_src :self, :data, *media_hosts p.frame_src :self, :https p.manifest_src :self, assets_host @@ -54,10 +54,10 @@ def sso_host webpacker_public_host = ENV.fetch('WEBPACKER_DEV_SERVER_PUBLIC', Webpacker.config.dev_server[:public]) webpacker_urls = %w(ws http).map { |protocol| "#{protocol}#{Webpacker.dev_server.https? ? 's' : ''}://#{webpacker_public_host}" } - p.connect_src :self, :data, :blob, assets_host, media_host, Rails.configuration.x.streaming_api_base_url, *webpacker_urls + p.connect_src :self, :data, :blob, *media_hosts, Rails.configuration.x.streaming_api_base_url, *webpacker_urls p.script_src :self, :unsafe_inline, :unsafe_eval, assets_host else - p.connect_src :self, :data, :blob, assets_host, media_host, Rails.configuration.x.streaming_api_base_url + p.connect_src :self, :data, :blob, *media_hosts, Rails.configuration.x.streaming_api_base_url p.script_src :self, assets_host, "'wasm-unsafe-eval'" end end diff --git a/spec/lib/content_security_policy_spec.rb b/spec/lib/content_security_policy_spec.rb index 2e92f815acc897..4286f14980a682 100644 --- a/spec/lib/content_security_policy_spec.rb +++ b/spec/lib/content_security_policy_spec.rb @@ -59,10 +59,10 @@ end end - describe '#media_host' do + describe '#media_hosts' do context 'when there is no configured CDN' do it 'defaults to using the assets_host value' do - expect(subject.media_host).to eq(subject.assets_host) + expect(subject.media_hosts).to contain_exactly(subject.assets_host) end end @@ -74,7 +74,7 @@ end it 'uses the s3 alias host value' do - expect(subject.media_host).to eq 'https://asset-host.s3-alias.example' + expect(subject.media_hosts).to contain_exactly(subject.assets_host, 'https://asset-host.s3-alias.example') end end @@ -86,7 +86,7 @@ end it 'uses the s3 alias host value and preserves the path' do - expect(subject.media_host).to eq 'https://asset-host.s3-alias.example/pathname/' + expect(subject.media_hosts).to contain_exactly(subject.assets_host, 'https://asset-host.s3-alias.example/pathname/') end end @@ -98,7 +98,7 @@ end it 'uses the s3 cloudfront host value' do - expect(subject.media_host).to eq 'https://asset-host.s3-cloudfront.example' + expect(subject.media_hosts).to contain_exactly(subject.assets_host, 'https://asset-host.s3-cloudfront.example') end end @@ -110,7 +110,7 @@ end it 'uses the azure alias host value' do - expect(subject.media_host).to eq 'https://asset-host.azure-alias.example' + expect(subject.media_hosts).to contain_exactly(subject.assets_host, 'https://asset-host.azure-alias.example') end end @@ -122,7 +122,7 @@ end it 'uses the s3 hostname host value' do - expect(subject.media_host).to eq 'https://asset-host.s3.example' + expect(subject.media_hosts).to contain_exactly(subject.assets_host, 'https://asset-host.s3.example') end end end diff --git a/spec/requests/content_security_policy_spec.rb b/spec/requests/content_security_policy_spec.rb index 7eb27d61d615ca..7610e698cdf4cd 100644 --- a/spec/requests/content_security_policy_spec.rb +++ b/spec/requests/content_security_policy_spec.rb @@ -12,15 +12,15 @@ "default-src 'none'", "frame-ancestors 'none'", "font-src 'self' https://cb6e6126.ngrok.io", - "img-src 'self' https: data: blob: https://cb6e6126.ngrok.io", + "img-src 'self' data: blob: https://cb6e6126.ngrok.io", "style-src 'self' https://cb6e6126.ngrok.io 'nonce-ZbA+JmE7+bK8F5qvADZHuQ=='", - "media-src 'self' https: data: https://cb6e6126.ngrok.io", + "media-src 'self' data: https://cb6e6126.ngrok.io", "frame-src 'self' https:", "manifest-src 'self' https://cb6e6126.ngrok.io", "form-action 'self'", "child-src 'self' blob: https://cb6e6126.ngrok.io", "worker-src 'self' blob: https://cb6e6126.ngrok.io", - "connect-src 'self' data: blob: https://cb6e6126.ngrok.io https://cb6e6126.ngrok.io ws://localhost:4000", + "connect-src 'self' data: blob: https://cb6e6126.ngrok.io ws://localhost:4000", "script-src 'self' https://cb6e6126.ngrok.io 'wasm-unsafe-eval'" ) end From b20af17a2c7dec49bc7ad1ec6706c5b02bf4f498 Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 30 Nov 2023 14:47:07 +0100 Subject: [PATCH 11/17] Fix onboarding step descriptions being truncated on narrow screens (#28021) --- app/javascript/styles/mastodon/components.scss | 6 ------ 1 file changed, 6 deletions(-) diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 9c3d9dc2c5202f..2106b529d6c639 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -2732,22 +2732,16 @@ $ui-header-height: 55px; &__description { flex: 1 1 auto; line-height: 20px; - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; h6 { color: $highlight-text-color; font-weight: 500; font-size: 14px; - overflow: hidden; - text-overflow: ellipsis; } p { color: $darker-text-color; overflow: hidden; - text-overflow: ellipsis; } } } From a8473f582d0d25ac0a2ad385cf3915e8012a3646 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 30 Nov 2023 08:55:20 -0500 Subject: [PATCH 12/17] Add zeitwerk inflector for cli->CLI (#27635) --- config/initializers/inflections.rb | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index 3d17509456c0fb..ba459e19f22c0d 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -13,21 +13,22 @@ # end ActiveSupport::Inflector.inflections(:en) do |inflect| - inflect.acronym 'StatsD' - inflect.acronym 'OEmbed' - inflect.acronym 'OStatus' inflect.acronym 'ActivityPub' - inflect.acronym 'PubSubHubbub' inflect.acronym 'ActivityStreams' - inflect.acronym 'JsonLd' - inflect.acronym 'Ed25519' - inflect.acronym 'TOC' - inflect.acronym 'RSS' - inflect.acronym 'REST' - inflect.acronym 'URL' inflect.acronym 'ASCII' + inflect.acronym 'CLI' inflect.acronym 'DeepL' inflect.acronym 'DSL' + inflect.acronym 'Ed25519' + inflect.acronym 'JsonLd' + inflect.acronym 'OEmbed' + inflect.acronym 'OStatus' + inflect.acronym 'PubSubHubbub' + inflect.acronym 'REST' + inflect.acronym 'RSS' + inflect.acronym 'StatsD' + inflect.acronym 'TOC' + inflect.acronym 'URL' inflect.singular 'data', 'data' end From e7c340a63475713d7f55b92fb8c963478f4d622a Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 30 Nov 2023 08:59:46 -0500 Subject: [PATCH 13/17] Spec coverage for missing `q` param and error conditions in `api/v2/search` controller (#27842) --- app/controllers/api/v2/search_controller.rb | 31 ++++++++++-- .../api/v2/search_controller_spec.rb | 48 +++++++++++++++++++ 2 files changed, 75 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/v2/search_controller.rb b/app/controllers/api/v2/search_controller.rb index 35be549305aaac..4339bee21e3aad 100644 --- a/app/controllers/api/v2/search_controller.rb +++ b/app/controllers/api/v2/search_controller.rb @@ -8,6 +8,11 @@ class Api::V2::SearchController < Api::BaseController before_action -> { authorize_if_got_token! :read, :'read:search' } before_action :validate_search_params! + with_options unless: :user_signed_in? do + before_action :query_pagination_error, if: :pagination_requested? + before_action :remote_resolve_error, if: :remote_resolve_requested? + end + def index @search = Search.new(search_results) render json: @search, serializer: REST::SearchSerializer @@ -21,12 +26,22 @@ def index def validate_search_params! params.require(:q) + end + + def query_pagination_error + render json: { error: 'Search queries pagination is not supported without authentication' }, status: 401 + end - return if user_signed_in? + def remote_resolve_error + render json: { error: 'Search queries that resolve remote resources are not supported without authentication' }, status: 401 + end - return render json: { error: 'Search queries pagination is not supported without authentication' }, status: 401 if params[:offset].present? + def remote_resolve_requested? + truthy_param?(:resolve) + end - render json: { error: 'Search queries that resolve remote resources are not supported without authentication' }, status: 401 if truthy_param?(:resolve) + def pagination_requested? + params[:offset].present? end def search_results @@ -34,7 +49,15 @@ def search_results params[:q], current_account, limit_param(RESULTS_LIMIT), - search_params.merge(resolve: truthy_param?(:resolve), exclude_unreviewed: truthy_param?(:exclude_unreviewed), following: truthy_param?(:following)) + combined_search_params + ) + end + + def combined_search_params + search_params.merge( + resolve: truthy_param?(:resolve), + exclude_unreviewed: truthy_param?(:exclude_unreviewed), + following: truthy_param?(:following) ) end diff --git a/spec/controllers/api/v2/search_controller_spec.rb b/spec/controllers/api/v2/search_controller_spec.rb index d3ff42d6a04f3b..a16716a10c4309 100644 --- a/spec/controllers/api/v2/search_controller_spec.rb +++ b/spec/controllers/api/v2/search_controller_spec.rb @@ -34,6 +34,26 @@ expect(body_as_json[:accounts].pluck(:id)).to contain_exactly(bob.id.to_s, ana.id.to_s, tom.id.to_s) end + context 'with truthy `resolve`' do + let(:params) { { q: 'test1', resolve: '1' } } + + it 'returns http unauthorized' do + get :index, params: params + + expect(response).to have_http_status(200) + end + end + + context 'with `offset`' do + let(:params) { { q: 'test1', offset: 1 } } + + it 'returns http unauthorized' do + get :index, params: params + + expect(response).to have_http_status(200) + end + end + context 'with following=true' do let(:params) { { q: 'test', type: 'accounts', following: 'true' } } @@ -48,6 +68,26 @@ end end end + + context 'when search raises syntax error' do + before { allow(Search).to receive(:new).and_raise(Mastodon::SyntaxError) } + + it 'returns http unprocessable_entity' do + get :index, params: params + + expect(response).to have_http_status(422) + end + end + + context 'when search raises not found error' do + before { allow(Search).to receive(:new).and_raise(ActiveRecord::RecordNotFound) } + + it 'returns http not_found' do + get :index, params: params + + expect(response).to have_http_status(404) + end + end end end @@ -59,6 +99,12 @@ get :index, params: search_params end + context 'without a `q` param' do + it 'returns http bad_request' do + expect(response).to have_http_status(400) + end + end + context 'with a `q` shorter than 5 characters' do let(:search_params) { { q: 'test' } } @@ -79,6 +125,7 @@ it 'returns http unauthorized' do expect(response).to have_http_status(401) + expect(response.body).to match('resolve remote resources') end end @@ -87,6 +134,7 @@ it 'returns http unauthorized' do expect(response).to have_http_status(401) + expect(response.body).to match('pagination is not supported') end end end From 0530ce5e9575c09464847412f43852f438b0494e Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 30 Nov 2023 09:28:05 -0500 Subject: [PATCH 14/17] Convert accounts controller spec to request spec (#28126) --- .../accounts_spec.rb} | 158 +++++++++--------- 1 file changed, 80 insertions(+), 78 deletions(-) rename spec/{controllers/accounts_controller_spec.rb => requests/accounts_spec.rb} (56%) diff --git a/spec/controllers/accounts_controller_spec.rb b/spec/requests/accounts_spec.rb similarity index 56% rename from spec/controllers/accounts_controller_spec.rb rename to spec/requests/accounts_spec.rb index 542a748784adcd..bf067cdc38ac56 100644 --- a/spec/controllers/accounts_controller_spec.rb +++ b/spec/requests/accounts_spec.rb @@ -2,23 +2,22 @@ require 'rails_helper' -RSpec.describe AccountsController do - render_views - +describe 'Accounts show response' do let(:account) { Fabricate(:account) } - describe 'unapproved account check' do + context 'with an unapproved account' do before { account.user.update(approved: false) } it 'returns http not found' do %w(html json rss).each do |format| - get :show, params: { username: account.username, format: format } + get short_account_path(username: account.username), as: format + expect(response).to have_http_status(404) end end end - describe 'permanently suspended account check' do + context 'with a permanently suspended account' do before do account.suspend! account.deletion_request.destroy @@ -26,25 +25,26 @@ it 'returns http gone' do %w(html json rss).each do |format| - get :show, params: { username: account.username, format: format } + get short_account_path(username: account.username), as: format + expect(response).to have_http_status(410) end end end - describe 'temporarily suspended account check' do + context 'with a temporarily suspended account' do before { account.suspend! } it 'returns appropriate http response code' do { html: 403, json: 200, rss: 403 }.each do |format, code| - get :show, params: { username: account.username, format: format } + get short_account_path(username: account.username), as: format expect(response).to have_http_status(code) end end end - describe 'GET #show' do + describe 'GET to short username paths' do context 'with existing statuses' do let!(:status) { Fabricate(:status, account: account) } let!(:status_reply) { Fabricate(:status, account: account, thread: Fabricate(:status)) } @@ -66,17 +66,17 @@ shared_examples 'common HTML response' do it 'returns a standard HTML response', :aggregate_failures do - expect(response).to have_http_status(200) + expect(response) + .to have_http_status(200) + .and render_template(:show) expect(response.headers['Link'].to_s).to include ActivityPub::TagManager.instance.uri_for(account) - - expect(response).to render_template(:show) end end context 'with a normal account in an HTML request' do before do - get :show, params: { username: account.username, format: format } + get short_account_path(username: account.username), as: format end it_behaves_like 'common HTML response' @@ -84,8 +84,7 @@ context 'with replies' do before do - allow(controller).to receive(:replies_requested?).and_return(true) - get :show, params: { username: account.username, format: format } + get short_account_with_replies_path(username: account.username), as: format end it_behaves_like 'common HTML response' @@ -93,8 +92,7 @@ context 'with media' do before do - allow(controller).to receive(:media_requested?).and_return(true) - get :show, params: { username: account.username, format: format } + get short_account_media_path(username: account.username), as: format end it_behaves_like 'common HTML response' @@ -106,9 +104,8 @@ let!(:status_tag) { Fabricate(:status, account: account) } before do - allow(controller).to receive(:tag_requested?).and_return(true) status_tag.tags << tag - get :show, params: { username: account.username, format: format, tag: tag.to_param } + get short_account_tag_path(username: account.username, tag: tag), as: format end it_behaves_like 'common HTML response' @@ -117,21 +114,25 @@ context 'with JSON' do let(:authorized_fetch_mode) { false } - let(:format) { 'json' } + let(:headers) { { 'ACCEPT' => 'application/json' } } - before do - allow(controller).to receive(:authorized_fetch_mode?).and_return(authorized_fetch_mode) + around do |example| + ClimateControl.modify AUTHORIZED_FETCH: authorized_fetch_mode.to_s do + example.run + end end context 'with a normal account in a JSON request' do before do - get :show, params: { username: account.username, format: format } + get short_account_path(username: account.username), headers: headers end it 'returns a JSON version of the account', :aggregate_failures do - expect(response).to have_http_status(200) - - expect(response.media_type).to eq 'application/activity+json' + expect(response) + .to have_http_status(200) + .and have_attributes( + media_type: eq('application/activity+json') + ) expect(body_as_json).to include(:id, :type, :preferredUsername, :inbox, :publicKey, :name, :summary) end @@ -152,13 +153,15 @@ before do sign_in(user) - get :show, params: { username: account.username, format: format } + get short_account_path(username: account.username), headers: headers.merge({ 'Cookie' => '123' }) end it 'returns a private JSON version of the account', :aggregate_failures do - expect(response).to have_http_status(200) - - expect(response.media_type).to eq 'application/activity+json' + expect(response) + .to have_http_status(200) + .and have_attributes( + media_type: eq('application/activity+json') + ) expect(response.headers['Cache-Control']).to include 'private' @@ -170,14 +173,15 @@ let(:remote_account) { Fabricate(:account, domain: 'example.com') } before do - allow(controller).to receive(:signed_request_actor).and_return(remote_account) - get :show, params: { username: account.username, format: format } + get short_account_path(username: account.username), headers: headers, sign_with: remote_account end it 'returns a JSON version of the account', :aggregate_failures do - expect(response).to have_http_status(200) - - expect(response.media_type).to eq 'application/activity+json' + expect(response) + .to have_http_status(200) + .and have_attributes( + media_type: eq('application/activity+json') + ) expect(body_as_json).to include(:id, :type, :preferredUsername, :inbox, :publicKey, :name, :summary) end @@ -188,12 +192,13 @@ let(:authorized_fetch_mode) { true } it 'returns a private signature JSON version of the account', :aggregate_failures do - expect(response).to have_http_status(200) - - expect(response.media_type).to eq 'application/activity+json' + expect(response) + .to have_http_status(200) + .and have_attributes( + media_type: eq('application/activity+json') + ) expect(response.headers['Cache-Control']).to include 'private' - expect(response.headers['Vary']).to include 'Signature' expect(body_as_json).to include(:id, :type, :preferredUsername, :inbox, :publicKey, :name, :summary) @@ -207,60 +212,58 @@ context 'with a normal account in an RSS request' do before do - get :show, params: { username: account.username, format: format } + get short_account_path(username: account.username, format: format) end it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie' it 'responds with correct statuses', :aggregate_failures do expect(response).to have_http_status(200) - expect(response.body).to include_status_tag(status_media) - expect(response.body).to include_status_tag(status_self_reply) - expect(response.body).to include_status_tag(status) - expect(response.body).to_not include_status_tag(status_direct) - expect(response.body).to_not include_status_tag(status_private) - expect(response.body).to_not include_status_tag(status_reblog.reblog) - expect(response.body).to_not include_status_tag(status_reply) + expect(response.body).to include(status_tag_for(status_media)) + expect(response.body).to include(status_tag_for(status_self_reply)) + expect(response.body).to include(status_tag_for(status)) + expect(response.body).to_not include(status_tag_for(status_direct)) + expect(response.body).to_not include(status_tag_for(status_private)) + expect(response.body).to_not include(status_tag_for(status_reblog.reblog)) + expect(response.body).to_not include(status_tag_for(status_reply)) end end context 'with replies' do before do - allow(controller).to receive(:replies_requested?).and_return(true) - get :show, params: { username: account.username, format: format } + get short_account_with_replies_path(username: account.username, format: format) end it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie' it 'responds with correct statuses with replies', :aggregate_failures do expect(response).to have_http_status(200) - expect(response.body).to include_status_tag(status_media) - expect(response.body).to include_status_tag(status_reply) - expect(response.body).to include_status_tag(status_self_reply) - expect(response.body).to include_status_tag(status) - expect(response.body).to_not include_status_tag(status_direct) - expect(response.body).to_not include_status_tag(status_private) - expect(response.body).to_not include_status_tag(status_reblog.reblog) + expect(response.body).to include(status_tag_for(status_media)) + expect(response.body).to include(status_tag_for(status_reply)) + expect(response.body).to include(status_tag_for(status_self_reply)) + expect(response.body).to include(status_tag_for(status)) + expect(response.body).to_not include(status_tag_for(status_direct)) + expect(response.body).to_not include(status_tag_for(status_private)) + expect(response.body).to_not include(status_tag_for(status_reblog.reblog)) end end context 'with media' do before do - allow(controller).to receive(:media_requested?).and_return(true) - get :show, params: { username: account.username, format: format } + get short_account_media_path(username: account.username, format: format) end it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie' it 'responds with correct statuses with media', :aggregate_failures do expect(response).to have_http_status(200) - expect(response.body).to include_status_tag(status_media) - expect(response.body).to_not include_status_tag(status_direct) - expect(response.body).to_not include_status_tag(status_private) - expect(response.body).to_not include_status_tag(status_reblog.reblog) - expect(response.body).to_not include_status_tag(status_reply) - expect(response.body).to_not include_status_tag(status_self_reply) - expect(response.body).to_not include_status_tag(status) + expect(response.body).to include(status_tag_for(status_media)) + expect(response.body).to_not include(status_tag_for(status_direct)) + expect(response.body).to_not include(status_tag_for(status_private)) + expect(response.body).to_not include(status_tag_for(status_reblog.reblog)) + expect(response.body).to_not include(status_tag_for(status_reply)) + expect(response.body).to_not include(status_tag_for(status_self_reply)) + expect(response.body).to_not include(status_tag_for(status)) end end @@ -270,30 +273,29 @@ let!(:status_tag) { Fabricate(:status, account: account) } before do - allow(controller).to receive(:tag_requested?).and_return(true) status_tag.tags << tag - get :show, params: { username: account.username, format: format, tag: tag.to_param } + get short_account_tag_path(username: account.username, tag: tag, format: format) end it_behaves_like 'cacheable response', expects_vary: 'Accept, Accept-Language, Cookie' it 'responds with correct statuses with a tag', :aggregate_failures do expect(response).to have_http_status(200) - expect(response.body).to include_status_tag(status_tag) - expect(response.body).to_not include_status_tag(status_direct) - expect(response.body).to_not include_status_tag(status_media) - expect(response.body).to_not include_status_tag(status_private) - expect(response.body).to_not include_status_tag(status_reblog.reblog) - expect(response.body).to_not include_status_tag(status_reply) - expect(response.body).to_not include_status_tag(status_self_reply) - expect(response.body).to_not include_status_tag(status) + expect(response.body).to include(status_tag_for(status_tag)) + expect(response.body).to_not include(status_tag_for(status_direct)) + expect(response.body).to_not include(status_tag_for(status_media)) + expect(response.body).to_not include(status_tag_for(status_private)) + expect(response.body).to_not include(status_tag_for(status_reblog.reblog)) + expect(response.body).to_not include(status_tag_for(status_reply)) + expect(response.body).to_not include(status_tag_for(status_self_reply)) + expect(response.body).to_not include(status_tag_for(status)) end end end end end - def include_status_tag(status) - include ActivityPub::TagManager.instance.url_for(status) + def status_tag_for(status) + ActivityPub::TagManager.instance.url_for(status) end end From 1f1c75bba56f4b22c5f4c745b8f50a002001213c Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 30 Nov 2023 09:39:41 -0500 Subject: [PATCH 15/17] File cleanup/organization in `controllers/concerns` (#27846) --- app/controllers/admin/export_domain_allows_controller.rb | 2 +- app/controllers/admin/export_domain_blocks_controller.rb | 2 +- app/controllers/api/base_controller.rb | 6 +++--- app/controllers/auth/confirmations_controller.rb | 2 +- app/controllers/auth/registrations_controller.rb | 2 +- app/controllers/auth/sessions_controller.rb | 2 +- .../export_controller_concern.rb} | 2 +- .../concerns/{ => api}/access_token_tracking_concern.rb | 2 +- .../{api_caching_concern.rb => api/caching_concern.rb} | 2 +- app/controllers/concerns/{ => api}/rate_limit_headers.rb | 2 +- app/controllers/concerns/{ => auth}/captcha_concern.rb | 2 +- .../concerns/{ => auth}/registration_spam_concern.rb | 2 +- .../{ => auth}/two_factor_authentication_concern.rb | 2 +- .../concerns/{ => settings}/export_controller_concern.rb | 2 +- .../settings/exports/blocked_accounts_controller.rb | 2 +- .../settings/exports/blocked_domains_controller.rb | 2 +- app/controllers/settings/exports/bookmarks_controller.rb | 2 +- .../settings/exports/following_accounts_controller.rb | 2 +- app/controllers/settings/exports/lists_controller.rb | 2 +- .../settings/exports/muted_accounts_controller.rb | 2 +- .../concerns/{ => api}/rate_limit_headers_spec.rb | 4 ++-- .../{ => settings}/export_controller_concern_spec.rb | 4 ++-- 22 files changed, 26 insertions(+), 26 deletions(-) rename app/controllers/concerns/{admin_export_controller_concern.rb => admin/export_controller_concern.rb} (92%) rename app/controllers/concerns/{ => api}/access_token_tracking_concern.rb (92%) rename app/controllers/concerns/{api_caching_concern.rb => api/caching_concern.rb} (93%) rename app/controllers/concerns/{ => api}/rate_limit_headers.rb (98%) rename app/controllers/concerns/{ => auth}/captcha_concern.rb (98%) rename app/controllers/concerns/{ => auth}/registration_spam_concern.rb (81%) rename app/controllers/concerns/{ => auth}/two_factor_authentication_concern.rb (98%) rename app/controllers/concerns/{ => settings}/export_controller_concern.rb (93%) rename spec/controllers/concerns/{ => api}/rate_limit_headers_spec.rb (95%) rename spec/controllers/concerns/{ => settings}/export_controller_concern_spec.rb (89%) diff --git a/app/controllers/admin/export_domain_allows_controller.rb b/app/controllers/admin/export_domain_allows_controller.rb index adfc39da21c872..ca88c6525e0ee6 100644 --- a/app/controllers/admin/export_domain_allows_controller.rb +++ b/app/controllers/admin/export_domain_allows_controller.rb @@ -4,7 +4,7 @@ module Admin class ExportDomainAllowsController < BaseController - include AdminExportControllerConcern + include Admin::ExportControllerConcern before_action :set_dummy_import!, only: [:new] diff --git a/app/controllers/admin/export_domain_blocks_controller.rb b/app/controllers/admin/export_domain_blocks_controller.rb index 816422d4ffcfae..433b8a158787a7 100644 --- a/app/controllers/admin/export_domain_blocks_controller.rb +++ b/app/controllers/admin/export_domain_blocks_controller.rb @@ -4,7 +4,7 @@ module Admin class ExportDomainBlocksController < BaseController - include AdminExportControllerConcern + include Admin::ExportControllerConcern before_action :set_dummy_import!, only: [:new] diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb index 135c5756589667..dc760297de7e0b 100644 --- a/app/controllers/api/base_controller.rb +++ b/app/controllers/api/base_controller.rb @@ -4,9 +4,9 @@ class Api::BaseController < ApplicationController DEFAULT_STATUSES_LIMIT = 20 DEFAULT_ACCOUNTS_LIMIT = 40 - include RateLimitHeaders - include AccessTokenTrackingConcern - include ApiCachingConcern + include Api::RateLimitHeaders + include Api::AccessTokenTrackingConcern + include Api::CachingConcern include Api::ContentSecurityPolicy skip_before_action :require_functional!, unless: :limited_federation_mode? diff --git a/app/controllers/auth/confirmations_controller.rb b/app/controllers/auth/confirmations_controller.rb index 05e4605f4e6a46..9f6be9c424d0c4 100644 --- a/app/controllers/auth/confirmations_controller.rb +++ b/app/controllers/auth/confirmations_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class Auth::ConfirmationsController < Devise::ConfirmationsController - include CaptchaConcern + include Auth::CaptchaConcern layout 'auth' diff --git a/app/controllers/auth/registrations_controller.rb b/app/controllers/auth/registrations_controller.rb index 8be7c5f192f185..4535ecdbd0e835 100644 --- a/app/controllers/auth/registrations_controller.rb +++ b/app/controllers/auth/registrations_controller.rb @@ -2,7 +2,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController include RegistrationHelper - include RegistrationSpamConcern + include Auth::RegistrationSpamConcern layout :determine_layout diff --git a/app/controllers/auth/sessions_controller.rb b/app/controllers/auth/sessions_controller.rb index 84d9d5e11ed6dd..148ad53755ef8f 100644 --- a/app/controllers/auth/sessions_controller.rb +++ b/app/controllers/auth/sessions_controller.rb @@ -10,7 +10,7 @@ class Auth::SessionsController < Devise::SessionsController prepend_before_action :check_suspicious!, only: [:create] - include TwoFactorAuthenticationConcern + include Auth::TwoFactorAuthenticationConcern before_action :set_body_classes diff --git a/app/controllers/concerns/admin_export_controller_concern.rb b/app/controllers/concerns/admin/export_controller_concern.rb similarity index 92% rename from app/controllers/concerns/admin_export_controller_concern.rb rename to app/controllers/concerns/admin/export_controller_concern.rb index 4ac48a04b7ced9..6228ae67fe1b9a 100644 --- a/app/controllers/concerns/admin_export_controller_concern.rb +++ b/app/controllers/concerns/admin/export_controller_concern.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module AdminExportControllerConcern +module Admin::ExportControllerConcern extend ActiveSupport::Concern private diff --git a/app/controllers/concerns/access_token_tracking_concern.rb b/app/controllers/concerns/api/access_token_tracking_concern.rb similarity index 92% rename from app/controllers/concerns/access_token_tracking_concern.rb rename to app/controllers/concerns/api/access_token_tracking_concern.rb index cf60cfb995ba49..bc6ae51c772d77 100644 --- a/app/controllers/concerns/access_token_tracking_concern.rb +++ b/app/controllers/concerns/api/access_token_tracking_concern.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module AccessTokenTrackingConcern +module Api::AccessTokenTrackingConcern extend ActiveSupport::Concern ACCESS_TOKEN_UPDATE_FREQUENCY = 24.hours.freeze diff --git a/app/controllers/concerns/api_caching_concern.rb b/app/controllers/concerns/api/caching_concern.rb similarity index 93% rename from app/controllers/concerns/api_caching_concern.rb rename to app/controllers/concerns/api/caching_concern.rb index 12264d514e50e9..55d7fe56d7b744 100644 --- a/app/controllers/concerns/api_caching_concern.rb +++ b/app/controllers/concerns/api/caching_concern.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module ApiCachingConcern +module Api::CachingConcern extend ActiveSupport::Concern def cache_if_unauthenticated! diff --git a/app/controllers/concerns/rate_limit_headers.rb b/app/controllers/concerns/api/rate_limit_headers.rb similarity index 98% rename from app/controllers/concerns/rate_limit_headers.rb rename to app/controllers/concerns/api/rate_limit_headers.rb index 5b83d8575ba5c4..fe57b6f6bd53e0 100644 --- a/app/controllers/concerns/rate_limit_headers.rb +++ b/app/controllers/concerns/api/rate_limit_headers.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module RateLimitHeaders +module Api::RateLimitHeaders extend ActiveSupport::Concern class_methods do diff --git a/app/controllers/concerns/captcha_concern.rb b/app/controllers/concerns/auth/captcha_concern.rb similarity index 98% rename from app/controllers/concerns/captcha_concern.rb rename to app/controllers/concerns/auth/captcha_concern.rb index 170c8f5e03a20f..cfd93978cea576 100644 --- a/app/controllers/concerns/captcha_concern.rb +++ b/app/controllers/concerns/auth/captcha_concern.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module CaptchaConcern +module Auth::CaptchaConcern extend ActiveSupport::Concern include Hcaptcha::Adapters::ViewMethods diff --git a/app/controllers/concerns/registration_spam_concern.rb b/app/controllers/concerns/auth/registration_spam_concern.rb similarity index 81% rename from app/controllers/concerns/registration_spam_concern.rb rename to app/controllers/concerns/auth/registration_spam_concern.rb index af434c985a0c96..9f4798b5372d59 100644 --- a/app/controllers/concerns/registration_spam_concern.rb +++ b/app/controllers/concerns/auth/registration_spam_concern.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module RegistrationSpamConcern +module Auth::RegistrationSpamConcern extend ActiveSupport::Concern def set_registration_form_time diff --git a/app/controllers/concerns/two_factor_authentication_concern.rb b/app/controllers/concerns/auth/two_factor_authentication_concern.rb similarity index 98% rename from app/controllers/concerns/two_factor_authentication_concern.rb rename to app/controllers/concerns/auth/two_factor_authentication_concern.rb index bc2d194c33ae35..effdb8d21c0885 100644 --- a/app/controllers/concerns/two_factor_authentication_concern.rb +++ b/app/controllers/concerns/auth/two_factor_authentication_concern.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module TwoFactorAuthenticationConcern +module Auth::TwoFactorAuthenticationConcern extend ActiveSupport::Concern included do diff --git a/app/controllers/concerns/export_controller_concern.rb b/app/controllers/concerns/settings/export_controller_concern.rb similarity index 93% rename from app/controllers/concerns/export_controller_concern.rb rename to app/controllers/concerns/settings/export_controller_concern.rb index e1792fd6bf2f71..2cf28cced87234 100644 --- a/app/controllers/concerns/export_controller_concern.rb +++ b/app/controllers/concerns/settings/export_controller_concern.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module ExportControllerConcern +module Settings::ExportControllerConcern extend ActiveSupport::Concern included do diff --git a/app/controllers/settings/exports/blocked_accounts_controller.rb b/app/controllers/settings/exports/blocked_accounts_controller.rb index 2190caa3619e6c..906564a3dcdcbd 100644 --- a/app/controllers/settings/exports/blocked_accounts_controller.rb +++ b/app/controllers/settings/exports/blocked_accounts_controller.rb @@ -3,7 +3,7 @@ module Settings module Exports class BlockedAccountsController < BaseController - include ExportControllerConcern + include Settings::ExportControllerConcern def index send_export_file diff --git a/app/controllers/settings/exports/blocked_domains_controller.rb b/app/controllers/settings/exports/blocked_domains_controller.rb index bee4b2431e374e..09dc52392f5cdd 100644 --- a/app/controllers/settings/exports/blocked_domains_controller.rb +++ b/app/controllers/settings/exports/blocked_domains_controller.rb @@ -3,7 +3,7 @@ module Settings module Exports class BlockedDomainsController < BaseController - include ExportControllerConcern + include Settings::ExportControllerConcern def index send_export_file diff --git a/app/controllers/settings/exports/bookmarks_controller.rb b/app/controllers/settings/exports/bookmarks_controller.rb index c12e2f147ac0cf..0321565b97c16c 100644 --- a/app/controllers/settings/exports/bookmarks_controller.rb +++ b/app/controllers/settings/exports/bookmarks_controller.rb @@ -3,7 +3,7 @@ module Settings module Exports class BookmarksController < BaseController - include ExportControllerConcern + include Settings::ExportControllerConcern def index send_export_file diff --git a/app/controllers/settings/exports/following_accounts_controller.rb b/app/controllers/settings/exports/following_accounts_controller.rb index acefcb15da67aa..0ac9031fb93fb7 100644 --- a/app/controllers/settings/exports/following_accounts_controller.rb +++ b/app/controllers/settings/exports/following_accounts_controller.rb @@ -3,7 +3,7 @@ module Settings module Exports class FollowingAccountsController < BaseController - include ExportControllerConcern + include Settings::ExportControllerConcern def index send_export_file diff --git a/app/controllers/settings/exports/lists_controller.rb b/app/controllers/settings/exports/lists_controller.rb index bc65f56a0eff65..d90c71e248aa9a 100644 --- a/app/controllers/settings/exports/lists_controller.rb +++ b/app/controllers/settings/exports/lists_controller.rb @@ -3,7 +3,7 @@ module Settings module Exports class ListsController < BaseController - include ExportControllerConcern + include Settings::ExportControllerConcern def index send_export_file diff --git a/app/controllers/settings/exports/muted_accounts_controller.rb b/app/controllers/settings/exports/muted_accounts_controller.rb index 50b7bf1f791192..e4b11589025e8f 100644 --- a/app/controllers/settings/exports/muted_accounts_controller.rb +++ b/app/controllers/settings/exports/muted_accounts_controller.rb @@ -3,7 +3,7 @@ module Settings module Exports class MutedAccountsController < BaseController - include ExportControllerConcern + include Settings::ExportControllerConcern def index send_export_file diff --git a/spec/controllers/concerns/rate_limit_headers_spec.rb b/spec/controllers/concerns/api/rate_limit_headers_spec.rb similarity index 95% rename from spec/controllers/concerns/rate_limit_headers_spec.rb rename to spec/controllers/concerns/api/rate_limit_headers_spec.rb index 1cdf741f4ded05..2050de2aed4ed8 100644 --- a/spec/controllers/concerns/rate_limit_headers_spec.rb +++ b/spec/controllers/concerns/api/rate_limit_headers_spec.rb @@ -2,9 +2,9 @@ require 'rails_helper' -describe RateLimitHeaders do +describe Api::RateLimitHeaders do controller(ApplicationController) do - include RateLimitHeaders + include Api::RateLimitHeaders def show head 200 diff --git a/spec/controllers/concerns/export_controller_concern_spec.rb b/spec/controllers/concerns/settings/export_controller_concern_spec.rb similarity index 89% rename from spec/controllers/concerns/export_controller_concern_spec.rb rename to spec/controllers/concerns/settings/export_controller_concern_spec.rb index 7f0a7c5b54a16d..a19af8689ac877 100644 --- a/spec/controllers/concerns/export_controller_concern_spec.rb +++ b/spec/controllers/concerns/settings/export_controller_concern_spec.rb @@ -2,9 +2,9 @@ require 'rails_helper' -describe ExportControllerConcern do +describe Settings::ExportControllerConcern do controller(ApplicationController) do - include ExportControllerConcern + include Settings::ExportControllerConcern def index send_export_file From 35deaaf90bec91f34b3e1f2afa472d5c3f2cdc75 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 30 Nov 2023 10:41:26 -0500 Subject: [PATCH 16/17] Reduce AbcSize complexity in `InitialStateSerializer` (#27782) --- .rubocop_todo.yml | 2 +- app/serializers/initial_state_serializer.rb | 48 ++++++++++++--------- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 43af4f670aeac8..dbd5beac2e7fe9 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -26,7 +26,7 @@ Lint/NonLocalExitFromIterator: # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes. Metrics/AbcSize: - Max: 144 + Max: 125 # Configuration parameters: CountBlocks, Max. Metrics/BlockNesting: diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb index b707d6fcb6ab84..a8af45990f5a9a 100644 --- a/app/serializers/initial_state_serializer.rb +++ b/app/serializers/initial_state_serializer.rb @@ -39,18 +39,18 @@ def meta if object.current_account store[:me] = object.current_account.id.to_s - store[:unfollow_modal] = object.current_account.user.setting_unfollow_modal - store[:boost_modal] = object.current_account.user.setting_boost_modal - store[:delete_modal] = object.current_account.user.setting_delete_modal - store[:auto_play_gif] = object.current_account.user.setting_auto_play_gif - store[:display_media] = object.current_account.user.setting_display_media - store[:expand_spoilers] = object.current_account.user.setting_expand_spoilers - store[:reduce_motion] = object.current_account.user.setting_reduce_motion - store[:disable_swiping] = object.current_account.user.setting_disable_swiping - store[:advanced_layout] = object.current_account.user.setting_advanced_layout - store[:use_blurhash] = object.current_account.user.setting_use_blurhash - store[:use_pending_items] = object.current_account.user.setting_use_pending_items - store[:show_trends] = Setting.trends && object.current_account.user.setting_trends + store[:unfollow_modal] = object_account_user.setting_unfollow_modal + store[:boost_modal] = object_account_user.setting_boost_modal + store[:delete_modal] = object_account_user.setting_delete_modal + store[:auto_play_gif] = object_account_user.setting_auto_play_gif + store[:display_media] = object_account_user.setting_display_media + store[:expand_spoilers] = object_account_user.setting_expand_spoilers + store[:reduce_motion] = object_account_user.setting_reduce_motion + store[:disable_swiping] = object_account_user.setting_disable_swiping + store[:advanced_layout] = object_account_user.setting_advanced_layout + store[:use_blurhash] = object_account_user.setting_use_blurhash + store[:use_pending_items] = object_account_user.setting_use_pending_items + store[:show_trends] = Setting.trends && object_account_user.setting_trends else store[:auto_play_gif] = Setting.auto_play_gif store[:display_media] = Setting.display_media @@ -71,9 +71,9 @@ def compose if object.current_account store[:me] = object.current_account.id.to_s - store[:default_privacy] = object.visibility || object.current_account.user.setting_default_privacy - store[:default_sensitive] = object.current_account.user.setting_default_sensitive - store[:default_language] = object.current_account.user.preferred_posting_language + store[:default_privacy] = object.visibility || object_account_user.setting_default_privacy + store[:default_sensitive] = object_account_user.setting_default_sensitive + store[:default_language] = object_account_user.preferred_posting_language end store[:text] = object.text if object.text @@ -89,11 +89,11 @@ def accounts associations: [:account_stat, :user, { moved_to_account: [:account_stat, :user] }] ) - store[object.current_account.id.to_s] = ActiveModelSerializers::SerializableResource.new(object.current_account, serializer: REST::AccountSerializer) if object.current_account - store[object.admin.id.to_s] = ActiveModelSerializers::SerializableResource.new(object.admin, serializer: REST::AccountSerializer) if object.admin - store[object.owner.id.to_s] = ActiveModelSerializers::SerializableResource.new(object.owner, serializer: REST::AccountSerializer) if object.owner - store[object.disabled_account.id.to_s] = ActiveModelSerializers::SerializableResource.new(object.disabled_account, serializer: REST::AccountSerializer) if object.disabled_account - store[object.moved_to_account.id.to_s] = ActiveModelSerializers::SerializableResource.new(object.moved_to_account, serializer: REST::AccountSerializer) if object.moved_to_account + store[object.current_account.id.to_s] = serialized_account(object.current_account) if object.current_account + store[object.admin.id.to_s] = serialized_account(object.admin) if object.admin + store[object.owner.id.to_s] = serialized_account(object.owner) if object.owner + store[object.disabled_account.id.to_s] = serialized_account(object.disabled_account) if object.disabled_account + store[object.moved_to_account.id.to_s] = serialized_account(object.moved_to_account) if object.moved_to_account store end @@ -108,6 +108,14 @@ def languages private + def object_account_user + object.current_account.user + end + + def serialized_account(account) + ActiveModelSerializers::SerializableResource.new(account, serializer: REST::AccountSerializer) + end + def instance_presenter @instance_presenter ||= InstancePresenter.new end From 963354978a0ba27c6ecea4a419b3330b3ad97733 Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 30 Nov 2023 16:43:26 +0100 Subject: [PATCH 17/17] Add `Account#unavailable?` and `Account#permanently_unavailable?` aliases (#28053) --- app/controllers/api/base_controller.rb | 2 +- .../accounts/follower_accounts_controller.rb | 2 +- .../accounts/following_accounts_controller.rb | 2 +- .../api/v1/accounts/statuses_controller.rb | 2 +- .../auth/registrations_controller.rb | 2 +- .../concerns/account_owned_concern.rb | 6 ++-- .../authorized_applications_controller.rb | 2 +- app/controllers/settings/base_controller.rb | 2 +- .../settings/deletes_controller.rb | 2 +- .../well_known/webfinger_controller.rb | 2 +- app/lib/account_statuses_filter.rb | 6 +--- app/lib/activitypub/activity/move.rb | 2 +- app/models/account.rb | 3 ++ app/models/user.rb | 2 +- app/policies/status_policy.rb | 2 +- .../activitypub/actor_serializer.rb | 22 +++++++------- app/serializers/rest/account_serializer.rb | 30 +++++++++---------- app/services/follow_service.rb | 2 +- app/services/notify_service.rb | 2 +- app/services/process_mentions_service.rb | 2 +- app/services/report_service.rb | 2 +- app/views/admin/accounts/_account.html.haml | 8 ++--- .../authorized_applications/index.html.haml | 2 +- app/workers/account_deletion_worker.rb | 2 +- .../suspended_user_cleanup_scheduler.rb | 4 +-- 25 files changed, 57 insertions(+), 58 deletions(-) diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb index dc760297de7e0b..c81ba32b08c086 100644 --- a/app/controllers/api/base_controller.rb +++ b/app/controllers/api/base_controller.rb @@ -105,7 +105,7 @@ def require_authenticated_user! end def require_not_suspended! - render json: { error: 'Your login is currently disabled' }, status: 403 if current_user&.account&.suspended? + render json: { error: 'Your login is currently disabled' }, status: 403 if current_user&.account&.unavailable? end def require_user! diff --git a/app/controllers/api/v1/accounts/follower_accounts_controller.rb b/app/controllers/api/v1/accounts/follower_accounts_controller.rb index 1a996d362aa4f4..21b1095f1845f8 100644 --- a/app/controllers/api/v1/accounts/follower_accounts_controller.rb +++ b/app/controllers/api/v1/accounts/follower_accounts_controller.rb @@ -26,7 +26,7 @@ def load_accounts end def hide_results? - @account.suspended? || (@account.hides_followers? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account)) + @account.unavailable? || (@account.hides_followers? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account)) end def default_accounts diff --git a/app/controllers/api/v1/accounts/following_accounts_controller.rb b/app/controllers/api/v1/accounts/following_accounts_controller.rb index 6e6ebae43b005c..1db521f79cbbd5 100644 --- a/app/controllers/api/v1/accounts/following_accounts_controller.rb +++ b/app/controllers/api/v1/accounts/following_accounts_controller.rb @@ -26,7 +26,7 @@ def load_accounts end def hide_results? - @account.suspended? || (@account.hides_following? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account)) + @account.unavailable? || (@account.hides_following? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account)) end def default_accounts diff --git a/app/controllers/api/v1/accounts/statuses_controller.rb b/app/controllers/api/v1/accounts/statuses_controller.rb index 51f541bd23ebc9..fe4279302fc891 100644 --- a/app/controllers/api/v1/accounts/statuses_controller.rb +++ b/app/controllers/api/v1/accounts/statuses_controller.rb @@ -19,7 +19,7 @@ def set_account end def load_statuses - @account.suspended? ? [] : cached_account_statuses + @account.unavailable? ? [] : cached_account_statuses end def cached_account_statuses diff --git a/app/controllers/auth/registrations_controller.rb b/app/controllers/auth/registrations_controller.rb index 4535ecdbd0e835..acfc0af0d9c0b6 100644 --- a/app/controllers/auth/registrations_controller.rb +++ b/app/controllers/auth/registrations_controller.rb @@ -120,7 +120,7 @@ def set_strikes end def require_not_suspended! - forbidden if current_account.suspended? + forbidden if current_account.unavailable? end def set_rules diff --git a/app/controllers/concerns/account_owned_concern.rb b/app/controllers/concerns/account_owned_concern.rb index 3fc0938bfc7672..2b132417f7cf33 100644 --- a/app/controllers/concerns/account_owned_concern.rb +++ b/app/controllers/concerns/account_owned_concern.rb @@ -34,8 +34,8 @@ def check_account_confirmation end def check_account_suspension - if @account.suspended_permanently? - permanent_suspension_response + if @account.permanently_unavailable? + permanent_unavailability_response elsif @account.suspended? && !skip_temporary_suspension_response? temporary_suspension_response end @@ -45,7 +45,7 @@ def skip_temporary_suspension_response? false end - def permanent_suspension_response + def permanent_unavailability_response expires_in(3.minutes, public: true) gone end diff --git a/app/controllers/oauth/authorized_applications_controller.rb b/app/controllers/oauth/authorized_applications_controller.rb index 350ae2e9062177..8440df6b7e69a9 100644 --- a/app/controllers/oauth/authorized_applications_controller.rb +++ b/app/controllers/oauth/authorized_applications_controller.rb @@ -31,7 +31,7 @@ def store_current_location end def require_not_suspended! - forbidden if current_account.suspended? + forbidden if current_account.unavailable? end def set_cache_headers diff --git a/app/controllers/settings/base_controller.rb b/app/controllers/settings/base_controller.rb index 64dcd47d120083..f15140aa2be3da 100644 --- a/app/controllers/settings/base_controller.rb +++ b/app/controllers/settings/base_controller.rb @@ -18,6 +18,6 @@ def set_cache_headers end def require_not_suspended! - forbidden if current_account.suspended? + forbidden if current_account.unavailable? end end diff --git a/app/controllers/settings/deletes_controller.rb b/app/controllers/settings/deletes_controller.rb index bb096567a9ceea..16c201b6b3f309 100644 --- a/app/controllers/settings/deletes_controller.rb +++ b/app/controllers/settings/deletes_controller.rb @@ -25,7 +25,7 @@ def resource_params end def require_not_suspended! - forbidden if current_account.suspended? + forbidden if current_account.unavailable? end def challenge_passed? diff --git a/app/controllers/well_known/webfinger_controller.rb b/app/controllers/well_known/webfinger_controller.rb index 4748940f7c2422..364fbf8a18c47e 100644 --- a/app/controllers/well_known/webfinger_controller.rb +++ b/app/controllers/well_known/webfinger_controller.rb @@ -42,7 +42,7 @@ def resource_param end def check_account_suspension - gone if @account.suspended_permanently? + gone if @account.permanently_unavailable? end def gone diff --git a/app/lib/account_statuses_filter.rb b/app/lib/account_statuses_filter.rb index d1365de586e42b..eb7592cdce09e1 100644 --- a/app/lib/account_statuses_filter.rb +++ b/app/lib/account_statuses_filter.rb @@ -32,7 +32,7 @@ def results private def initial_scope - return Status.none if suspended? + return Status.none if account.unavailable? if anonymous? account.statuses.where(visibility: %i(public unlisted)) @@ -95,10 +95,6 @@ def hashtag_scope end end - def suspended? - account.suspended? - end - def anonymous? current_account.nil? end diff --git a/app/lib/activitypub/activity/move.rb b/app/lib/activitypub/activity/move.rb index 8576ceccdf2bc7..7bd7e238e2db06 100644 --- a/app/lib/activitypub/activity/move.rb +++ b/app/lib/activitypub/activity/move.rb @@ -9,7 +9,7 @@ def perform target_account = ActivityPub::FetchRemoteAccountService.new.call(target_uri) - if target_account.nil? || target_account.suspended? || !target_account.also_known_as.include?(origin_account.uri) + if target_account.nil? || target_account.unavailable? || !target_account.also_known_as.include?(origin_account.uri) unmark_as_processing! return end diff --git a/app/models/account.rb b/app/models/account.rb index a25ebc4aaf15d3..03edcb2a25708c 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -246,6 +246,9 @@ def suspended_temporarily? suspended? && deletion_request.present? end + alias unavailable? suspended? + alias permanently_unavailable? suspended_permanently? + def suspend!(date: Time.now.utc, origin: :local, block_email: true) transaction do create_deletion_request! diff --git a/app/models/user.rb b/app/models/user.rb index 5185343af3e207..b0eba97c3636b4 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -250,7 +250,7 @@ def functional? end def functional_or_moved? - confirmed? && approved? && !disabled? && !account.suspended? && !account.memorial? + confirmed? && approved? && !disabled? && !account.unavailable? && !account.memorial? end def unconfirmed? diff --git a/app/policies/status_policy.rb b/app/policies/status_policy.rb index f3d0ffdbae2879..322d3aec5cdff7 100644 --- a/app/policies/status_policy.rb +++ b/app/policies/status_policy.rb @@ -8,7 +8,7 @@ def initialize(current_account, record, preloaded_relations = {}) end def show? - return false if author.suspended? + return false if author.unavailable? if requires_mention? owned? || mention_exists? diff --git a/app/serializers/activitypub/actor_serializer.rb b/app/serializers/activitypub/actor_serializer.rb index 31f39954fb077d..4ab48ff204b344 100644 --- a/app/serializers/activitypub/actor_serializer.rb +++ b/app/serializers/activitypub/actor_serializer.rb @@ -96,19 +96,19 @@ def preferred_username end def discoverable - object.suspended? ? false : (object.discoverable || false) + object.unavailable? ? false : (object.discoverable || false) end def indexable - object.suspended? ? false : (object.indexable || false) + object.unavailable? ? false : (object.indexable || false) end def name - object.suspended? ? object.username : (object.display_name.presence || object.username) + object.unavailable? ? object.username : (object.display_name.presence || object.username) end def summary - object.suspended? ? '' : account_bio_format(object) + object.unavailable? ? '' : account_bio_format(object) end def icon @@ -132,23 +132,23 @@ def url end def avatar_exists? - !object.suspended? && object.avatar? + !object.unavailable? && object.avatar? end def header_exists? - !object.suspended? && object.header? + !object.unavailable? && object.header? end def manually_approves_followers - object.suspended? ? false : object.locked + object.unavailable? ? false : object.locked end def virtual_tags - object.suspended? ? [] : (object.emojis + object.tags) + object.unavailable? ? [] : (object.emojis + object.tags) end def virtual_attachments - object.suspended? ? [] : object.fields + object.unavailable? ? [] : object.fields end def moved_to @@ -156,11 +156,11 @@ def moved_to end def moved? - !object.suspended? && object.moved? + !object.unavailable? && object.moved? end def also_known_as? - !object.suspended? && !object.also_known_as.empty? + !object.unavailable? && !object.also_known_as.empty? end def published diff --git a/app/serializers/rest/account_serializer.rb b/app/serializers/rest/account_serializer.rb index 5d1292a6bdae6f..354d384464dffb 100644 --- a/app/serializers/rest/account_serializer.rb +++ b/app/serializers/rest/account_serializer.rb @@ -61,7 +61,7 @@ def acct end def note - object.suspended? ? '' : account_bio_format(object) + object.unavailable? ? '' : account_bio_format(object) end def url @@ -73,19 +73,19 @@ def uri end def avatar - full_asset_url(object.suspended? ? object.avatar.default_url : object.avatar_original_url) + full_asset_url(object.unavailable? ? object.avatar.default_url : object.avatar_original_url) end def avatar_static - full_asset_url(object.suspended? ? object.avatar.default_url : object.avatar_static_url) + full_asset_url(object.unavailable? ? object.avatar.default_url : object.avatar_static_url) end def header - full_asset_url(object.suspended? ? object.header.default_url : object.header_original_url) + full_asset_url(object.unavailable? ? object.header.default_url : object.header_original_url) end def header_static - full_asset_url(object.suspended? ? object.header.default_url : object.header_static_url) + full_asset_url(object.unavailable? ? object.header.default_url : object.header_static_url) end def created_at @@ -97,39 +97,39 @@ def last_status_at end def display_name - object.suspended? ? '' : object.display_name + object.unavailable? ? '' : object.display_name end def locked - object.suspended? ? false : object.locked + object.unavailable? ? false : object.locked end def bot - object.suspended? ? false : object.bot + object.unavailable? ? false : object.bot end def discoverable - object.suspended? ? false : object.discoverable + object.unavailable? ? false : object.discoverable end def indexable - object.suspended? ? false : object.indexable + object.unavailable? ? false : object.indexable end def moved_to_account - object.suspended? ? nil : AccountDecorator.new(object.moved_to_account) + object.unavailable? ? nil : AccountDecorator.new(object.moved_to_account) end def emojis - object.suspended? ? [] : object.emojis + object.unavailable? ? [] : object.emojis end def fields - object.suspended? ? [] : object.fields + object.unavailable? ? [] : object.fields end def suspended - object.suspended? + object.unavailable? end def silenced @@ -141,7 +141,7 @@ def memorial end def roles - if object.suspended? || object.user.nil? + if object.unavailable? || object.user.nil? [] else [object.user.role].compact.filter(&:highlighted?) diff --git a/app/services/follow_service.rb b/app/services/follow_service.rb index 1aa0241fe62325..af5f996077e4a1 100644 --- a/app/services/follow_service.rb +++ b/app/services/follow_service.rb @@ -50,7 +50,7 @@ def mark_home_feed_as_partial! end def following_not_possible? - @target_account.nil? || @target_account.id == @source_account.id || @target_account.suspended? + @target_account.nil? || @target_account.id == @source_account.id || @target_account.unavailable? end def following_not_allowed? diff --git a/app/services/notify_service.rb b/app/services/notify_service.rb index 125883b1534d54..13eb20986e3e65 100644 --- a/app/services/notify_service.rb +++ b/app/services/notify_service.rb @@ -108,7 +108,7 @@ def domain_blocking? end def blocked? - blocked = @recipient.suspended? + blocked = @recipient.unavailable? blocked ||= from_self? && @notification.type != :poll return blocked if message? && from_staff? diff --git a/app/services/process_mentions_service.rb b/app/services/process_mentions_service.rb index f3fbb802100f42..1c4c7805f1423e 100644 --- a/app/services/process_mentions_service.rb +++ b/app/services/process_mentions_service.rb @@ -51,7 +51,7 @@ def scan_text! # If after resolving it still isn't found or isn't the right # protocol, then give up - next match if mention_undeliverable?(mentioned_account) || mentioned_account&.suspended? + next match if mention_undeliverable?(mentioned_account) || mentioned_account&.unavailable? mention = @previous_mentions.find { |x| x.account_id == mentioned_account.id } mention ||= @current_mentions.find { |x| x.account_id == mentioned_account.id } diff --git a/app/services/report_service.rb b/app/services/report_service.rb index 38e55c5b6347fd..fe546c383e62c0 100644 --- a/app/services/report_service.rb +++ b/app/services/report_service.rb @@ -12,7 +12,7 @@ def call(source_account, target_account, options = {}) @rule_ids = options.delete(:rule_ids).presence @options = options - raise ActiveRecord::RecordNotFound if @target_account.suspended? + raise ActiveRecord::RecordNotFound if @target_account.unavailable? create_report! notify_staff! diff --git a/app/views/admin/accounts/_account.html.haml b/app/views/admin/accounts/_account.html.haml index 755b987a877cd7..d2f6652a00d581 100644 --- a/app/views/admin/accounts/_account.html.haml +++ b/app/views/admin/accounts/_account.html.haml @@ -1,4 +1,4 @@ -.batch-table__row{ class: [!account.suspended? && account.user_pending? && 'batch-table__row--attention', (account.suspended? || account.user_unconfirmed?) && 'batch-table__row--muted'] } +.batch-table__row{ class: [!account.unavailable? && account.user_pending? && 'batch-table__row--attention', (account.unavailable? || account.user_unconfirmed?) && 'batch-table__row--muted'] } %label.batch-table__row__select.batch-table__row__select--aligned.batch-checkbox = f.check_box :account_ids, { multiple: true, include_hidden: false }, account.id .batch-table__row__content.batch-table__row__content--unpadded @@ -8,13 +8,13 @@ %td = account_link_to account, path: admin_account_path(account.id) %td.accounts-table__count.optional - - if account.suspended? || account.user_pending? + - if account.unavailable? || account.user_pending? \- - else = friendly_number_to_human account.statuses_count %small= t('accounts.posts', count: account.statuses_count).downcase %td.accounts-table__count.optional - - if account.suspended? || account.user_pending? + - if account.unavailable? || account.user_pending? \- - else = friendly_number_to_human account.followers_count @@ -30,6 +30,6 @@ \- %br/ %samp.ellipsized-ip= relevant_account_ip(account, params[:ip]) - - if !account.suspended? && account.user_pending? && account.user&.invite_request&.text.present? + - if !account.unavailable? && account.user_pending? && account.user&.invite_request&.text.present? .batch-table__row__content__quote %p= account.user&.invite_request&.text diff --git a/app/views/oauth/authorized_applications/index.html.haml b/app/views/oauth/authorized_applications/index.html.haml index 40b09d87f1afb8..92e24d30c8597d 100644 --- a/app/views/oauth/authorized_applications/index.html.haml +++ b/app/views/oauth/authorized_applications/index.html.haml @@ -27,7 +27,7 @@ = t('doorkeeper.authorized_applications.index.authorized_at', date: l(application.created_at.to_date)) - - unless application.superapp? || current_account.suspended? + - unless application.superapp? || current_account.unavailable? %div = table_link_to 'times', t('doorkeeper.authorized_applications.buttons.revoke'), oauth_authorized_application_path(application), method: :delete, data: { confirm: t('doorkeeper.authorized_applications.confirmations.revoke') } diff --git a/app/workers/account_deletion_worker.rb b/app/workers/account_deletion_worker.rb index e4f943fbd1fffd..070352f9572544 100644 --- a/app/workers/account_deletion_worker.rb +++ b/app/workers/account_deletion_worker.rb @@ -7,7 +7,7 @@ class AccountDeletionWorker def perform(account_id, options = {}) account = Account.find(account_id) - return unless account.suspended? + return unless account.unavailable? reserve_username = options.with_indifferent_access.fetch(:reserve_username, true) skip_activitypub = options.with_indifferent_access.fetch(:skip_activitypub, false) diff --git a/app/workers/scheduler/suspended_user_cleanup_scheduler.rb b/app/workers/scheduler/suspended_user_cleanup_scheduler.rb index 90feead676d80d..4ea81c785b38a9 100644 --- a/app/workers/scheduler/suspended_user_cleanup_scheduler.rb +++ b/app/workers/scheduler/suspended_user_cleanup_scheduler.rb @@ -21,12 +21,12 @@ class Scheduler::SuspendedUserCleanupScheduler def perform return if Sidekiq::Queue.new('pull').size > MAX_PULL_SIZE - clean_suspended_accounts! + process_deletion_requests! end private - def clean_suspended_accounts! + def process_deletion_requests! # This should be fine because we only process a small amount of deletion requests at once and # `id` and `created_at` should follow the same order. AccountDeletionRequest.reorder(id: :asc).take(MAX_DELETIONS_PER_JOB).each do |deletion_request|