From 49219508bc2e01fe724830ca31a7cfa7adba15cf Mon Sep 17 00:00:00 2001 From: Claire Date: Sat, 3 Jul 2021 21:13:47 +0200 Subject: [PATCH 01/18] Fix anonymous access to outbox not being cached by the reverse proxy (#16458) * Fix anonymous access to outbox not being cached by the reverse proxy Up until now, anonymous access to outbox was marked as public, but with a 0 duration for caching, which means remote proxies would only serve from cache when the server was completely overwhelmed. Changed that cache duration to one minute, so that repeated anonymous access to one account's outbox can be appropriately cached. Also added `Signature` to the `Vary` header in case a page is requested, so that authenticated fetches are never served from cache (which only contains public toots). * Remove Vary: Accept header from webfinger controller Indeed, we have stopped returning xrd, and only ever return jrd, so the Accept request header does not matter anymore. * Cache negative webfinger hits for 3 minutes --- .../activitypub/outboxes_controller.rb | 10 +++++++++- .../well_known/webfinger_controller.rb | 3 ++- .../activitypub/outboxes_controller_spec.rb | 16 ++++++++++++---- .../well_known/webfinger_controller_spec.rb | 4 ++++ 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/app/controllers/activitypub/outboxes_controller.rb b/app/controllers/activitypub/outboxes_controller.rb index 4a52560ac..b2aab56a5 100644 --- a/app/controllers/activitypub/outboxes_controller.rb +++ b/app/controllers/activitypub/outboxes_controller.rb @@ -11,7 +11,11 @@ class ActivityPub::OutboxesController < ActivityPub::BaseController before_action :set_cache_headers def show - expires_in(page_requested? ? 0 : 3.minutes, public: public_fetch_mode? && !(signed_request_account.present? && page_requested?)) + if page_requested? + expires_in(1.minute, public: public_fetch_mode? && signed_request_account.nil?) + else + expires_in(3.minutes, public: public_fetch_mode?) + end render json: outbox_presenter, serializer: ActivityPub::OutboxSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json' end @@ -76,4 +80,8 @@ class ActivityPub::OutboxesController < ActivityPub::BaseController def set_account @account = params[:account_username].present? ? Account.find_local!(username_param) : Account.representative end + + def set_cache_headers + response.headers['Vary'] = 'Signature' if authorized_fetch_mode? || page_requested? + end end diff --git a/app/controllers/well_known/webfinger_controller.rb b/app/controllers/well_known/webfinger_controller.rb index 0227f722a..2b296ea3b 100644 --- a/app/controllers/well_known/webfinger_controller.rb +++ b/app/controllers/well_known/webfinger_controller.rb @@ -4,7 +4,6 @@ module WellKnown class WebfingerController < ActionController::Base include RoutingHelper - before_action { response.headers['Vary'] = 'Accept' } before_action :set_account before_action :check_account_suspension @@ -39,10 +38,12 @@ module WellKnown end def bad_request + expires_in(3.minutes, public: true) head 400 end def not_found + expires_in(3.minutes, public: true) head 404 end diff --git a/spec/controllers/activitypub/outboxes_controller_spec.rb b/spec/controllers/activitypub/outboxes_controller_spec.rb index d23f2c17c..1722690db 100644 --- a/spec/controllers/activitypub/outboxes_controller_spec.rb +++ b/spec/controllers/activitypub/outboxes_controller_spec.rb @@ -55,6 +55,10 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do it_behaves_like 'cachable response' + it 'does not have a Vary header' do + expect(response.headers['Vary']).to be_nil + end + context 'when account is permanently suspended' do before do account.suspend! @@ -96,6 +100,10 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do it_behaves_like 'cachable response' + it 'returns Vary header with Signature' do + expect(response.headers['Vary']).to include 'Signature' + end + context 'when account is permanently suspended' do before do account.suspend! @@ -144,7 +152,7 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do end it 'returns private Cache-Control header' do - expect(response.headers['Cache-Control']).to eq 'max-age=0, private' + expect(response.headers['Cache-Control']).to eq 'max-age=60, private' end end @@ -170,7 +178,7 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do end it 'returns private Cache-Control header' do - expect(response.headers['Cache-Control']).to eq 'max-age=0, private' + expect(response.headers['Cache-Control']).to eq 'max-age=60, private' end end @@ -195,7 +203,7 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do end it 'returns private Cache-Control header' do - expect(response.headers['Cache-Control']).to eq 'max-age=0, private' + expect(response.headers['Cache-Control']).to eq 'max-age=60, private' end end @@ -220,7 +228,7 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do end it 'returns private Cache-Control header' do - expect(response.headers['Cache-Control']).to eq 'max-age=0, private' + expect(response.headers['Cache-Control']).to eq 'max-age=60, private' end end end diff --git a/spec/controllers/well_known/webfinger_controller_spec.rb b/spec/controllers/well_known/webfinger_controller_spec.rb index 1075456f3..8574d369d 100644 --- a/spec/controllers/well_known/webfinger_controller_spec.rb +++ b/spec/controllers/well_known/webfinger_controller_spec.rb @@ -24,6 +24,10 @@ describe WellKnown::WebfingerController, type: :controller do expect(response).to have_http_status(200) end + it 'does not set a Vary header' do + expect(response.headers['Vary']).to be_nil + end + it 'returns application/jrd+json' do expect(response.media_type).to eq 'application/jrd+json' end From 7b14b8074d937c1ab4ea2656269a39563cf24f09 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 4 Jul 2021 05:07:32 +0900 Subject: [PATCH 02/18] Bump rails from 6.1.3.2 to 6.1.4 (#16436) Bumps [rails](https://github.com/rails/rails) from 6.1.3.2 to 6.1.4. - [Release notes](https://github.com/rails/rails/releases) - [Commits](https://github.com/rails/rails/compare/v6.1.3.2...v6.1.4) --- updated-dependencies: - dependency-name: rails dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Gemfile | 2 +- Gemfile.lock | 116 +++++++++++++++++++++++++-------------------------- 2 files changed, 59 insertions(+), 59 deletions(-) diff --git a/Gemfile b/Gemfile index abb8f9195..56f52f3e1 100644 --- a/Gemfile +++ b/Gemfile @@ -6,7 +6,7 @@ ruby '>= 2.5.0', '< 3.1.0' gem 'pkg-config', '~> 1.4' gem 'puma', '~> 5.3' -gem 'rails', '~> 6.1.3' +gem 'rails', '~> 6.1.4' gem 'sprockets', '~> 3.7.2' gem 'thor', '~> 1.1' gem 'rack', '~> 2.2.3' diff --git a/Gemfile.lock b/Gemfile.lock index 97d2e2222..b14dbc129 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,40 +1,40 @@ GEM remote: https://rubygems.org/ specs: - actioncable (6.1.3.2) - actionpack (= 6.1.3.2) - activesupport (= 6.1.3.2) + actioncable (6.1.4) + actionpack (= 6.1.4) + activesupport (= 6.1.4) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.1.3.2) - actionpack (= 6.1.3.2) - activejob (= 6.1.3.2) - activerecord (= 6.1.3.2) - activestorage (= 6.1.3.2) - activesupport (= 6.1.3.2) + actionmailbox (6.1.4) + actionpack (= 6.1.4) + activejob (= 6.1.4) + activerecord (= 6.1.4) + activestorage (= 6.1.4) + activesupport (= 6.1.4) mail (>= 2.7.1) - actionmailer (6.1.3.2) - actionpack (= 6.1.3.2) - actionview (= 6.1.3.2) - activejob (= 6.1.3.2) - activesupport (= 6.1.3.2) + actionmailer (6.1.4) + actionpack (= 6.1.4) + actionview (= 6.1.4) + activejob (= 6.1.4) + activesupport (= 6.1.4) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (6.1.3.2) - actionview (= 6.1.3.2) - activesupport (= 6.1.3.2) + actionpack (6.1.4) + actionview (= 6.1.4) + activesupport (= 6.1.4) rack (~> 2.0, >= 2.0.9) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.1.3.2) - actionpack (= 6.1.3.2) - activerecord (= 6.1.3.2) - activestorage (= 6.1.3.2) - activesupport (= 6.1.3.2) + actiontext (6.1.4) + actionpack (= 6.1.4) + activerecord (= 6.1.4) + activestorage (= 6.1.4) + activesupport (= 6.1.4) nokogiri (>= 1.8.5) - actionview (6.1.3.2) - activesupport (= 6.1.3.2) + actionview (6.1.4) + activesupport (= 6.1.4) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) @@ -45,22 +45,22 @@ GEM case_transform (>= 0.2) jsonapi-renderer (>= 0.1.1.beta1, < 0.3) active_record_query_trace (1.8) - activejob (6.1.3.2) - activesupport (= 6.1.3.2) + activejob (6.1.4) + activesupport (= 6.1.4) globalid (>= 0.3.6) - activemodel (6.1.3.2) - activesupport (= 6.1.3.2) - activerecord (6.1.3.2) - activemodel (= 6.1.3.2) - activesupport (= 6.1.3.2) - activestorage (6.1.3.2) - actionpack (= 6.1.3.2) - activejob (= 6.1.3.2) - activerecord (= 6.1.3.2) - activesupport (= 6.1.3.2) + activemodel (6.1.4) + activesupport (= 6.1.4) + activerecord (6.1.4) + activemodel (= 6.1.4) + activesupport (= 6.1.4) + activestorage (6.1.4) + actionpack (= 6.1.4) + activejob (= 6.1.4) + activerecord (= 6.1.4) + activesupport (= 6.1.4) marcel (~> 1.0.0) - mini_mime (~> 1.0.2) - activesupport (6.1.3.2) + mini_mime (>= 1.1.0) + activesupport (6.1.4) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) @@ -353,7 +353,7 @@ GEM mimemagic (0.3.10) nokogiri (~> 1) rake - mini_mime (1.0.3) + mini_mime (1.1.0) mini_portile2 (2.5.3) minitest (5.14.4) msgpack (1.4.2) @@ -443,20 +443,20 @@ GEM rack rack-test (1.1.0) rack (>= 1.0, < 3) - rails (6.1.3.2) - actioncable (= 6.1.3.2) - actionmailbox (= 6.1.3.2) - actionmailer (= 6.1.3.2) - actionpack (= 6.1.3.2) - actiontext (= 6.1.3.2) - actionview (= 6.1.3.2) - activejob (= 6.1.3.2) - activemodel (= 6.1.3.2) - activerecord (= 6.1.3.2) - activestorage (= 6.1.3.2) - activesupport (= 6.1.3.2) + rails (6.1.4) + actioncable (= 6.1.4) + actionmailbox (= 6.1.4) + actionmailer (= 6.1.4) + actionpack (= 6.1.4) + actiontext (= 6.1.4) + actionview (= 6.1.4) + activejob (= 6.1.4) + activemodel (= 6.1.4) + activerecord (= 6.1.4) + activestorage (= 6.1.4) + activesupport (= 6.1.4) bundler (>= 1.15.0) - railties (= 6.1.3.2) + railties (= 6.1.4) sprockets-rails (>= 2.0.0) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) @@ -472,11 +472,11 @@ GEM railties (>= 6.0.0, < 7) rails-settings-cached (0.6.6) rails (>= 4.2.0) - railties (6.1.3.2) - actionpack (= 6.1.3.2) - activesupport (= 6.1.3.2) + railties (6.1.4) + actionpack (= 6.1.4) + activesupport (= 6.1.4) method_source - rake (>= 0.8.7) + rake (>= 0.13) thor (~> 1.0) rainbow (3.0.0) rake (13.0.3) @@ -658,7 +658,7 @@ GEM webpush (0.3.8) hkdf (~> 0.2) jwt (~> 2.0) - websocket-driver (0.7.3) + websocket-driver (0.7.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) wisper (2.0.1) @@ -757,7 +757,7 @@ DEPENDENCIES rack (~> 2.2.3) rack-attack (~> 6.5) rack-cors (~> 1.1) - rails (~> 6.1.3) + rails (~> 6.1.4) rails-controller-testing (~> 1.0) rails-i18n (~> 6.0) rails-settings-cached (~> 0.6) From 23c180b02bac27a4cd1d80349e186235999355cc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 4 Jul 2021 05:07:46 +0900 Subject: [PATCH 03/18] Bump @rails/ujs from 6.1.3 to 6.1.4 (#16442) Bumps [@rails/ujs](https://github.com/rails/rails) from 6.1.3 to 6.1.4. - [Release notes](https://github.com/rails/rails/releases) - [Commits](https://github.com/rails/rails/compare/v6.1.3...v6.1.4) --- updated-dependencies: - dependency-name: "@rails/ujs" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 538bd057f..967551ccc 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "@babel/runtime": "^7.14.6", "@gamestdio/websocket": "^0.3.2", "@github/webauthn-json": "^0.5.7", - "@rails/ujs": "^6.1.3", + "@rails/ujs": "^6.1.4", "array-includes": "^3.1.3", "arrow-key-navigation": "^1.2.0", "autoprefixer": "^9.8.6", diff --git a/yarn.lock b/yarn.lock index 441fe5649..35066b1bc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1370,10 +1370,10 @@ resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.11.tgz#aeb16f50649a91af79dbe36574b66d0f9e4d9f71" integrity sha512-3NsZsJIA/22P3QUyrEDNA2D133H4j224twJrdipXN38dpnIOzAbUDtOwkcJ5pXmn75w7LSQDjA4tO9dm1XlqlA== -"@rails/ujs@^6.1.3": - version "6.1.3" - resolved "https://registry.yarnpkg.com/@rails/ujs/-/ujs-6.1.3.tgz#90ef26caa0925492b1a3b1495db09cfbe49e745e" - integrity sha512-9mip5o+LVouWAqLMNJWhxda+D5uP+4RziNECgOGJlL6k3rc5SC/ljCHpV9Cym4i3oeGZkpZJ2tu4frCwt84kzQ== +"@rails/ujs@^6.1.4": + version "6.1.4" + resolved "https://registry.yarnpkg.com/@rails/ujs/-/ujs-6.1.4.tgz#093d5341595a02089ed309dec40f3c37da7b1b10" + integrity sha512-O3lEzL5DYbxppMdsFSw36e4BHIlfz/xusynwXGv3l2lhSlvah41qviRpsoAlKXxl37nZAqK+UUF5cnGGK45Mfw== "@sinonjs/commons@^1.7.0": version "1.8.1" From 9f76be5e7d15bc0deefa1c9227246dce54277382 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 4 Jul 2021 11:59:37 +0900 Subject: [PATCH 04/18] Bump eslint from 7.29.0 to 7.30.0 (#16461) Bumps [eslint](https://github.com/eslint/eslint) from 7.29.0 to 7.30.0. - [Release notes](https://github.com/eslint/eslint/releases) - [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md) - [Commits](https://github.com/eslint/eslint/compare/v7.29.0...v7.30.0) --- updated-dependencies: - dependency-name: eslint dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 23 +++++++++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 967551ccc..6cf923249 100644 --- a/package.json +++ b/package.json @@ -175,7 +175,7 @@ "@testing-library/react": "^11.2.7", "babel-eslint": "^10.1.0", "babel-jest": "^27.0.6", - "eslint": "^7.29.0", + "eslint": "^7.30.0", "eslint-plugin-import": "~2.23.4", "eslint-plugin-jsx-a11y": "~6.4.1", "eslint-plugin-promise": "~5.1.0", diff --git a/yarn.lock b/yarn.lock index 35066b1bc..bdf2c6c33 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1129,6 +1129,20 @@ resolved "https://registry.yarnpkg.com/@github/webauthn-json/-/webauthn-json-0.5.7.tgz#143bc67f6e0f75f8d188e565741507bb08c31214" integrity sha512-SUYsttDxFSvWvvJssJpwzjmRCqYfdfqC9VCmAHQYfdKCVelyJteCHo9/lK1CB72mx/jrl6cFNY08aua4J2jIyg== +"@humanwhocodes/config-array@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9" + integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg== + dependencies: + "@humanwhocodes/object-schema" "^1.2.0" + debug "^4.1.1" + minimatch "^3.0.4" + +"@humanwhocodes/object-schema@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz#87de7af9c231826fdd68ac7258f77c429e0e5fcf" + integrity sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w== + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -4436,13 +4450,14 @@ eslint@^2.7.0: text-table "~0.2.0" user-home "^2.0.0" -eslint@^7.29.0: - version "7.29.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.29.0.tgz#ee2a7648f2e729485e4d0bd6383ec1deabc8b3c0" - integrity sha512-82G/JToB9qIy/ArBzIWG9xvvwL3R86AlCjtGw+A29OMZDqhTybz/MByORSukGxeI+YPCR4coYyITKk8BFH9nDA== +eslint@^7.30.0: + version "7.30.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.30.0.tgz#6d34ab51aaa56112fd97166226c9a97f505474f8" + integrity sha512-VLqz80i3as3NdloY44BQSJpFw534L9Oh+6zJOUaViV4JPd+DaHwutqP7tcpkW3YiXbK6s05RZl7yl7cQn+lijg== dependencies: "@babel/code-frame" "7.12.11" "@eslint/eslintrc" "^0.4.2" + "@humanwhocodes/config-array" "^0.5.0" ajv "^6.10.0" chalk "^4.0.0" cross-spawn "^7.0.2" From 1381e0e1d9f27bd108d8b9349896f10ffe996cb2 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 5 Jul 2021 19:16:06 +0200 Subject: [PATCH 05/18] Fix pop-in player display when poster has long username or handle (#16468) --- app/javascript/styles/mastodon/components.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 0579c3c6f..35c10b096 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -7291,6 +7291,7 @@ noscript { &__account { display: flex; text-decoration: none; + overflow: hidden; } .account__avatar { From 67226acf7e8e91a44dc9599aecb17dcd73a72ea9 Mon Sep 17 00:00:00 2001 From: Ikko Ashimine Date: Tue, 6 Jul 2021 02:16:21 +0900 Subject: [PATCH 06/18] Fix typo in tag_feed_spec.rb (#16466) existant -> existent --- spec/models/tag_feed_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/models/tag_feed_spec.rb b/spec/models/tag_feed_spec.rb index 17d88eb99..819fe3765 100644 --- a/spec/models/tag_feed_spec.rb +++ b/spec/models/tag_feed_spec.rb @@ -37,7 +37,7 @@ describe TagFeed, type: :service do expect(results).to include both end - it 'handles being passed non existant tag names' do + it 'handles being passed non existent tag names' do results = described_class.new(tag1, nil, any: ['wark']).get(20) expect(results).to include status1 expect(results).to_not include status2 From 8af7f3b063a9d082b95e087bc7bf6feac7d13631 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Tue, 6 Jul 2021 02:16:35 +0900 Subject: [PATCH 07/18] Preload libjemalloc.so for long-running Ruby (#16462) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Always mark jemalloc needed if jemalloc is enabled by akihikodaki · Pull Request #4627 · ruby/ruby https://github.com/ruby/ruby/pull/4627 > Symbols exported by jemalloc is referred by the shared library but not > by the executables when building Ruby as a shared library with > jemalloc. It causes shared libraries such as the GNU C++ library > occasionally rely on the memory allocator provided by the standard C > library. Worse, the resolved symbols can later be replaced with > jemalloc, and jemalloc may see pointers from the standard C library, > which results in various failures. > e.g. https://github.com/tootsuite/mastodon/issues/15751 As a workaround, do not rely on jemalloc enablement of Ruby, and preload libjemalloc.so instead. --- dist/mastodon-sidekiq.service | 1 + dist/mastodon-web.service | 1 + 2 files changed, 2 insertions(+) diff --git a/dist/mastodon-sidekiq.service b/dist/mastodon-sidekiq.service index 9dd21b8a0..35b121cd7 100644 --- a/dist/mastodon-sidekiq.service +++ b/dist/mastodon-sidekiq.service @@ -9,6 +9,7 @@ WorkingDirectory=/home/mastodon/live Environment="RAILS_ENV=production" Environment="DB_POOL=25" Environment="MALLOC_ARENA_MAX=2" +Environment="LD_PRELOAD=libjemalloc.so" ExecStart=/home/mastodon/.rbenv/shims/bundle exec sidekiq -c 25 TimeoutSec=15 Restart=always diff --git a/dist/mastodon-web.service b/dist/mastodon-web.service index c106a4860..f41efd2b0 100644 --- a/dist/mastodon-web.service +++ b/dist/mastodon-web.service @@ -8,6 +8,7 @@ User=mastodon WorkingDirectory=/home/mastodon/live Environment="RAILS_ENV=production" Environment="PORT=3000" +Environment="LD_PRELOAD=libjemalloc.so" ExecStart=/home/mastodon/.rbenv/shims/bundle exec puma -C config/puma.rb ExecReload=/bin/kill -SIGUSR1 $MAINPID TimeoutSec=15 From 225c6582d17b8e744c279e254d4e96062afb7a3b Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 7 Jul 2021 21:12:43 +0200 Subject: [PATCH 08/18] Add tests for BootstrapTimelineService (#16476) --- .../bootstrap_timeline_service_spec.rb | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/spec/services/bootstrap_timeline_service_spec.rb b/spec/services/bootstrap_timeline_service_spec.rb index 880ca4f0d..16f3e9962 100644 --- a/spec/services/bootstrap_timeline_service_spec.rb +++ b/spec/services/bootstrap_timeline_service_spec.rb @@ -1,4 +1,37 @@ require 'rails_helper' RSpec.describe BootstrapTimelineService, type: :service do + subject { BootstrapTimelineService.new } + + context 'when the new user has registered from an invite' do + let(:service) { double } + let(:autofollow) { false } + let(:inviter) { Fabricate(:user, confirmed_at: 2.days.ago) } + let(:invite) { Fabricate(:invite, user: inviter, max_uses: nil, expires_at: 1.hour.from_now, autofollow: autofollow) } + let(:new_user) { Fabricate(:user, invite_code: invite.code) } + + before do + allow(FollowService).to receive(:new).and_return(service) + allow(service).to receive(:call) + end + + context 'when the invite has auto-follow enabled' do + let(:autofollow) { true } + + it 'calls FollowService to follow the inviter' do + subject.call(new_user.account) + expect(service).to have_received(:call).with(new_user.account, inviter.account) + end + end + + context 'when the invite does not have auto-follow enable' do + let(:autofollow) { false } + + it 'calls FollowService to follow the inviter' do + subject.call(new_user.account) + expect(service).to_not have_received(:call) + end + end + + end end From e2844b7e58e1ebdf666c5fecc97a75620da7bddf Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 7 Jul 2021 21:13:08 +0200 Subject: [PATCH 09/18] Change number_to_human calls to always use 3-digits precision (#16469) Fixes #16435 --- app/helpers/accounts_helper.rb | 6 +++--- app/helpers/application_helper.rb | 11 +++++++++++ app/views/about/more.html.haml | 4 ++-- app/views/about/show.html.haml | 4 ++-- app/views/accounts/_header.html.haml | 10 +++++----- app/views/accounts/show.html.haml | 2 +- app/views/admin/dashboard/index.html.haml | 16 ++++++++-------- .../follow_recommendations/_account.html.haml | 4 ++-- app/views/admin/instances/_instance.html.haml | 2 +- app/views/admin/tags/_tag.html.haml | 2 +- app/views/directories/index.html.haml | 4 ++-- app/views/relationships/_account.html.haml | 4 ++-- app/views/settings/featured_tags/index.html.haml | 2 +- app/views/statuses/_detailed_status.html.haml | 6 +++--- 14 files changed, 44 insertions(+), 33 deletions(-) diff --git a/app/helpers/accounts_helper.rb b/app/helpers/accounts_helper.rb index 134217734..db3da2b05 100644 --- a/app/helpers/accounts_helper.rb +++ b/app/helpers/accounts_helper.rb @@ -80,17 +80,17 @@ module AccountsHelper def account_description(account) prepend_str = [ [ - number_to_human(account.statuses_count, strip_insignificant_zeros: true), + number_to_human(account.statuses_count, precision: 3, strip_insignificant_zeros: true), I18n.t('accounts.posts', count: account.statuses_count), ].join(' '), [ - number_to_human(account.following_count, strip_insignificant_zeros: true), + number_to_human(account.following_count, precision: 3, strip_insignificant_zeros: true), I18n.t('accounts.following', count: account.following_count), ].join(' '), [ - number_to_human(account.followers_count, strip_insignificant_zeros: true), + number_to_human(account.followers_count, precision: 3, strip_insignificant_zeros: true), I18n.t('accounts.followers', count: account.followers_count), ].join(' '), ].join(', ') diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index bf5742d34..a39e8e5bf 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -14,6 +14,17 @@ module ApplicationHelper ku ).freeze + def friendly_number_to_human(number, **options) + # By default, the number of precision digits used by number_to_human + # is looked up from the locales definition, and rails-i18n comes with + # values that don't seem to make much sense for many languages, so + # override these values with a default of 3 digits of precision. + options[:precision] = 3 + options[:strip_insignificant_zeros] = true + + number_to_human(number, **options) + end + def active_nav_class(*paths) paths.any? { |path| current_page?(path) } ? 'active' : '' end diff --git a/app/views/about/more.html.haml b/app/views/about/more.html.haml index cd93b0f58..f4429622c 100644 --- a/app/views/about/more.html.haml +++ b/app/views/about/more.html.haml @@ -17,11 +17,11 @@ .row__information-board .information-board__section %span= t 'about.user_count_before' - %strong= number_to_human @instance_presenter.user_count, strip_insignificant_zeros: true + %strong= friendly_number_to_human @instance_presenter.user_count %span= t 'about.user_count_after', count: @instance_presenter.user_count .information-board__section %span= t 'about.status_count_before' - %strong= number_to_human @instance_presenter.status_count, strip_insignificant_zeros: true + %strong= friendly_number_to_human @instance_presenter.status_count %span= t 'about.status_count_after', count: @instance_presenter.status_count .row__mascot .landing-page__mascot diff --git a/app/views/about/show.html.haml b/app/views/about/show.html.haml index 565c4ed59..6ae9e6ae0 100644 --- a/app/views/about/show.html.haml +++ b/app/views/about/show.html.haml @@ -70,10 +70,10 @@ .hero-widget__counters__wrapper .hero-widget__counter - %strong= number_to_human @instance_presenter.user_count, strip_insignificant_zeros: true + %strong= friendly_number_to_human @instance_presenter.user_count %span= t 'about.user_count_after', count: @instance_presenter.user_count .hero-widget__counter - %strong= number_to_human @instance_presenter.active_user_count, strip_insignificant_zeros: true + %strong= friendly_number_to_human @instance_presenter.active_user_count %span = t 'about.active_count_after' %abbr{ title: t('about.active_footnote') } * diff --git a/app/views/accounts/_header.html.haml b/app/views/accounts/_header.html.haml index cae5a5ac9..d9966723a 100644 --- a/app/views/accounts/_header.html.haml +++ b/app/views/accounts/_header.html.haml @@ -15,17 +15,17 @@ .details-counters .counter{ class: active_nav_class(short_account_url(account), short_account_with_replies_url(account), short_account_media_url(account)) } = link_to short_account_url(account), class: 'u-url u-uid', title: number_with_delimiter(account.statuses_count) do - %span.counter-number= number_to_human account.statuses_count, strip_insignificant_zeros: true + %span.counter-number= friendly_number_to_human account.statuses_count %span.counter-label= t('accounts.posts', count: account.statuses_count) .counter{ class: active_nav_class(account_following_index_url(account)) } = link_to account_following_index_url(account), title: number_with_delimiter(account.following_count) do - %span.counter-number= number_to_human account.following_count, strip_insignificant_zeros: true + %span.counter-number= friendly_number_to_human account.following_count %span.counter-label= t('accounts.following', count: account.following_count) .counter{ class: active_nav_class(account_followers_url(account)) } = link_to account_followers_url(account), title: number_with_delimiter(account.followers_count) do - %span.counter-number= number_to_human account.followers_count, strip_insignificant_zeros: true + %span.counter-number= friendly_number_to_human account.followers_count %span.counter-label= t('accounts.followers', count: account.followers_count) .spacer .public-account-header__tabs__tabs__buttons @@ -36,8 +36,8 @@ .public-account-header__extra__links = link_to account_following_index_url(account) do - %strong= number_to_human account.following_count, strip_insignificant_zeros: true + %strong= friendly_number_to_human account.following_count = t('accounts.following', count: account.following_count) = link_to account_followers_url(account) do - %strong= number_to_human account.followers_count, strip_insignificant_zeros: true + %strong= friendly_number_to_human account.followers_count = t('accounts.followers', count: account.followers_count) diff --git a/app/views/accounts/show.html.haml b/app/views/accounts/show.html.haml index 1a81b96f6..72e9c6611 100644 --- a/app/views/accounts/show.html.haml +++ b/app/views/accounts/show.html.haml @@ -81,6 +81,6 @@ = t('accounts.nothing_here') - else %time.formatted{ datetime: featured_tag.last_status_at.iso8601, title: l(featured_tag.last_status_at) }= l featured_tag.last_status_at - .trends__item__current= number_to_human featured_tag.statuses_count, strip_insignificant_zeros: true + .trends__item__current= friendly_number_to_human featured_tag.statuses_count = render 'application/sidebar' diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml index e8a2b46fd..05b585ab6 100644 --- a/app/views/admin/dashboard/index.html.haml +++ b/app/views/admin/dashboard/index.html.haml @@ -13,42 +13,42 @@ %div = link_to admin_accounts_url(local: 1, recent: 1) do .dashboard__counters__num{ title: number_with_delimiter(@users_count, strip_insignificant_zeros: true) } - = number_to_human @users_count, strip_insignificant_zeros: true + = friendly_number_to_human @users_count .dashboard__counters__label= t 'admin.dashboard.total_users' %div %div .dashboard__counters__num{ title: number_with_delimiter(@registrations_week, strip_insignificant_zeros: true) } - = number_to_human @registrations_week, strip_insignificant_zeros: true + = friendly_number_to_human @registrations_week .dashboard__counters__label= t 'admin.dashboard.week_users_new' %div %div .dashboard__counters__num{ title: number_with_delimiter(@logins_week, strip_insignificant_zeros: true) } - = number_to_human @logins_week, strip_insignificant_zeros: true + = friendly_number_to_human @logins_week .dashboard__counters__label= t 'admin.dashboard.week_users_active' %div = link_to admin_pending_accounts_path do .dashboard__counters__num{ title: number_with_delimiter(@pending_users_count, strip_insignificant_zeros: true) } - = number_to_human @pending_users_count, strip_insignificant_zeros: true + = friendly_number_to_human @pending_users_count .dashboard__counters__label= t 'admin.dashboard.pending_users' %div = link_to admin_reports_url do .dashboard__counters__num{ title: number_with_delimiter(@reports_count, strip_insignificant_zeros: true) } - = number_to_human @reports_count, strip_insignificant_zeros: true + = friendly_number_to_human @reports_count .dashboard__counters__label= t 'admin.dashboard.open_reports' %div = link_to admin_tags_path(pending_review: '1') do .dashboard__counters__num{ title: number_with_delimiter(@pending_tags_count, strip_insignificant_zeros: true) } - = number_to_human @pending_tags_count, strip_insignificant_zeros: true + = friendly_number_to_human @pending_tags_count .dashboard__counters__label= t 'admin.dashboard.pending_tags' %div %div .dashboard__counters__num{ title: number_with_delimiter(@interactions_week, strip_insignificant_zeros: true) } - = number_to_human @interactions_week, strip_insignificant_zeros: true + = friendly_number_to_human @interactions_week .dashboard__counters__label= t 'admin.dashboard.week_interactions' %div = link_to sidekiq_url do .dashboard__counters__num{ title: number_with_delimiter(@queue_backlog, strip_insignificant_zeros: true) } - = number_to_human @queue_backlog, strip_insignificant_zeros: true + = friendly_number_to_human @queue_backlog .dashboard__counters__label= t 'admin.dashboard.backlog' .dashboard__widgets diff --git a/app/views/admin/follow_recommendations/_account.html.haml b/app/views/admin/follow_recommendations/_account.html.haml index af5a4aaf7..00196dd01 100644 --- a/app/views/admin/follow_recommendations/_account.html.haml +++ b/app/views/admin/follow_recommendations/_account.html.haml @@ -7,10 +7,10 @@ %tr %td= account_link_to account %td.accounts-table__count.optional - = number_to_human account.statuses_count, strip_insignificant_zeros: true + = friendly_number_to_human account.statuses_count %small= t('accounts.posts', count: account.statuses_count).downcase %td.accounts-table__count.optional - = number_to_human account.followers_count, strip_insignificant_zeros: true + = friendly_number_to_human account.followers_count %small= t('accounts.followers', count: account.followers_count).downcase %td.accounts-table__count - if account.last_status_at.present? diff --git a/app/views/admin/instances/_instance.html.haml b/app/views/admin/instances/_instance.html.haml index 990cf9ec8..dc81007ac 100644 --- a/app/views/admin/instances/_instance.html.haml +++ b/app/views/admin/instances/_instance.html.haml @@ -30,4 +30,4 @@ = ' / ' %span.negative-hint = t('admin.instances.delivery.unavailable_message') - .trends__item__current{ title: t('admin.instances.known_accounts', count: instance.accounts_count) }= number_to_human instance.accounts_count, strip_insignificant_zeros: true + .trends__item__current{ title: t('admin.instances.known_accounts', count: instance.accounts_count) }= friendly_number_to_human instance.accounts_count diff --git a/app/views/admin/tags/_tag.html.haml b/app/views/admin/tags/_tag.html.haml index adf4ca7b2..ac0c72816 100644 --- a/app/views/admin/tags/_tag.html.haml +++ b/app/views/admin/tags/_tag.html.haml @@ -16,4 +16,4 @@ = fa_icon 'fire fw' = t('admin.tags.trending_right_now') - .trends__item__current= number_to_human tag.history.first[:uses], strip_insignificant_zeros: true + .trends__item__current= friendly_number_to_human tag.history.first[:uses] diff --git a/app/views/directories/index.html.haml b/app/views/directories/index.html.haml index 7975ee999..04639e32c 100644 --- a/app/views/directories/index.html.haml +++ b/app/views/directories/index.html.haml @@ -39,10 +39,10 @@ .directory__card__extra .accounts-table__count - = number_to_human account.statuses_count, strip_insignificant_zeros: true + = friendly_number_to_human account.statuses_count %small= t('accounts.posts', count: account.statuses_count).downcase .accounts-table__count - = number_to_human account.followers_count, strip_insignificant_zeros: true + = friendly_number_to_human account.followers_count %small= t('accounts.followers', count: account.followers_count).downcase .accounts-table__count - if account.last_status_at.present? diff --git a/app/views/relationships/_account.html.haml b/app/views/relationships/_account.html.haml index f521aff22..0fa3cffb5 100644 --- a/app/views/relationships/_account.html.haml +++ b/app/views/relationships/_account.html.haml @@ -9,10 +9,10 @@ = interrelationships_icon(@relationships, account.id) %td= account_link_to account %td.accounts-table__count.optional - = number_to_human account.statuses_count, strip_insignificant_zeros: true + = friendly_number_to_human account.statuses_count %small= t('accounts.posts', count: account.statuses_count).downcase %td.accounts-table__count.optional - = number_to_human account.followers_count, strip_insignificant_zeros: true + = friendly_number_to_human account.followers_count %small= t('accounts.followers', count: account.followers_count).downcase %td.accounts-table__count - if account.last_status_at.present? diff --git a/app/views/settings/featured_tags/index.html.haml b/app/views/settings/featured_tags/index.html.haml index 297379893..65de7f8f3 100644 --- a/app/views/settings/featured_tags/index.html.haml +++ b/app/views/settings/featured_tags/index.html.haml @@ -28,4 +28,4 @@ - else %time{ datetime: featured_tag.last_status_at.iso8601, title: l(featured_tag.last_status_at) }= l featured_tag.last_status_at = table_link_to 'trash', t('filters.index.delete'), settings_featured_tag_path(featured_tag), method: :delete, data: { confirm: t('admin.accounts.are_you_sure') } - .trends__item__current= number_to_human featured_tag.statuses_count, strip_insignificant_zeros: true + .trends__item__current= friendly_number_to_human featured_tag.statuses_count diff --git a/app/views/statuses/_detailed_status.html.haml b/app/views/statuses/_detailed_status.html.haml index daf164949..6b3b81306 100644 --- a/app/views/statuses/_detailed_status.html.haml +++ b/app/views/statuses/_detailed_status.html.haml @@ -55,18 +55,18 @@ = fa_icon('reply') - else = fa_icon('reply-all') - %span.detailed-status__reblogs>= number_to_human status.replies_count, strip_insignificant_zeros: true + %span.detailed-status__reblogs>= friendly_number_to_human status.replies_count = " " · - if status.public_visibility? || status.unlisted_visibility? = link_to remote_interaction_path(status, type: :reblog), class: 'modal-button detailed-status__link' do = fa_icon('retweet') - %span.detailed-status__reblogs>= number_to_human status.reblogs_count, strip_insignificant_zeros: true + %span.detailed-status__reblogs>= friendly_number_to_human status.reblogs_count = " " · = link_to remote_interaction_path(status, type: :favourite), class: 'modal-button detailed-status__link' do = fa_icon('star') - %span.detailed-status__favorites>= number_to_human status.favourites_count, strip_insignificant_zeros: true + %span.detailed-status__favorites>= friendly_number_to_human status.favourites_count = " " - if user_signed_in? From 8569126c2e52cdde6dba2dd86c9a8e802b0c5e4c Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 7 Jul 2021 21:13:30 +0200 Subject: [PATCH 10/18] Fix upgrade path from 3.4.0 (#16465) 3.4.1 dropped account_stats.lock_version, but in a way breaking the usual upgrade path by requiring services to be reloaded after the post-migrations. Indeed, `self.locking_column = nil` was not enough for Rails to ignore the `lock_version` column when preparing statements on application load, resulting in some ActiveRecord queries (typically those involving `includes(:account_stat)`) erroring out with: ActiveRecord::StatementInvalid (PG::UndefinedColumn: ERROR: column account_stats.lock_version does not exist --- app/models/account_stat.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/account_stat.rb b/app/models/account_stat.rb index 44da4f0d0..e702fa4a4 100644 --- a/app/models/account_stat.rb +++ b/app/models/account_stat.rb @@ -15,6 +15,7 @@ class AccountStat < ApplicationRecord self.locking_column = nil + self.ignored_columns = %w(lock_version) belongs_to :account, inverse_of: :account_stat From 2e0eac71ddf0f5b61b6e395f57b7bc3f805cbf87 Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 7 Jul 2021 21:17:00 +0200 Subject: [PATCH 11/18] Add --by-uri option to `tootctl domains purge` (#16434) Fixes #16410 --- lib/mastodon/domains_cli.rb | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/mastodon/domains_cli.rb b/lib/mastodon/domains_cli.rb index 4ebd8a1e2..a7c78c4a7 100644 --- a/lib/mastodon/domains_cli.rb +++ b/lib/mastodon/domains_cli.rb @@ -17,6 +17,7 @@ module Mastodon option :verbose, type: :boolean, aliases: [:v] option :dry_run, type: :boolean option :limited_federation_mode, type: :boolean + option :by_uri, type: :boolean desc 'purge [DOMAIN...]', 'Remove accounts from a DOMAIN without a trace' long_desc <<-LONG_DESC Remove all accounts from a given DOMAIN without leaving behind any @@ -26,6 +27,12 @@ module Mastodon When the --limited-federation-mode option is given, instead of purging accounts from a single domain, all accounts from domains that have not been explicitly allowed are removed from the database. + + When the --by-uri option is given, DOMAIN is used to match the domain part of actor + URIs rather than the domain part of the webfinger handle. For instance, an account + that has the handle `foo@bar.com` but whose profile is at the URL + `https://mastodon-bar.com/users/foo`, would be purged by either + `tootctl domains purge bar.com` or `tootctl domains purge --by-uri mastodon-bar.com`. LONG_DESC def purge(*domains) dry_run = options[:dry_run] ? ' (DRY RUN)' : '' @@ -34,7 +41,11 @@ module Mastodon if options[:limited_federation_mode] Account.remote.where.not(domain: DomainAllow.pluck(:domain)) elsif !domains.empty? - Account.remote.where(domain: domains) + if options[:by_uri] + domains.map { |domain| Account.remote.where(Account.arel_table[:uri].matches("https://#{domain}/%", false, true)) }.reduce(:or) + else + Account.remote.where(domain: domains) + end else say('No domain(s) given', :red) exit(1) From 771c9d4ba87a388dc306c58139d11bf510680c98 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 8 Jul 2021 05:31:28 +0200 Subject: [PATCH 12/18] Add ability to skip sign-in token authentication for specific users (#16427) Remove "active within last two weeks" exception for sign in token requirement Change admin reset password to lock access until the password is reset --- app/controllers/admin/resets_controller.rb | 4 +- ...ign_in_token_authentications_controller.rb | 27 ++++++++++++ .../two_factor_authentications_controller.rb | 2 +- app/models/user.rb | 25 ++++++++++- app/policies/user_policy.rb | 8 ++++ app/views/admin/accounts/show.html.haml | 24 +++++++++-- config/locales/en.yml | 42 ++++++++++++------- config/routes.rb | 1 + ...1221010_add_skip_sign_in_token_to_users.rb | 5 +++ db/schema.rb | 1 + lib/mastodon/accounts_cli.rb | 15 +++++-- .../admin/resets_controller_spec.rb | 2 +- ..._factor_authentications_controller_spec.rb | 8 ++-- spec/models/user_spec.rb | 28 +++++++++++++ 14 files changed, 160 insertions(+), 32 deletions(-) create mode 100644 app/controllers/admin/sign_in_token_authentications_controller.rb create mode 100644 db/migrate/20210621221010_add_skip_sign_in_token_to_users.rb diff --git a/app/controllers/admin/resets_controller.rb b/app/controllers/admin/resets_controller.rb index db8f61d64..7962b7a58 100644 --- a/app/controllers/admin/resets_controller.rb +++ b/app/controllers/admin/resets_controller.rb @@ -6,9 +6,9 @@ module Admin def create authorize @user, :reset_password? - @user.send_reset_password_instructions + @user.reset_password! log_action :reset_password, @user - redirect_to admin_accounts_path + redirect_to admin_account_path(@user.account_id) end end end diff --git a/app/controllers/admin/sign_in_token_authentications_controller.rb b/app/controllers/admin/sign_in_token_authentications_controller.rb new file mode 100644 index 000000000..e620ab292 --- /dev/null +++ b/app/controllers/admin/sign_in_token_authentications_controller.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +module Admin + class SignInTokenAuthenticationsController < BaseController + before_action :set_target_user + + def create + authorize @user, :enable_sign_in_token_auth? + @user.update(skip_sign_in_token: false) + log_action :enable_sign_in_token_auth, @user + redirect_to admin_account_path(@user.account_id) + end + + def destroy + authorize @user, :disable_sign_in_token_auth? + @user.update(skip_sign_in_token: true) + log_action :disable_sign_in_token_auth, @user + redirect_to admin_account_path(@user.account_id) + end + + private + + def set_target_user + @user = User.find(params[:user_id]) + end + end +end diff --git a/app/controllers/admin/two_factor_authentications_controller.rb b/app/controllers/admin/two_factor_authentications_controller.rb index 0652c3a7a..f7fb7eb8f 100644 --- a/app/controllers/admin/two_factor_authentications_controller.rb +++ b/app/controllers/admin/two_factor_authentications_controller.rb @@ -9,7 +9,7 @@ module Admin @user.disable_two_factor! log_action :disable_2fa, @user UserMailer.two_factor_disabled(@user).deliver_later! - redirect_to admin_accounts_path + redirect_to admin_account_path(@user.account_id) end private diff --git a/app/models/user.rb b/app/models/user.rb index 4973c68b6..4059c96b5 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -42,6 +42,7 @@ # sign_in_token_sent_at :datetime # webauthn_id :string # sign_up_ip :inet +# skip_sign_in_token :boolean # class User < ApplicationRecord @@ -200,7 +201,7 @@ class User < ApplicationRecord end def suspicious_sign_in?(ip) - !otp_required_for_login? && current_sign_in_at.present? && current_sign_in_at < 2.weeks.ago && !recent_ip?(ip) + !otp_required_for_login? && !skip_sign_in_token? && current_sign_in_at.present? && !recent_ip?(ip) end def functional? @@ -329,12 +330,32 @@ class User < ApplicationRecord super end - def reset_password!(new_password, new_password_confirmation) + def reset_password(new_password, new_password_confirmation) return false if encrypted_password.blank? super end + def reset_password! + # First, change password to something random, invalidate the remember-me token, + # and deactivate all sessions + transaction do + update(remember_token: nil, remember_created_at: nil, password: SecureRandom.hex) + session_activations.destroy_all + end + + # Then, remove all authorized applications and connected push subscriptions + Doorkeeper::AccessGrant.by_resource_owner(self).in_batches.update_all(revoked_at: Time.now.utc) + + Doorkeeper::AccessToken.by_resource_owner(self).in_batches do |batch| + batch.update_all(revoked_at: Time.now.utc) + Web::PushSubscription.where(access_token_id: batch).delete_all + end + + # Finally, send a reset password prompt to the user + send_reset_password_instructions + end + def show_all_media? setting_display_media == 'show_all' end diff --git a/app/policies/user_policy.rb b/app/policies/user_policy.rb index d832bff75..6695a0ddf 100644 --- a/app/policies/user_policy.rb +++ b/app/policies/user_policy.rb @@ -13,6 +13,14 @@ class UserPolicy < ApplicationPolicy admin? && !record.staff? end + def disable_sign_in_token_auth? + staff? + end + + def enable_sign_in_token_auth? + staff? + end + def confirm? staff? && !record.confirmed? end diff --git a/app/views/admin/accounts/show.html.haml b/app/views/admin/accounts/show.html.haml index 27e1f80a7..66eb49342 100644 --- a/app/views/admin/accounts/show.html.haml +++ b/app/views/admin/accounts/show.html.haml @@ -129,6 +129,27 @@ - else = t('admin.accounts.confirming') %td= table_link_to 'refresh', t('admin.accounts.resend_confirmation.send'), resend_admin_account_confirmation_path(@account.id), method: :post if can?(:confirm, @account.user) + %tr + %th{ rowspan: can?(:reset_password, @account.user) ? 2 : 1 }= t('admin.accounts.security') + %td{ rowspan: can?(:reset_password, @account.user) ? 2 : 1 } + - if @account.user&.two_factor_enabled? + = t 'admin.accounts.security_measures.password_and_2fa' + - elsif @account.user&.skip_sign_in_token? + = t 'admin.accounts.security_measures.only_password' + - else + = t 'admin.accounts.security_measures.password_and_sign_in_token' + %td + - if @account.user&.two_factor_enabled? + = table_link_to 'unlock', t('admin.accounts.disable_two_factor_authentication'), admin_user_two_factor_authentication_path(@account.user.id), method: :delete if can?(:disable_2fa, @account.user) + - elsif @account.user&.skip_sign_in_token? + = table_link_to 'lock', t('admin.accounts.enable_sign_in_token_auth'), admin_user_sign_in_token_authentication_path(@account.user.id), method: :post if can?(:enable_sign_in_token_auth, @account.user) + - else + = table_link_to 'unlock', t('admin.accounts.disable_sign_in_token_auth'), admin_user_sign_in_token_authentication_path(@account.user.id), method: :delete if can?(:disable_sign_in_token_auth, @account.user) + + - if can?(:reset_password, @account.user) + %tr + %td + = table_link_to 'key', t('admin.accounts.reset_password'), admin_account_reset_path(@account.id), method: :create, data: { confirm: t('admin.accounts.are_you_sure') } %tr %th= t('simple_form.labels.defaults.locale') @@ -221,9 +242,6 @@ %div - if @account.local? - = link_to t('admin.accounts.reset_password'), admin_account_reset_path(@account.id), method: :create, class: 'button' if can?(:reset_password, @account.user) - - if @account.user&.otp_required_for_login? - = link_to t('admin.accounts.disable_two_factor_authentication'), admin_user_two_factor_authentication_path(@account.user.id), method: :delete, class: 'button' if can?(:disable_2fa, @account.user) - if !@account.memorial? && @account.user_approved? = link_to t('admin.accounts.memorialize'), memorialize_admin_account_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button button--destructive' if can?(:memorialize, @account) - else diff --git a/config/locales/en.yml b/config/locales/en.yml index cdb2e3df7..51764a0e1 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -44,7 +44,7 @@ en: rejecting_media: 'Media files from these servers will not be processed or stored, and no thumbnails will be displayed, requiring manual click-through to the original file:' rejecting_media_title: Filtered media silenced: 'Posts from these servers will be hidden in public timelines and conversations, and no notifications will be generated from their users interactions, unless you are following them:' - silenced_title: Silenced servers + silenced_title: Limited servers suspended: 'No data from these servers will be processed, stored or exchanged, making any interaction or communication with users from these servers impossible:' suspended_title: Suspended servers unavailable_content_html: Mastodon generally allows you to view content from and interact with users from any other server in the fediverse. These are the exceptions that have been made on this particular server. @@ -119,6 +119,7 @@ en: demote: Demote destroyed_msg: "%{username}'s data is now queued to be deleted imminently" disable: Freeze + disable_sign_in_token_auth: Disable e-mail token authentication disable_two_factor_authentication: Disable 2FA disabled: Frozen display_name: Display name @@ -127,6 +128,7 @@ en: email: Email email_status: Email status enable: Unfreeze + enable_sign_in_token_auth: Enable e-mail token authentication enabled: Enabled enabled_msg: Successfully unfroze %{username}'s account followers: Followers @@ -151,7 +153,7 @@ en: active: Active all: All pending: Pending - silenced: Silenced + silenced: Limited suspended: Suspended title: Moderation moderation_notes: Moderation notes @@ -191,8 +193,12 @@ en: search: Search search_same_email_domain: Other users with the same e-mail domain search_same_ip: Other users with the same IP - sensitive: Sensitive - sensitized: marked as sensitive + security_measures: + only_password: Only password + password_and_2fa: Password and 2FA + password_and_sign_in_token: Password and e-mail token + sensitive: Force-sensitive + sensitized: Marked as sensitive shared_inbox_url: Shared inbox URL show: created_reports: Made reports @@ -207,10 +213,10 @@ en: time_in_queue: Waiting in queue %{time} title: Accounts unconfirmed_email: Unconfirmed email - undo_sensitized: Undo sensitive - undo_silenced: Undo silence + undo_sensitized: Undo force-sensitive + undo_silenced: Undo limit undo_suspension: Undo suspension - unsilenced_msg: Successfully unlimited %{username}'s account + unsilenced_msg: Successfully undid limit of %{username}'s account unsubscribe: Unsubscribe unsuspended_msg: Successfully unsuspended %{username}'s account username: Username @@ -236,14 +242,16 @@ en: destroy_custom_emoji: Delete Custom Emoji destroy_domain_allow: Delete Domain Allow destroy_domain_block: Delete Domain Block - destroy_email_domain_block: Delete e-mail domain block + destroy_email_domain_block: Delete E-mail Domain Block destroy_ip_block: Delete IP rule destroy_status: Delete Post destroy_unavailable_domain: Delete Unavailable Domain disable_2fa_user: Disable 2FA disable_custom_emoji: Disable Custom Emoji + disable_sign_in_token_auth_user: Disable E-mail Token Authentication for User disable_user: Disable User enable_custom_emoji: Enable Custom Emoji + enable_sign_in_token_auth_user: Enable E-mail Token Authentication for User enable_user: Enable User memorialize_account: Memorialize Account promote_user: Promote User @@ -251,12 +259,12 @@ en: reopen_report: Reopen Report reset_password_user: Reset Password resolve_report: Resolve Report - sensitive_account: Mark the media in your account as sensitive - silence_account: Silence Account + sensitive_account: Force-Sensitive Account + silence_account: Limit Account suspend_account: Suspend Account unassigned_report: Unassign Report - unsensitive_account: Unmark the media in your account as sensitive - unsilence_account: Unsilence Account + unsensitive_account: Undo Force-Sensitive Account + unsilence_account: Undo Limit Account unsuspend_account: Unsuspend Account update_announcement: Update Announcement update_custom_emoji: Update Custom Emoji @@ -285,8 +293,10 @@ en: destroy_unavailable_domain_html: "%{name} resumed delivery to domain %{target}" disable_2fa_user_html: "%{name} disabled two factor requirement for user %{target}" disable_custom_emoji_html: "%{name} disabled emoji %{target}" + disable_sign_in_token_auth_user_html: "%{name} disabled e-mail token authentication for %{target}" disable_user_html: "%{name} disabled login for user %{target}" enable_custom_emoji_html: "%{name} enabled emoji %{target}" + enable_sign_in_token_auth_user_html: "%{name} enabled e-mail token authentication for %{target}" enable_user_html: "%{name} enabled login for user %{target}" memorialize_account_html: "%{name} turned %{target}'s account into a memoriam page" promote_user_html: "%{name} promoted user %{target}" @@ -295,11 +305,11 @@ en: reset_password_user_html: "%{name} reset password of user %{target}" resolve_report_html: "%{name} resolved report %{target}" sensitive_account_html: "%{name} marked %{target}'s media as sensitive" - silence_account_html: "%{name} silenced %{target}'s account" + silence_account_html: "%{name} limited %{target}'s account" suspend_account_html: "%{name} suspended %{target}'s account" unassigned_report_html: "%{name} unassigned report %{target}" unsensitive_account_html: "%{name} unmarked %{target}'s media as sensitive" - unsilence_account_html: "%{name} unsilenced %{target}'s account" + unsilence_account_html: "%{name} undid limit of %{target}'s account" unsuspend_account_html: "%{name} unsuspended %{target}'s account" update_announcement_html: "%{name} updated announcement %{target}" update_custom_emoji_html: "%{name} updated emoji %{target}" @@ -421,14 +431,14 @@ en: rejecting_media: rejecting media files rejecting_reports: rejecting reports severity: - silence: silenced + silence: limited suspend: suspended show: affected_accounts: one: One account in the database affected other: "%{count} accounts in the database affected" retroactive: - silence: Unsilence existing affected accounts from this domain + silence: Undo limit of existing affected accounts from this domain suspend: Unsuspend existing affected accounts from this domain title: Undo domain block for %{domain} undo: Undo diff --git a/config/routes.rb b/config/routes.rb index eb618324a..0c4b29546 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -283,6 +283,7 @@ Rails.application.routes.draw do resources :users, only: [] do resource :two_factor_authentication, only: [:destroy] + resource :sign_in_token_authentication, only: [:create, :destroy] end resources :custom_emojis, only: [:index, :new, :create] do diff --git a/db/migrate/20210621221010_add_skip_sign_in_token_to_users.rb b/db/migrate/20210621221010_add_skip_sign_in_token_to_users.rb new file mode 100644 index 000000000..43ad9b954 --- /dev/null +++ b/db/migrate/20210621221010_add_skip_sign_in_token_to_users.rb @@ -0,0 +1,5 @@ +class AddSkipSignInTokenToUsers < ActiveRecord::Migration[6.1] + def change + add_column :users, :skip_sign_in_token, :boolean + end +end diff --git a/db/schema.rb b/db/schema.rb index 935e2a564..b2929f693 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -927,6 +927,7 @@ ActiveRecord::Schema.define(version: 2021_06_30_000137) do t.datetime "sign_in_token_sent_at" t.string "webauthn_id" t.inet "sign_up_ip" + t.boolean "skip_sign_in_token" t.index ["account_id"], name: "index_users_on_account_id" t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true t.index ["created_by_application_id"], name: "index_users_on_created_by_application_id" diff --git a/lib/mastodon/accounts_cli.rb b/lib/mastodon/accounts_cli.rb index 74162256f..050194801 100644 --- a/lib/mastodon/accounts_cli.rb +++ b/lib/mastodon/accounts_cli.rb @@ -54,7 +54,8 @@ module Mastodon option :email, required: true option :confirmed, type: :boolean - option :role, default: 'user' + option :role, default: 'user', enum: %w(user moderator admin) + option :skip_sign_in_token, type: :boolean option :reattach, type: :boolean option :force, type: :boolean desc 'create USERNAME', 'Create a new user' @@ -68,6 +69,9 @@ module Mastodon With the --role option one of "user", "admin" or "moderator" can be supplied. Defaults to "user" + With the --skip-sign-in-token option, you can ensure that + the user is never asked for an e-mailed security code. + With the --reattach option, the new user will be reattached to a given existing username of an old account. If the old account is still in use by someone else, you can supply @@ -77,7 +81,7 @@ module Mastodon def create(username) account = Account.new(username: username) password = SecureRandom.hex - user = User.new(email: options[:email], password: password, agreement: true, approved: true, admin: options[:role] == 'admin', moderator: options[:role] == 'moderator', confirmed_at: options[:confirmed] ? Time.now.utc : nil, bypass_invite_request_check: true) + user = User.new(email: options[:email], password: password, agreement: true, approved: true, admin: options[:role] == 'admin', moderator: options[:role] == 'moderator', confirmed_at: options[:confirmed] ? Time.now.utc : nil, bypass_invite_request_check: true, skip_sign_in_token: options[:skip_sign_in_token]) if options[:reattach] account = Account.find_local(username) || Account.new(username: username) @@ -113,7 +117,7 @@ module Mastodon end end - option :role + option :role, enum: %w(user moderator admin) option :email option :confirm, type: :boolean option :enable, type: :boolean @@ -121,6 +125,7 @@ module Mastodon option :disable_2fa, type: :boolean option :approve, type: :boolean option :reset_password, type: :boolean + option :skip_sign_in_token, type: :boolean desc 'modify USERNAME', 'Modify a user' long_desc <<-LONG_DESC Modify a user account. @@ -142,6 +147,9 @@ module Mastodon With the --reset-password option, the user's password is replaced by a randomly-generated one, printed in the output. + + With the --skip-sign-in-token option, you can ensure that + the user is never asked for an e-mailed security code. LONG_DESC def modify(username) user = Account.find_local(username)&.user @@ -163,6 +171,7 @@ module Mastodon user.disabled = true if options[:disable] user.approved = true if options[:approve] user.otp_required_for_login = false if options[:disable_2fa] + user.skip_sign_in_token = options[:skip_sign_in_token] unless options[:skip_sign_in_token].nil? user.confirm if options[:confirm] if user.save diff --git a/spec/controllers/admin/resets_controller_spec.rb b/spec/controllers/admin/resets_controller_spec.rb index a20a460bd..c1e34b7f9 100644 --- a/spec/controllers/admin/resets_controller_spec.rb +++ b/spec/controllers/admin/resets_controller_spec.rb @@ -16,7 +16,7 @@ describe Admin::ResetsController do post :create, params: { account_id: account.id } - expect(response).to redirect_to(admin_accounts_path) + expect(response).to redirect_to(admin_account_path(account.id)) end end end diff --git a/spec/controllers/admin/two_factor_authentications_controller_spec.rb b/spec/controllers/admin/two_factor_authentications_controller_spec.rb index b0e82d3d6..c65095729 100644 --- a/spec/controllers/admin/two_factor_authentications_controller_spec.rb +++ b/spec/controllers/admin/two_factor_authentications_controller_spec.rb @@ -15,12 +15,12 @@ describe Admin::TwoFactorAuthenticationsController do user.update(otp_required_for_login: true) end - it 'redirects to admin accounts page' do + it 'redirects to admin account page' do delete :destroy, params: { user_id: user.id } user.reload expect(user.otp_enabled?).to eq false - expect(response).to redirect_to(admin_accounts_path) + expect(response).to redirect_to(admin_account_path(user.account_id)) end end @@ -38,13 +38,13 @@ describe Admin::TwoFactorAuthenticationsController do nickname: 'Security Key') end - it 'redirects to admin accounts page' do + it 'redirects to admin account page' do delete :destroy, params: { user_id: user.id } user.reload expect(user.otp_enabled?).to eq false expect(user.webauthn_enabled?).to eq false - expect(response).to redirect_to(admin_accounts_path) + expect(response).to redirect_to(admin_account_path(user.account_id)) end end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 5db249be2..54bb6db7f 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -344,6 +344,34 @@ RSpec.describe User, type: :model do end end + describe '#reset_password!' do + subject(:user) { Fabricate(:user, password: 'foobar12345') } + + let!(:session_activation) { Fabricate(:session_activation, user: user) } + let!(:access_token) { Fabricate(:access_token, resource_owner_id: user.id) } + let!(:web_push_subscription) { Fabricate(:web_push_subscription, access_token: access_token) } + + before do + user.reset_password! + end + + it 'changes the password immediately' do + expect(user.external_or_valid_password?('foobar12345')).to be false + end + + it 'deactivates all sessions' do + expect(user.session_activations.count).to eq 0 + end + + it 'revokes all access tokens' do + expect(Doorkeeper::AccessToken.active_for(user).count).to eq 0 + end + + it 'removes push subscriptions' do + expect(Web::PushSubscription.where(user: user).or(Web::PushSubscription.where(access_token: access_token)).count).to eq 0 + end + end + describe '#confirm!' do subject(:user) { Fabricate(:user, confirmed_at: confirmed_at) } From 895f1a531d1c2f7ef3352388a9e3502699222c01 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Jul 2021 14:34:32 +0900 Subject: [PATCH 13/18] Bump ws from 7.5.1 to 7.5.2 (#16475) Bumps [ws](https://github.com/websockets/ws) from 7.5.1 to 7.5.2. - [Release notes](https://github.com/websockets/ws/releases) - [Commits](https://github.com/websockets/ws/compare/7.5.1...7.5.2) --- updated-dependencies: - dependency-name: ws dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 6cf923249..517030f78 100644 --- a/package.json +++ b/package.json @@ -168,7 +168,7 @@ "webpack-cli": "^3.3.12", "webpack-merge": "^5.8.0", "wicg-inert": "^3.1.1", - "ws": "^7.5.1" + "ws": "^7.5.2" }, "devDependencies": { "@testing-library/jest-dom": "^5.14.1", diff --git a/yarn.lock b/yarn.lock index bdf2c6c33..53b0e722a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11720,10 +11720,10 @@ ws@^6.2.1: dependencies: async-limiter "~1.0.0" -ws@^7.2.3, ws@^7.3.1, ws@^7.5.1: - version "7.5.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.1.tgz#44fc000d87edb1d9c53e51fbc69a0ac1f6871d66" - integrity sha512-2c6faOUH/nhoQN6abwMloF7Iyl0ZS2E9HGtsiLrWn0zOOMWlhtDmdf/uihDt6jnuCxgtwGBNy6Onsoy2s2O2Ow== +ws@^7.2.3, ws@^7.3.1, ws@^7.5.2: + version "7.5.2" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.2.tgz#09cc8fea3bec1bc5ed44ef51b42f945be36900f6" + integrity sha512-lkF7AWRicoB9mAgjeKbGqVUekLnSNO4VjKVnuPHpQeOxZOErX6BPXwJk70nFslRCEEA8EVW7ZjKwXaP9N+1sKQ== xml-name-validator@^3.0.0: version "3.0.0" From d36cfb99da14804e058efa2c9d828c008401c2ad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Jul 2021 14:35:20 +0900 Subject: [PATCH 14/18] Bump addressable from 2.7.0 to 2.8.0 (#16474) Bumps [addressable](https://github.com/sporkmonger/addressable) from 2.7.0 to 2.8.0. - [Release notes](https://github.com/sporkmonger/addressable/releases) - [Changelog](https://github.com/sporkmonger/addressable/blob/main/CHANGELOG.md) - [Commits](https://github.com/sporkmonger/addressable/compare/addressable-2.7.0...addressable-2.8.0) --- updated-dependencies: - dependency-name: addressable dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 56f52f3e1..a76e69ac3 100644 --- a/Gemfile +++ b/Gemfile @@ -24,7 +24,7 @@ gem 'paperclip', '~> 6.0' gem 'blurhash', '~> 0.1' gem 'active_model_serializers', '~> 0.10' -gem 'addressable', '~> 2.7' +gem 'addressable', '~> 2.8' gem 'bootsnap', '~> 1.6.0', require: false gem 'browser' gem 'charlock_holmes', '~> 0.7.7' diff --git a/Gemfile.lock b/Gemfile.lock index b14dbc129..2875bb3e3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -66,7 +66,7 @@ GEM minitest (>= 5.1) tzinfo (~> 2.0) zeitwerk (~> 2.3) - addressable (2.7.0) + addressable (2.8.0) public_suffix (>= 2.0.2, < 5.0) airbrussh (1.4.0) sshkit (>= 1.6.1, != 1.7.0) @@ -673,7 +673,7 @@ PLATFORMS DEPENDENCIES active_model_serializers (~> 0.10) active_record_query_trace (~> 1.8) - addressable (~> 2.7) + addressable (~> 2.8) annotate (~> 3.1) aws-sdk-s3 (~> 1.96) better_errors (~> 2.9) From e5b4b672f0b8d2768c7d1d5ae80a9698830882a7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Jul 2021 14:35:34 +0900 Subject: [PATCH 15/18] Bump oj from 3.11.7 to 3.11.8 (#16473) Bumps [oj](https://github.com/ohler55/oj) from 3.11.7 to 3.11.8. - [Release notes](https://github.com/ohler55/oj/releases) - [Changelog](https://github.com/ohler55/oj/blob/develop/CHANGELOG.md) - [Commits](https://github.com/ohler55/oj/compare/v3.11.7...v3.11.8) --- updated-dependencies: - dependency-name: oj dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 2875bb3e3..17b6f152b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -374,7 +374,7 @@ GEM concurrent-ruby (~> 1.0, >= 1.0.2) sidekiq (>= 3.5) statsd-ruby (~> 1.4, >= 1.4.0) - oj (3.11.7) + oj (3.11.8) omniauth (1.9.1) hashie (>= 3.4.6) rack (>= 1.6.2, < 3) From 6eaa39c3873adc8c0ade8e8138773b590b7ccc1d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Jul 2021 14:35:45 +0900 Subject: [PATCH 16/18] Bump sidekiq-unique-jobs from 7.1.1 to 7.1.2 (#16472) Bumps [sidekiq-unique-jobs](https://github.com/mhenrixon/sidekiq-unique-jobs) from 7.1.1 to 7.1.2. - [Release notes](https://github.com/mhenrixon/sidekiq-unique-jobs/releases) - [Changelog](https://github.com/mhenrixon/sidekiq-unique-jobs/blob/master/CHANGELOG.md) - [Commits](https://github.com/mhenrixon/sidekiq-unique-jobs/compare/v7.1.1...v7.1.2) --- updated-dependencies: - dependency-name: sidekiq-unique-jobs dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 17b6f152b..efc3f544f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -569,7 +569,7 @@ GEM sidekiq (>= 3) thwait tilt (>= 1.4.0) - sidekiq-unique-jobs (7.1.1) + sidekiq-unique-jobs (7.1.2) brpoplpush-redis_script (> 0.1.1, <= 2.0.0) concurrent-ruby (~> 1.0, >= 1.0.5) sidekiq (>= 5.0, < 7.0) From ca662c13f03b50aa50479110db2d11777dd8d453 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Jul 2021 14:37:06 +0900 Subject: [PATCH 17/18] Bump rubocop-rails from 2.11.1 to 2.11.2 (#16471) Bumps [rubocop-rails](https://github.com/rubocop/rubocop-rails) from 2.11.1 to 2.11.2. - [Release notes](https://github.com/rubocop/rubocop-rails/releases) - [Changelog](https://github.com/rubocop/rubocop-rails/blob/master/CHANGELOG.md) - [Commits](https://github.com/rubocop/rubocop-rails/compare/v2.11.1...v2.11.2) --- updated-dependencies: - dependency-name: rubocop-rails dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index efc3f544f..6885c28af 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -535,7 +535,7 @@ GEM unicode-display_width (>= 1.4.0, < 3.0) rubocop-ast (1.7.0) parser (>= 3.0.1.1) - rubocop-rails (2.11.1) + rubocop-rails (2.11.2) activesupport (>= 4.2.0) rack (>= 1.1) rubocop (>= 1.7.0, < 2.0) From c4568e3b606cc4007739f881c334bdfe8dc77745 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Jul 2021 14:37:18 +0900 Subject: [PATCH 18/18] Bump rubocop from 1.18.1 to 1.18.2 (#16470) Bumps [rubocop](https://github.com/rubocop/rubocop) from 1.18.1 to 1.18.2. - [Release notes](https://github.com/rubocop/rubocop/releases) - [Changelog](https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md) - [Commits](https://github.com/rubocop/rubocop/compare/v1.18.1...v1.18.2) --- updated-dependencies: - dependency-name: rubocop dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 6885c28af..96d89fbae 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -524,7 +524,7 @@ GEM rspec-support (3.10.2) rspec_junit_formatter (0.4.1) rspec-core (>= 2, < 4, != 2.12.0) - rubocop (1.18.1) + rubocop (1.18.2) parallel (~> 1.10) parser (>= 3.0.0.0) rainbow (>= 2.2.2, < 4.0)