From 7d575c669e4c67e6044fb48bc4012c10359136bd Mon Sep 17 00:00:00 2001 From: ThibG Date: Sun, 1 Mar 2020 22:25:13 +0100 Subject: [PATCH 01/29] Bump puma from 4.3.2 to 4.3.3 (#13177) This fixes cookies and devise authentication being broken as a result of upgrading to puma 4.3.2, see https://github.com/puma/puma/issues/2132 --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 59ab2ba7c..6c13a4aa1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -435,7 +435,7 @@ GEM pry-rails (0.3.9) pry (>= 0.10.4) public_suffix (4.0.3) - puma (4.3.2) + puma (4.3.3) nio4r (~> 2.0) pundit (2.1.0) activesupport (>= 3.0.0) From 74c2490cddd062bde9ede51456da64a47c8f09ff Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 2 Mar 2020 21:44:44 +0900 Subject: [PATCH 02/29] Bump strong_migrations from 0.5.1 to 0.6.2 (#13071) Bumps [strong_migrations](https://github.com/ankane/strong_migrations) from 0.5.1 to 0.6.2. - [Release notes](https://github.com/ankane/strong_migrations/releases) - [Changelog](https://github.com/ankane/strong_migrations/blob/master/CHANGELOG.md) - [Commits](https://github.com/ankane/strong_migrations/compare/v0.5.1...v0.6.2) Signed-off-by: dependabot-preview[bot] --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 07959fd3d..5f7ad430b 100644 --- a/Gemfile +++ b/Gemfile @@ -92,7 +92,7 @@ gem 'simple-navigation', '~> 4.1' gem 'simple_form', '~> 5.0' gem 'sprockets-rails', '~> 3.2', require: 'sprockets/railtie' gem 'stoplight', '~> 2.2.0' -gem 'strong_migrations', '~> 0.5' +gem 'strong_migrations', '~> 0.6' gem 'tty-command', '~> 0.9', require: false gem 'tty-prompt', '~> 0.20', require: false gem 'twitter-text', '~> 1.14' diff --git a/Gemfile.lock b/Gemfile.lock index 6c13a4aa1..d815fefc3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -602,7 +602,7 @@ GEM stoplight (2.2.0) streamio-ffmpeg (3.0.2) multi_json (~> 1.8) - strong_migrations (0.5.1) + strong_migrations (0.6.2) activerecord (>= 5) temple (0.8.2) terminal-table (1.8.0) @@ -777,7 +777,7 @@ DEPENDENCIES stackprof stoplight (~> 2.2.0) streamio-ffmpeg (~> 3.0) - strong_migrations (~> 0.5) + strong_migrations (~> 0.6) thor (~> 0.20) thwait (~> 0.1.0) tty-command (~> 0.9) From 95155ecbe7b86c4c180a78d7ef296822ba673d73 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 2 Mar 2020 21:46:56 +0900 Subject: [PATCH 03/29] Bump oj from 3.10.1 to 3.10.3 (#13187) Bumps [oj](https://github.com/ohler55/oj) from 3.10.1 to 3.10.3. - [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.10.1...v3.10.3) Signed-off-by: dependabot-preview[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index d815fefc3..9dda8efe5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -383,7 +383,7 @@ GEM concurrent-ruby (~> 1.0, >= 1.0.2) sidekiq (>= 3.5) statsd-ruby (~> 1.4, >= 1.4.0) - oj (3.10.1) + oj (3.10.3) omniauth (1.9.0) hashie (>= 3.4.6, < 3.7.0) rack (>= 1.6.2, < 3) From 66b014ca50938d3ef725fb63fa3c26e0c6f3d438 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 2 Mar 2020 21:48:02 +0900 Subject: [PATCH 04/29] Bump json-ld-preloaded from 3.1.0 to 3.1.1 (#13143) Bumps [json-ld-preloaded](https://github.com/ruby-rdf/json-ld-preloaded) from 3.1.0 to 3.1.1. - [Release notes](https://github.com/ruby-rdf/json-ld-preloaded/releases) - [Commits](https://github.com/ruby-rdf/json-ld-preloaded/compare/3.1.0...3.1.1) Signed-off-by: dependabot-preview[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 9dda8efe5..9dcd36f4a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -311,7 +311,7 @@ GEM multi_json (~> 1.14) rack (~> 2.0) rdf (~> 3.1) - json-ld-preloaded (3.1.0) + json-ld-preloaded (3.1.1) json-ld (~> 3.1) rdf (~> 3.1) jsonapi-renderer (0.2.2) From 131c16f0bcc5efd9ccc24f1ca66955e3c0cb7c9c Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 2 Mar 2020 21:49:40 +0900 Subject: [PATCH 05/29] Bump @babel/core from 7.8.4 to 7.8.6 (#13185) Bumps [@babel/core](https://github.com/babel/babel) from 7.8.4 to 7.8.6. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/master/CHANGELOG.md) - [Commits](https://github.com/babel/babel/compare/v7.8.4...v7.8.6) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 70 ++++++++++++++++++++++++++-------------------------- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/package.json b/package.json index 1a873615d..deb5ff8fd 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ }, "private": true, "dependencies": { - "@babel/core": "^7.8.4", + "@babel/core": "^7.8.6", "@babel/plugin-proposal-class-properties": "^7.8.3", "@babel/plugin-proposal-decorators": "^7.8.3", "@babel/plugin-transform-react-inline-elements": "^7.8.3", diff --git a/yarn.lock b/yarn.lock index 8814eb961..d5ff8afdf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18,18 +18,18 @@ invariant "^2.2.4" semver "^5.5.0" -"@babel/core@^7.1.0", "@babel/core@^7.4.5", "@babel/core@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.4.tgz#d496799e5c12195b3602d0fddd77294e3e38e80e" - integrity sha512-0LiLrB2PwrVI+a2/IEskBopDYSd8BCb3rOvH7D5tzoWd696TBEduBvuLVm4Nx6rltrLZqvI3MCalB2K2aVzQjA== +"@babel/core@^7.1.0", "@babel/core@^7.4.5", "@babel/core@^7.8.6": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.6.tgz#27d7df9258a45c2e686b6f18b6c659e563aa4636" + integrity sha512-Sheg7yEJD51YHAvLEV/7Uvw95AeWqYPL3Vk3zGujJKIhJ+8oLw2ALaf3hbucILhKsgSoADOvtKRJuNVdcJkOrg== dependencies: "@babel/code-frame" "^7.8.3" - "@babel/generator" "^7.8.4" + "@babel/generator" "^7.8.6" "@babel/helpers" "^7.8.4" - "@babel/parser" "^7.8.4" - "@babel/template" "^7.8.3" - "@babel/traverse" "^7.8.4" - "@babel/types" "^7.8.3" + "@babel/parser" "^7.8.6" + "@babel/template" "^7.8.6" + "@babel/traverse" "^7.8.6" + "@babel/types" "^7.8.6" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.1" @@ -39,12 +39,12 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.0.0", "@babel/generator@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.4.tgz#35bbc74486956fe4251829f9f6c48330e8d0985e" - integrity sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA== +"@babel/generator@^7.0.0", "@babel/generator@^7.8.6": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.6.tgz#57adf96d370c9a63c241cd719f9111468578537a" + integrity sha512-4bpOR5ZBz+wWcMeVtcf7FbjcFzCp+817z2/gHNncIRcM9MmKzUhtWCYAq27RAfUrAFwb+OCG1s9WEaVxfi6cjg== dependencies: - "@babel/types" "^7.8.3" + "@babel/types" "^7.8.6" jsesc "^2.5.1" lodash "^4.17.13" source-map "^0.5.0" @@ -261,10 +261,10 @@ esutils "^2.0.2" js-tokens "^4.0.0" -"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.8.3", "@babel/parser@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.4.tgz#d1dbe64691d60358a974295fa53da074dd2ce8e8" - integrity sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw== +"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.8.6": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.6.tgz#ba5c9910cddb77685a008e3c587af8d27b67962c" + integrity sha512-trGNYSfwq5s0SgM1BMEB8hX3NDmO7EP2wsDGDexiaKMB92BaRpS+qZfpkMqUBhcsOTBwNy9B/jieo4ad/t/z2g== "@babel/plugin-proposal-async-generator-functions@^7.8.3": version "7.8.3" @@ -808,34 +808,34 @@ dependencies: regenerator-runtime "^0.13.2" -"@babel/template@^7.0.0", "@babel/template@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.3.tgz#e02ad04fe262a657809327f578056ca15fd4d1b8" - integrity sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ== +"@babel/template@^7.0.0", "@babel/template@^7.8.3", "@babel/template@^7.8.6": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b" + integrity sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg== dependencies: "@babel/code-frame" "^7.8.3" - "@babel/parser" "^7.8.3" - "@babel/types" "^7.8.3" + "@babel/parser" "^7.8.6" + "@babel/types" "^7.8.6" -"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.4.tgz#f0845822365f9d5b0e312ed3959d3f827f869e3c" - integrity sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg== +"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.4", "@babel/traverse@^7.8.6": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.6.tgz#acfe0c64e1cd991b3e32eae813a6eb564954b5ff" + integrity sha512-2B8l0db/DPi8iinITKuo7cbPznLCEk0kCxDoB9/N6gGNg/gxOXiR/IcymAFPiBwk5w6TtQ27w4wpElgp9btR9A== dependencies: "@babel/code-frame" "^7.8.3" - "@babel/generator" "^7.8.4" + "@babel/generator" "^7.8.6" "@babel/helper-function-name" "^7.8.3" "@babel/helper-split-export-declaration" "^7.8.3" - "@babel/parser" "^7.8.4" - "@babel/types" "^7.8.3" + "@babel/parser" "^7.8.6" + "@babel/types" "^7.8.6" debug "^4.1.0" globals "^11.1.0" lodash "^4.17.13" -"@babel/types@^7.0.0", "@babel/types@^7.0.0-beta.49", "@babel/types@^7.3.0", "@babel/types@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.3.tgz#5a383dffa5416db1b73dedffd311ffd0788fb31c" - integrity sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg== +"@babel/types@^7.0.0", "@babel/types@^7.0.0-beta.49", "@babel/types@^7.3.0", "@babel/types@^7.8.3", "@babel/types@^7.8.6": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.6.tgz#629ecc33c2557fcde7126e58053127afdb3e6d01" + integrity sha512-wqz7pgWMIrht3gquyEFPVXeXCti72Rm8ep9b5tQKz9Yg9LzJA3HxosF1SB3Kc81KD1A3XBkkVYtJvCKS2Z/QrA== dependencies: esutils "^2.0.2" lodash "^4.17.13" From 3d8a6dc043c0d2c7ff535fa05d3f1ba289851ec7 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 2 Mar 2020 21:55:32 +0900 Subject: [PATCH 06/29] Bump webpack-dev-server from 3.10.1 to 3.10.3 (#13184) Bumps [webpack-dev-server](https://github.com/webpack/webpack-dev-server) from 3.10.1 to 3.10.3. - [Release notes](https://github.com/webpack/webpack-dev-server/releases) - [Changelog](https://github.com/webpack/webpack-dev-server/blob/master/CHANGELOG.md) - [Commits](https://github.com/webpack/webpack-dev-server/compare/v3.10.1...v3.10.3) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index deb5ff8fd..3fa2eca52 100644 --- a/package.json +++ b/package.json @@ -184,7 +184,7 @@ "react-intl-translations-manager": "^5.0.3", "react-test-renderer": "^16.12.0", "sass-lint": "^1.13.1", - "webpack-dev-server": "^3.10.1", + "webpack-dev-server": "^3.10.3", "yargs": "^15.1.0" } } diff --git a/yarn.lock b/yarn.lock index d5ff8afdf..b2bccee34 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10860,10 +10860,10 @@ webpack-dev-middleware@^3.7.2: range-parser "^1.2.1" webpack-log "^2.0.0" -webpack-dev-server@^3.10.1: - version "3.10.1" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.10.1.tgz#1ff3e5cccf8e0897aa3f5909c654e623f69b1c0e" - integrity sha512-AGG4+XrrXn4rbZUueyNrQgO4KGnol+0wm3MPdqGLmmA+NofZl3blZQKxZ9BND6RDNuvAK9OMYClhjOSnxpWRoA== +webpack-dev-server@^3.10.3: + version "3.10.3" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.10.3.tgz#f35945036813e57ef582c2420ef7b470e14d3af0" + integrity sha512-e4nWev8YzEVNdOMcNzNeCN947sWJNd43E5XvsJzbAL08kGc2frm1tQ32hTJslRS+H65LCb/AaUCYU7fjHCpDeQ== dependencies: ansi-html "0.0.7" bonjour "^3.5.0" From 86c932f79cdf94989721a467c716b1237992a5dc Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 2 Mar 2020 21:55:52 +0900 Subject: [PATCH 07/29] Bump @babel/runtime from 7.8.3 to 7.8.4 (#13183) Bumps [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) from 7.8.3 to 7.8.4. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/master/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.8.4/packages/babel-runtime) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 3fa2eca52..13a6789a4 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "@babel/plugin-transform-runtime": "^7.8.3", "@babel/preset-env": "^7.8.3", "@babel/preset-react": "^7.8.3", - "@babel/runtime": "^7.8.3", + "@babel/runtime": "^7.8.4", "@clusterws/cws": "^0.17.3", "@gamestdio/websocket": "^0.3.2", "array-includes": "^3.1.1", diff --git a/yarn.lock b/yarn.lock index b2bccee34..c0655e71a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -801,10 +801,10 @@ dependencies: regenerator-runtime "^0.12.0" -"@babel/runtime@^7.1.2", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.8.3.tgz#0811944f73a6c926bb2ad35e918dcc1bfab279f1" - integrity sha512-fVHx1rzEmwB130VTkLnxR+HmxcTjGzH12LYQcFFoBwakMd3aOMD4OsRN7tGG/UOYE2ektgFrS8uACAoRk1CY0w== +"@babel/runtime@^7.1.2", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.8.4.tgz#d79f5a2040f7caa24d53e563aad49cbc05581308" + integrity sha512-neAp3zt80trRVBI1x0azq6c57aNBqYZH8KhMm3TaB7wEI5Q4A2SHfBHE8w9gOhI/lrqxtEbXZgQIrHP+wvSGwQ== dependencies: regenerator-runtime "^0.13.2" From 036ba3f51065a96cb9203a9ac5aa71d7d6edeebe Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 5 Mar 2020 15:52:15 +0100 Subject: [PATCH 08/29] Add tooltips to audio/video player buttons (#13203) --- app/javascript/mastodon/features/audio/index.js | 6 +++--- app/javascript/mastodon/features/video/index.js | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/javascript/mastodon/features/audio/index.js b/app/javascript/mastodon/features/audio/index.js index fda5a074f..95c9c7751 100644 --- a/app/javascript/mastodon/features/audio/index.js +++ b/app/javascript/mastodon/features/audio/index.js @@ -214,8 +214,8 @@ class Audio extends React.PureComponent {
- - + +
  @@ -236,7 +236,7 @@ class Audio extends React.PureComponent {
- - + +
  @@ -517,11 +517,11 @@ class Video extends React.PureComponent {
- {(!onCloseVideo && !editable && !fullscreen) && } - {(!fullscreen && onOpenVideo) && } - {onCloseVideo && } - - + {(!onCloseVideo && !editable && !fullscreen) && } + {(!fullscreen && onOpenVideo) && } + {onCloseVideo && } + +
From d081a80cff8e53a0ff48fb4274bc615166478b40 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 5 Mar 2020 15:56:01 +0100 Subject: [PATCH 09/29] Fix "tootctl media remove-orphans" crashing when encountering invalid media (#13170) Fixes #13168 --- app/models/media_attachment.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/media_attachment.rb b/app/models/media_attachment.rb index 42364641f..1e36625ca 100644 --- a/app/models/media_attachment.rb +++ b/app/models/media_attachment.rb @@ -170,6 +170,7 @@ class MediaAttachment < ApplicationRecord def variant?(other_file_name) return true if file_file_name == other_file_name + return false if file_file_name.nil? formats = file.styles.values.map(&:format).compact From 39453de232e068f58a711b2c052fe74fdd0c40b6 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 5 Mar 2020 23:20:49 +0100 Subject: [PATCH 10/29] =?UTF-8?q?Change=20the=20string=20"Hide=20everythin?= =?UTF-8?q?g=20from=20=E2=80=A6"=20to=20"Block=20domain=20=E2=80=A6"=20in?= =?UTF-8?q?=20web=20UI=20(#13178)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Blocking a domain is closer to blocking all its users than to a mute action. --- .../mastodon/components/status_action_bar.js | 4 ++-- .../features/account/components/header.js | 4 ++-- .../features/status/components/action_bar.js | 4 ++-- .../mastodon/locales/defaultMessages.json | 18 +++++++++--------- app/javascript/mastodon/locales/en.json | 4 ++-- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/app/javascript/mastodon/components/status_action_bar.js b/app/javascript/mastodon/components/status_action_bar.js index e2c8d43c9..bebbbcb5a 100644 --- a/app/javascript/mastodon/components/status_action_bar.js +++ b/app/javascript/mastodon/components/status_action_bar.js @@ -36,8 +36,8 @@ const messages = defineMessages({ admin_account: { id: 'status.admin_account', defaultMessage: 'Open moderation interface for @{name}' }, admin_status: { id: 'status.admin_status', defaultMessage: 'Open this status in the moderation interface' }, copy: { id: 'status.copy', defaultMessage: 'Copy link to status' }, - blockDomain: { id: 'account.block_domain', defaultMessage: 'Hide everything from {domain}' }, - unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unhide {domain}' }, + blockDomain: { id: 'account.block_domain', defaultMessage: 'Block domain {domain}' }, + unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unblock domain {domain}' }, unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' }, unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' }, }); diff --git a/app/javascript/mastodon/features/account/components/header.js b/app/javascript/mastodon/features/account/components/header.js index 8bd7f2db5..35cc3952f 100644 --- a/app/javascript/mastodon/features/account/components/header.js +++ b/app/javascript/mastodon/features/account/components/header.js @@ -29,8 +29,8 @@ const messages = defineMessages({ report: { id: 'account.report', defaultMessage: 'Report @{name}' }, share: { id: 'account.share', defaultMessage: 'Share @{name}\'s profile' }, media: { id: 'account.media', defaultMessage: 'Media' }, - blockDomain: { id: 'account.block_domain', defaultMessage: 'Hide everything from {domain}' }, - unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unhide {domain}' }, + blockDomain: { id: 'account.block_domain', defaultMessage: 'Block domain {domain}' }, + unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unblock domain {domain}' }, hideReblogs: { id: 'account.hide_reblogs', defaultMessage: 'Hide boosts from @{name}' }, showReblogs: { id: 'account.show_reblogs', defaultMessage: 'Show boosts from @{name}' }, pins: { id: 'navigation_bar.pins', defaultMessage: 'Pinned toots' }, diff --git a/app/javascript/mastodon/features/status/components/action_bar.js b/app/javascript/mastodon/features/status/components/action_bar.js index 959774da4..ba62d7b10 100644 --- a/app/javascript/mastodon/features/status/components/action_bar.js +++ b/app/javascript/mastodon/features/status/components/action_bar.js @@ -32,8 +32,8 @@ const messages = defineMessages({ admin_account: { id: 'status.admin_account', defaultMessage: 'Open moderation interface for @{name}' }, admin_status: { id: 'status.admin_status', defaultMessage: 'Open this status in the moderation interface' }, copy: { id: 'status.copy', defaultMessage: 'Copy link to status' }, - blockDomain: { id: 'account.block_domain', defaultMessage: 'Hide everything from {domain}' }, - unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unhide {domain}' }, + blockDomain: { id: 'account.block_domain', defaultMessage: 'Block domain {domain}' }, + unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unblock domain {domain}' }, unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' }, unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' }, }); diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json index 0eb054acd..4c1fe94c5 100644 --- a/app/javascript/mastodon/locales/defaultMessages.json +++ b/app/javascript/mastodon/locales/defaultMessages.json @@ -142,7 +142,7 @@ { "descriptors": [ { - "defaultMessage": "Unhide {domain}", + "defaultMessage": "Unblock domain {domain}", "id": "account.unblock_domain" } ], @@ -451,11 +451,11 @@ "id": "status.copy" }, { - "defaultMessage": "Hide everything from {domain}", + "defaultMessage": "Block domain {domain}", "id": "account.block_domain" }, { - "defaultMessage": "Unhide {domain}", + "defaultMessage": "Unblock domain {domain}", "id": "account.unblock_domain" }, { @@ -697,11 +697,11 @@ "id": "account.media" }, { - "defaultMessage": "Hide everything from {domain}", + "defaultMessage": "Block domain {domain}", "id": "account.block_domain" }, { - "defaultMessage": "Unhide {domain}", + "defaultMessage": "Unblock domain {domain}", "id": "account.unblock_domain" }, { @@ -1470,7 +1470,7 @@ "id": "column.domain_blocks" }, { - "defaultMessage": "Unhide {domain}", + "defaultMessage": "Unblock domain {domain}", "id": "account.unblock_domain" }, { @@ -2384,11 +2384,11 @@ "id": "status.copy" }, { - "defaultMessage": "Hide everything from {domain}", + "defaultMessage": "Block domain {domain}", "id": "account.block_domain" }, { - "defaultMessage": "Unhide {domain}", + "defaultMessage": "Unblock domain {domain}", "id": "account.unblock_domain" }, { @@ -2944,4 +2944,4 @@ ], "path": "app/javascript/mastodon/features/video/index.json" } -] \ No newline at end of file +] diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index 5927aeb6c..fff449a51 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -3,7 +3,7 @@ "account.badges.bot": "Bot", "account.badges.group": "Group", "account.block": "Block @{name}", - "account.block_domain": "Hide everything from {domain}", + "account.block_domain": "Block domain {domain}", "account.blocked": "Blocked", "account.cancel_follow_request": "Cancel follow request", "account.direct": "Direct message @{name}", @@ -34,7 +34,7 @@ "account.share": "Share @{name}'s profile", "account.show_reblogs": "Show boosts from @{name}", "account.unblock": "Unblock @{name}", - "account.unblock_domain": "Unhide {domain}", + "account.unblock_domain": "Unblock domain {domain}", "account.unendorse": "Don't feature on profile", "account.unfollow": "Unfollow", "account.unmute": "Unmute @{name}", From 0ae5c6312fa4c65b6b7bd7a00eb8960b8a69e951 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 6 Mar 2020 01:29:38 +0100 Subject: [PATCH 11/29] Remove useless `respond_to` calls (#13208) --- .../api/v1/accounts/follower_accounts_controller.rb | 2 -- .../api/v1/accounts/following_accounts_controller.rb | 2 -- app/controllers/api/v1/accounts/identity_proofs_controller.rb | 2 -- app/controllers/api/v1/accounts/lists_controller.rb | 2 -- app/controllers/api/v1/accounts/pins_controller.rb | 2 -- app/controllers/api/v1/accounts/relationships_controller.rb | 2 -- app/controllers/api/v1/accounts/search_controller.rb | 2 -- app/controllers/api/v1/accounts/statuses_controller.rb | 2 -- app/controllers/api/v1/accounts_controller.rb | 2 -- app/controllers/api/v1/apps/credentials_controller.rb | 2 -- app/controllers/api/v1/blocks_controller.rb | 2 -- app/controllers/api/v1/bookmarks_controller.rb | 2 -- app/controllers/api/v1/conversations_controller.rb | 2 -- app/controllers/api/v1/custom_emojis_controller.rb | 2 -- app/controllers/api/v1/domain_blocks_controller.rb | 2 -- app/controllers/api/v1/endorsements_controller.rb | 2 -- app/controllers/api/v1/favourites_controller.rb | 2 -- app/controllers/api/v1/featured_tags/suggestions_controller.rb | 3 --- app/controllers/api/v1/filters_controller.rb | 2 -- app/controllers/api/v1/instances/activity_controller.rb | 2 -- app/controllers/api/v1/instances/peers_controller.rb | 2 -- app/controllers/api/v1/instances_controller.rb | 2 -- app/controllers/api/v1/media_controller.rb | 2 -- app/controllers/api/v1/mutes_controller.rb | 2 -- app/controllers/api/v1/notifications_controller.rb | 2 -- app/controllers/api/v1/polls/votes_controller.rb | 2 -- app/controllers/api/v1/polls_controller.rb | 2 -- app/controllers/api/v1/preferences_controller.rb | 2 -- app/controllers/api/v1/reports_controller.rb | 2 -- app/controllers/api/v1/statuses/bookmarks_controller.rb | 2 -- .../api/v1/statuses/favourited_by_accounts_controller.rb | 2 -- app/controllers/api/v1/statuses/favourites_controller.rb | 2 -- app/controllers/api/v1/statuses/mutes_controller.rb | 2 -- app/controllers/api/v1/statuses/pins_controller.rb | 2 -- .../api/v1/statuses/reblogged_by_accounts_controller.rb | 2 -- app/controllers/api/v1/statuses/reblogs_controller.rb | 2 -- app/controllers/api/v1/statuses_controller.rb | 2 -- app/controllers/api/v1/streaming_controller.rb | 2 -- app/controllers/api/v1/suggestions_controller.rb | 2 -- app/controllers/api/v1/timelines/home_controller.rb | 2 -- app/controllers/api/v1/timelines/public_controller.rb | 2 -- app/controllers/api/v1/timelines/tag_controller.rb | 2 -- app/controllers/api/v1/trends_controller.rb | 2 -- app/controllers/api/v2/search_controller.rb | 2 -- app/controllers/api/web/embeds_controller.rb | 2 -- app/controllers/api/web/push_subscriptions_controller.rb | 2 -- app/controllers/api/web/settings_controller.rb | 2 -- 47 files changed, 95 deletions(-) diff --git a/app/controllers/api/v1/accounts/follower_accounts_controller.rb b/app/controllers/api/v1/accounts/follower_accounts_controller.rb index e360b8a92..850702cca 100644 --- a/app/controllers/api/v1/accounts/follower_accounts_controller.rb +++ b/app/controllers/api/v1/accounts/follower_accounts_controller.rb @@ -5,8 +5,6 @@ class Api::V1::Accounts::FollowerAccountsController < Api::BaseController before_action :set_account after_action :insert_pagination_headers - respond_to :json - def index @accounts = load_accounts render json: @accounts, each_serializer: REST::AccountSerializer diff --git a/app/controllers/api/v1/accounts/following_accounts_controller.rb b/app/controllers/api/v1/accounts/following_accounts_controller.rb index a405b365f..830dcd8a1 100644 --- a/app/controllers/api/v1/accounts/following_accounts_controller.rb +++ b/app/controllers/api/v1/accounts/following_accounts_controller.rb @@ -5,8 +5,6 @@ class Api::V1::Accounts::FollowingAccountsController < Api::BaseController before_action :set_account after_action :insert_pagination_headers - respond_to :json - def index @accounts = load_accounts render json: @accounts, each_serializer: REST::AccountSerializer diff --git a/app/controllers/api/v1/accounts/identity_proofs_controller.rb b/app/controllers/api/v1/accounts/identity_proofs_controller.rb index bea51ae11..8dad6fee9 100644 --- a/app/controllers/api/v1/accounts/identity_proofs_controller.rb +++ b/app/controllers/api/v1/accounts/identity_proofs_controller.rb @@ -4,8 +4,6 @@ class Api::V1::Accounts::IdentityProofsController < Api::BaseController before_action :require_user! before_action :set_account - respond_to :json - def index @proofs = @account.identity_proofs.active render json: @proofs, each_serializer: REST::IdentityProofSerializer diff --git a/app/controllers/api/v1/accounts/lists_controller.rb b/app/controllers/api/v1/accounts/lists_controller.rb index 72392453c..ccb751f8f 100644 --- a/app/controllers/api/v1/accounts/lists_controller.rb +++ b/app/controllers/api/v1/accounts/lists_controller.rb @@ -5,8 +5,6 @@ class Api::V1::Accounts::ListsController < Api::BaseController before_action :require_user! before_action :set_account - respond_to :json - def index @lists = @account.lists.where(account: current_account) render json: @lists, each_serializer: REST::ListSerializer diff --git a/app/controllers/api/v1/accounts/pins_controller.rb b/app/controllers/api/v1/accounts/pins_controller.rb index 0a0239c42..3915b5669 100644 --- a/app/controllers/api/v1/accounts/pins_controller.rb +++ b/app/controllers/api/v1/accounts/pins_controller.rb @@ -7,8 +7,6 @@ class Api::V1::Accounts::PinsController < Api::BaseController before_action :require_user! before_action :set_account - respond_to :json - def create AccountPin.create!(account: current_account, target_account: @account) render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships_presenter diff --git a/app/controllers/api/v1/accounts/relationships_controller.rb b/app/controllers/api/v1/accounts/relationships_controller.rb index ab8a0461f..1d3992a28 100644 --- a/app/controllers/api/v1/accounts/relationships_controller.rb +++ b/app/controllers/api/v1/accounts/relationships_controller.rb @@ -4,8 +4,6 @@ class Api::V1::Accounts::RelationshipsController < Api::BaseController before_action -> { doorkeeper_authorize! :read, :'read:follows' } before_action :require_user! - respond_to :json - def index accounts = Account.where(id: account_ids).select('id') # .where doesn't guarantee that our results are in the same order diff --git a/app/controllers/api/v1/accounts/search_controller.rb b/app/controllers/api/v1/accounts/search_controller.rb index 4217b527a..3061fcb7e 100644 --- a/app/controllers/api/v1/accounts/search_controller.rb +++ b/app/controllers/api/v1/accounts/search_controller.rb @@ -4,8 +4,6 @@ class Api::V1::Accounts::SearchController < Api::BaseController before_action -> { doorkeeper_authorize! :read, :'read:accounts' } before_action :require_user! - respond_to :json - def show @accounts = account_search render json: @accounts, each_serializer: REST::AccountSerializer diff --git a/app/controllers/api/v1/accounts/statuses_controller.rb b/app/controllers/api/v1/accounts/statuses_controller.rb index 333db9618..114ee0a82 100644 --- a/app/controllers/api/v1/accounts/statuses_controller.rb +++ b/app/controllers/api/v1/accounts/statuses_controller.rb @@ -6,8 +6,6 @@ class Api::V1::Accounts::StatusesController < Api::BaseController after_action :insert_pagination_headers, unless: -> { truthy_param?(:pinned) } - respond_to :json - def index @statuses = load_statuses render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id) diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb index d68d2715f..f5b06862b 100644 --- a/app/controllers/api/v1/accounts_controller.rb +++ b/app/controllers/api/v1/accounts_controller.rb @@ -14,8 +14,6 @@ class Api::V1::AccountsController < Api::BaseController skip_before_action :require_authenticated_user!, only: :create - respond_to :json - def show render json: @account, serializer: REST::AccountSerializer end diff --git a/app/controllers/api/v1/apps/credentials_controller.rb b/app/controllers/api/v1/apps/credentials_controller.rb index 8b63d0490..0475b2d4a 100644 --- a/app/controllers/api/v1/apps/credentials_controller.rb +++ b/app/controllers/api/v1/apps/credentials_controller.rb @@ -3,8 +3,6 @@ class Api::V1::Apps::CredentialsController < Api::BaseController before_action -> { doorkeeper_authorize! :read } - respond_to :json - def show render json: doorkeeper_token.application, serializer: REST::ApplicationSerializer, fields: %i(name website vapid_key) end diff --git a/app/controllers/api/v1/blocks_controller.rb b/app/controllers/api/v1/blocks_controller.rb index 4cff04cad..a2baeef90 100644 --- a/app/controllers/api/v1/blocks_controller.rb +++ b/app/controllers/api/v1/blocks_controller.rb @@ -5,8 +5,6 @@ class Api::V1::BlocksController < Api::BaseController before_action :require_user! after_action :insert_pagination_headers - respond_to :json - def index @accounts = load_accounts render json: @accounts, each_serializer: REST::AccountSerializer diff --git a/app/controllers/api/v1/bookmarks_controller.rb b/app/controllers/api/v1/bookmarks_controller.rb index e1b244e76..c15212f0a 100644 --- a/app/controllers/api/v1/bookmarks_controller.rb +++ b/app/controllers/api/v1/bookmarks_controller.rb @@ -5,8 +5,6 @@ class Api::V1::BookmarksController < Api::BaseController before_action :require_user! after_action :insert_pagination_headers - respond_to :json - def index @statuses = load_statuses render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id) diff --git a/app/controllers/api/v1/conversations_controller.rb b/app/controllers/api/v1/conversations_controller.rb index b19f27ebf..bc8013379 100644 --- a/app/controllers/api/v1/conversations_controller.rb +++ b/app/controllers/api/v1/conversations_controller.rb @@ -9,8 +9,6 @@ class Api::V1::ConversationsController < Api::BaseController before_action :set_conversation, except: :index after_action :insert_pagination_headers, only: :index - respond_to :json - def index @conversations = paginated_conversations render json: @conversations, each_serializer: REST::ConversationSerializer diff --git a/app/controllers/api/v1/custom_emojis_controller.rb b/app/controllers/api/v1/custom_emojis_controller.rb index 4e6d5d7c6..08b3474cc 100644 --- a/app/controllers/api/v1/custom_emojis_controller.rb +++ b/app/controllers/api/v1/custom_emojis_controller.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true class Api::V1::CustomEmojisController < Api::BaseController - respond_to :json - skip_before_action :set_cache_headers def index diff --git a/app/controllers/api/v1/domain_blocks_controller.rb b/app/controllers/api/v1/domain_blocks_controller.rb index af9e7a20f..5bb02d834 100644 --- a/app/controllers/api/v1/domain_blocks_controller.rb +++ b/app/controllers/api/v1/domain_blocks_controller.rb @@ -8,8 +8,6 @@ class Api::V1::DomainBlocksController < Api::BaseController before_action :require_user! after_action :insert_pagination_headers, only: :show - respond_to :json - def show @blocks = load_domain_blocks render json: @blocks.map(&:domain) diff --git a/app/controllers/api/v1/endorsements_controller.rb b/app/controllers/api/v1/endorsements_controller.rb index 2770c7aef..c87dbc4ce 100644 --- a/app/controllers/api/v1/endorsements_controller.rb +++ b/app/controllers/api/v1/endorsements_controller.rb @@ -5,8 +5,6 @@ class Api::V1::EndorsementsController < Api::BaseController before_action :require_user! after_action :insert_pagination_headers - respond_to :json - def index @accounts = load_accounts render json: @accounts, each_serializer: REST::AccountSerializer diff --git a/app/controllers/api/v1/favourites_controller.rb b/app/controllers/api/v1/favourites_controller.rb index db827f9d4..3e242905d 100644 --- a/app/controllers/api/v1/favourites_controller.rb +++ b/app/controllers/api/v1/favourites_controller.rb @@ -5,8 +5,6 @@ class Api::V1::FavouritesController < Api::BaseController before_action :require_user! after_action :insert_pagination_headers - respond_to :json - def index @statuses = load_statuses render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id) diff --git a/app/controllers/api/v1/featured_tags/suggestions_controller.rb b/app/controllers/api/v1/featured_tags/suggestions_controller.rb index fb27ef88b..8c1b81a0f 100644 --- a/app/controllers/api/v1/featured_tags/suggestions_controller.rb +++ b/app/controllers/api/v1/featured_tags/suggestions_controller.rb @@ -2,12 +2,9 @@ class Api::V1::FeaturedTags::SuggestionsController < Api::BaseController before_action -> { doorkeeper_authorize! :read, :'read:accounts' }, only: :index - before_action :require_user! before_action :set_most_used_tags, only: :index - respond_to :json - def index render json: @most_used_tags, each_serializer: REST::TagSerializer end diff --git a/app/controllers/api/v1/filters_controller.rb b/app/controllers/api/v1/filters_controller.rb index e5ebaff4d..b0ace3af0 100644 --- a/app/controllers/api/v1/filters_controller.rb +++ b/app/controllers/api/v1/filters_controller.rb @@ -7,8 +7,6 @@ class Api::V1::FiltersController < Api::BaseController before_action :set_filters, only: :index before_action :set_filter, only: [:show, :update, :destroy] - respond_to :json - def index render json: @filters, each_serializer: REST::FilterSerializer end diff --git a/app/controllers/api/v1/instances/activity_controller.rb b/app/controllers/api/v1/instances/activity_controller.rb index b30e8464c..4f6b4bcbf 100644 --- a/app/controllers/api/v1/instances/activity_controller.rb +++ b/app/controllers/api/v1/instances/activity_controller.rb @@ -6,8 +6,6 @@ class Api::V1::Instances::ActivityController < Api::BaseController skip_before_action :set_cache_headers skip_before_action :require_authenticated_user!, unless: :whitelist_mode? - respond_to :json - def show expires_in 1.day, public: true render_with_cache json: :activity, expires_in: 1.day diff --git a/app/controllers/api/v1/instances/peers_controller.rb b/app/controllers/api/v1/instances/peers_controller.rb index cc00d8a6b..9fa440935 100644 --- a/app/controllers/api/v1/instances/peers_controller.rb +++ b/app/controllers/api/v1/instances/peers_controller.rb @@ -6,8 +6,6 @@ class Api::V1::Instances::PeersController < Api::BaseController skip_before_action :set_cache_headers skip_before_action :require_authenticated_user!, unless: :whitelist_mode? - respond_to :json - def index expires_in 1.day, public: true render_with_cache(expires_in: 1.day) { Account.remote.domains } diff --git a/app/controllers/api/v1/instances_controller.rb b/app/controllers/api/v1/instances_controller.rb index c323b60b4..5b5058a7b 100644 --- a/app/controllers/api/v1/instances_controller.rb +++ b/app/controllers/api/v1/instances_controller.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true class Api::V1::InstancesController < Api::BaseController - respond_to :json - skip_before_action :set_cache_headers skip_before_action :require_authenticated_user!, unless: :whitelist_mode? diff --git a/app/controllers/api/v1/media_controller.rb b/app/controllers/api/v1/media_controller.rb index 81825db15..d87d7b946 100644 --- a/app/controllers/api/v1/media_controller.rb +++ b/app/controllers/api/v1/media_controller.rb @@ -4,8 +4,6 @@ class Api::V1::MediaController < Api::BaseController before_action -> { doorkeeper_authorize! :write, :'write:media' } before_action :require_user! - respond_to :json - def create @media = current_account.media_attachments.create!(media_params) render json: @media, serializer: REST::MediaAttachmentSerializer diff --git a/app/controllers/api/v1/mutes_controller.rb b/app/controllers/api/v1/mutes_controller.rb index df6c8e86c..65439fe9b 100644 --- a/app/controllers/api/v1/mutes_controller.rb +++ b/app/controllers/api/v1/mutes_controller.rb @@ -5,8 +5,6 @@ class Api::V1::MutesController < Api::BaseController before_action :require_user! after_action :insert_pagination_headers - respond_to :json - def index @accounts = load_accounts render json: @accounts, each_serializer: REST::AccountSerializer diff --git a/app/controllers/api/v1/notifications_controller.rb b/app/controllers/api/v1/notifications_controller.rb index bf3002e79..8ac227765 100644 --- a/app/controllers/api/v1/notifications_controller.rb +++ b/app/controllers/api/v1/notifications_controller.rb @@ -6,8 +6,6 @@ class Api::V1::NotificationsController < Api::BaseController before_action :require_user! after_action :insert_pagination_headers, only: :index - respond_to :json - DEFAULT_NOTIFICATIONS_LIMIT = 15 def index diff --git a/app/controllers/api/v1/polls/votes_controller.rb b/app/controllers/api/v1/polls/votes_controller.rb index 3fa0b6a76..e1d26106a 100644 --- a/app/controllers/api/v1/polls/votes_controller.rb +++ b/app/controllers/api/v1/polls/votes_controller.rb @@ -7,8 +7,6 @@ class Api::V1::Polls::VotesController < Api::BaseController before_action :require_user! before_action :set_poll - respond_to :json - def create VoteService.new.call(current_account, @poll, vote_params[:choices]) render json: @poll, serializer: REST::PollSerializer diff --git a/app/controllers/api/v1/polls_controller.rb b/app/controllers/api/v1/polls_controller.rb index 031e6d42d..744baf7bb 100644 --- a/app/controllers/api/v1/polls_controller.rb +++ b/app/controllers/api/v1/polls_controller.rb @@ -7,8 +7,6 @@ class Api::V1::PollsController < Api::BaseController before_action :set_poll before_action :refresh_poll - respond_to :json - def show render json: @poll, serializer: REST::PollSerializer, include_results: true end diff --git a/app/controllers/api/v1/preferences_controller.rb b/app/controllers/api/v1/preferences_controller.rb index 077d39f5d..1640a8224 100644 --- a/app/controllers/api/v1/preferences_controller.rb +++ b/app/controllers/api/v1/preferences_controller.rb @@ -4,8 +4,6 @@ class Api::V1::PreferencesController < Api::BaseController before_action -> { doorkeeper_authorize! :read, :'read:accounts' } before_action :require_user! - respond_to :json - def index render json: current_account, serializer: REST::PreferencesSerializer end diff --git a/app/controllers/api/v1/reports_controller.rb b/app/controllers/api/v1/reports_controller.rb index 1b0b4b05b..66c40f6f4 100644 --- a/app/controllers/api/v1/reports_controller.rb +++ b/app/controllers/api/v1/reports_controller.rb @@ -4,8 +4,6 @@ class Api::V1::ReportsController < Api::BaseController before_action -> { doorkeeper_authorize! :write, :'write:reports' }, only: [:create] before_action :require_user! - respond_to :json - def create @report = ReportService.new.call( current_account, diff --git a/app/controllers/api/v1/statuses/bookmarks_controller.rb b/app/controllers/api/v1/statuses/bookmarks_controller.rb index a7f1eed00..3954af3c9 100644 --- a/app/controllers/api/v1/statuses/bookmarks_controller.rb +++ b/app/controllers/api/v1/statuses/bookmarks_controller.rb @@ -7,8 +7,6 @@ class Api::V1::Statuses::BookmarksController < Api::BaseController before_action :require_user! before_action :set_status - respond_to :json - def create current_account.bookmarks.find_or_create_by!(account: current_account, status: @status) render json: @status, serializer: REST::StatusSerializer diff --git a/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb b/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb index 05f4acc33..8229786d6 100644 --- a/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb +++ b/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb @@ -7,8 +7,6 @@ class Api::V1::Statuses::FavouritedByAccountsController < Api::BaseController before_action :set_status after_action :insert_pagination_headers - respond_to :json - def index @accounts = load_accounts render json: @accounts, each_serializer: REST::AccountSerializer diff --git a/app/controllers/api/v1/statuses/favourites_controller.rb b/app/controllers/api/v1/statuses/favourites_controller.rb index f18ace996..7afa822ed 100644 --- a/app/controllers/api/v1/statuses/favourites_controller.rb +++ b/app/controllers/api/v1/statuses/favourites_controller.rb @@ -7,8 +7,6 @@ class Api::V1::Statuses::FavouritesController < Api::BaseController before_action :require_user! before_action :set_status - respond_to :json - def create FavouriteService.new.call(current_account, @status) render json: @status, serializer: REST::StatusSerializer diff --git a/app/controllers/api/v1/statuses/mutes_controller.rb b/app/controllers/api/v1/statuses/mutes_controller.rb index b02469b4f..43c7a525a 100644 --- a/app/controllers/api/v1/statuses/mutes_controller.rb +++ b/app/controllers/api/v1/statuses/mutes_controller.rb @@ -8,8 +8,6 @@ class Api::V1::Statuses::MutesController < Api::BaseController before_action :set_status before_action :set_conversation - respond_to :json - def create current_account.mute_conversation!(@conversation) @mutes_map = { @conversation.id => true } diff --git a/app/controllers/api/v1/statuses/pins_controller.rb b/app/controllers/api/v1/statuses/pins_controller.rb index 4118a8ce4..51b1621b6 100644 --- a/app/controllers/api/v1/statuses/pins_controller.rb +++ b/app/controllers/api/v1/statuses/pins_controller.rb @@ -7,8 +7,6 @@ class Api::V1::Statuses::PinsController < Api::BaseController before_action :require_user! before_action :set_status - respond_to :json - def create StatusPin.create!(account: current_account, status: @status) distribute_add_activity! diff --git a/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb b/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb index fa60e7d84..6c9e49d90 100644 --- a/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb +++ b/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb @@ -7,8 +7,6 @@ class Api::V1::Statuses::RebloggedByAccountsController < Api::BaseController before_action :set_status after_action :insert_pagination_headers - respond_to :json - def index @accounts = load_accounts render json: @accounts, each_serializer: REST::AccountSerializer diff --git a/app/controllers/api/v1/statuses/reblogs_controller.rb b/app/controllers/api/v1/statuses/reblogs_controller.rb index 67106ccbe..9abeb0759 100644 --- a/app/controllers/api/v1/statuses/reblogs_controller.rb +++ b/app/controllers/api/v1/statuses/reblogs_controller.rb @@ -7,8 +7,6 @@ class Api::V1::Statuses::ReblogsController < Api::BaseController before_action :require_user! before_action :set_reblog - respond_to :json - def create @status = ReblogService.new.call(current_account, @reblog, reblog_params) render json: @status, serializer: REST::StatusSerializer diff --git a/app/controllers/api/v1/statuses_controller.rb b/app/controllers/api/v1/statuses_controller.rb index bba3c0651..85521fadf 100644 --- a/app/controllers/api/v1/statuses_controller.rb +++ b/app/controllers/api/v1/statuses_controller.rb @@ -8,8 +8,6 @@ class Api::V1::StatusesController < Api::BaseController before_action :require_user!, except: [:show, :context] before_action :set_status, only: [:show, :context] - respond_to :json - # This API was originally unlimited, pagination cannot be introduced without # breaking backwards-compatibility. Arbitrarily high number to cover most # conversations as quasi-unlimited, it would be too much work to render more diff --git a/app/controllers/api/v1/streaming_controller.rb b/app/controllers/api/v1/streaming_controller.rb index ebb17608c..7cd60615a 100644 --- a/app/controllers/api/v1/streaming_controller.rb +++ b/app/controllers/api/v1/streaming_controller.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true class Api::V1::StreamingController < Api::BaseController - respond_to :json - def index if Rails.configuration.x.streaming_api_base_url != request.host redirect_to streaming_api_url, status: 301 diff --git a/app/controllers/api/v1/suggestions_controller.rb b/app/controllers/api/v1/suggestions_controller.rb index 9da2b60ae..52054160d 100644 --- a/app/controllers/api/v1/suggestions_controller.rb +++ b/app/controllers/api/v1/suggestions_controller.rb @@ -7,8 +7,6 @@ class Api::V1::SuggestionsController < Api::BaseController before_action :require_user! before_action :set_accounts - respond_to :json - def index render json: @accounts, each_serializer: REST::AccountSerializer end diff --git a/app/controllers/api/v1/timelines/home_controller.rb b/app/controllers/api/v1/timelines/home_controller.rb index ff5ede138..ae6dbcb8b 100644 --- a/app/controllers/api/v1/timelines/home_controller.rb +++ b/app/controllers/api/v1/timelines/home_controller.rb @@ -5,8 +5,6 @@ class Api::V1::Timelines::HomeController < Api::BaseController before_action :require_user!, only: [:show] after_action :insert_pagination_headers, unless: -> { @statuses.empty? } - respond_to :json - def show @statuses = load_statuses diff --git a/app/controllers/api/v1/timelines/public_controller.rb b/app/controllers/api/v1/timelines/public_controller.rb index ccc10f966..581befef1 100644 --- a/app/controllers/api/v1/timelines/public_controller.rb +++ b/app/controllers/api/v1/timelines/public_controller.rb @@ -4,8 +4,6 @@ class Api::V1::Timelines::PublicController < Api::BaseController before_action :require_user!, only: [:show], if: :require_auth? after_action :insert_pagination_headers, unless: -> { @statuses.empty? } - respond_to :json - def show @statuses = load_statuses render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id) diff --git a/app/controllers/api/v1/timelines/tag_controller.rb b/app/controllers/api/v1/timelines/tag_controller.rb index 9adc4ad29..2d6ad5a80 100644 --- a/app/controllers/api/v1/timelines/tag_controller.rb +++ b/app/controllers/api/v1/timelines/tag_controller.rb @@ -4,8 +4,6 @@ class Api::V1::Timelines::TagController < Api::BaseController before_action :load_tag after_action :insert_pagination_headers, unless: -> { @statuses.empty? } - respond_to :json - def show @statuses = load_statuses render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id) diff --git a/app/controllers/api/v1/trends_controller.rb b/app/controllers/api/v1/trends_controller.rb index bcea9857e..c875e9041 100644 --- a/app/controllers/api/v1/trends_controller.rb +++ b/app/controllers/api/v1/trends_controller.rb @@ -3,8 +3,6 @@ class Api::V1::TrendsController < Api::BaseController before_action :set_tags - respond_to :json - def index render json: @tags, each_serializer: REST::TagSerializer end diff --git a/app/controllers/api/v2/search_controller.rb b/app/controllers/api/v2/search_controller.rb index cbd9b551d..f17431dd1 100644 --- a/app/controllers/api/v2/search_controller.rb +++ b/app/controllers/api/v2/search_controller.rb @@ -8,8 +8,6 @@ class Api::V2::SearchController < Api::BaseController before_action -> { doorkeeper_authorize! :read, :'read:search' } before_action :require_user! - respond_to :json - def index @search = Search.new(search_results) render json: @search, serializer: REST::SearchSerializer diff --git a/app/controllers/api/web/embeds_controller.rb b/app/controllers/api/web/embeds_controller.rb index 4aa31695c..741ba910f 100644 --- a/app/controllers/api/web/embeds_controller.rb +++ b/app/controllers/api/web/embeds_controller.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true class Api::Web::EmbedsController < Api::Web::BaseController - respond_to :json - before_action :require_user! def create diff --git a/app/controllers/api/web/push_subscriptions_controller.rb b/app/controllers/api/web/push_subscriptions_controller.rb index f388b17e5..7916b82fa 100644 --- a/app/controllers/api/web/push_subscriptions_controller.rb +++ b/app/controllers/api/web/push_subscriptions_controller.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true class Api::Web::PushSubscriptionsController < Api::Web::BaseController - respond_to :json - before_action :require_user! def create diff --git a/app/controllers/api/web/settings_controller.rb b/app/controllers/api/web/settings_controller.rb index e3178bf48..3d65e46ed 100644 --- a/app/controllers/api/web/settings_controller.rb +++ b/app/controllers/api/web/settings_controller.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true class Api::Web::SettingsController < Api::Web::BaseController - respond_to :json - before_action :require_user! def update From e69a3f54a10e58d32d7e46c494d98be948dde4b3 Mon Sep 17 00:00:00 2001 From: koyu Date: Fri, 6 Mar 2020 05:31:51 +0100 Subject: [PATCH 12/29] Change GIF label to be displayed even when autoplay is enabled in web UI (#13209) --- 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 653ad8188..1be93dfea 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -5058,12 +5058,6 @@ a.status-card.compact:hover { } .media-gallery__gifv { - &.autoplay { - .media-gallery__gifv__label { - display: none; - } - } - &:hover { .media-gallery__gifv__label { opacity: 1; From 503eab1c1f101e92f163ed4f8457cac9a6193ffc Mon Sep 17 00:00:00 2001 From: ThibG Date: Fri, 6 Mar 2020 15:20:14 +0100 Subject: [PATCH 13/29] Fix too large announcements not being scrollable in web UI (#13211) --- app/javascript/styles/mastodon/components.scss | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 1be93dfea..456929f3a 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -870,6 +870,7 @@ .announcements__item__content { word-wrap: break-word; + overflow-y: auto; .emojione { width: 20px; @@ -6676,17 +6677,21 @@ noscript { box-sizing: border-box; width: 100%; padding: 15px; - padding-right: 15px + 18px; position: relative; font-size: 15px; line-height: 20px; word-wrap: break-word; font-weight: 400; + max-height: 50vh; + overflow: hidden; + display: flex; + flex-direction: column; &__range { display: block; font-weight: 500; margin-bottom: 10px; + padding-right: 18px; } &__unread { From 339ce1c4e90605b736745b1f04493a247b2627ec Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sun, 8 Mar 2020 15:17:39 +0100 Subject: [PATCH 14/29] Add specific rate limits for posting and following (#13172) --- app/controllers/account_follow_controller.rb | 2 +- app/controllers/api/base_controller.rb | 4 + app/controllers/api/v1/accounts_controller.rb | 4 +- .../api/v1/statuses/reblogs_controller.rb | 3 + app/controllers/api/v1/statuses_controller.rb | 5 +- app/controllers/application_controller.rb | 5 ++ .../authorize_interactions_controller.rb | 2 +- .../concerns/rate_limit_headers.rb | 16 +++- app/lib/exceptions.rb | 1 + app/lib/rate_limiter.rb | 64 ++++++++++++++++ app/models/concerns/account_interactions.rb | 16 +++- app/models/concerns/rate_limitable.rb | 36 +++++++++ app/models/follow.rb | 3 + app/models/follow_request.rb | 3 + app/models/status.rb | 3 + app/services/follow_service.rb | 74 +++++++++++-------- app/services/post_status_service.rb | 11 ++- app/services/reblog_service.rb | 16 +++- app/views/errors/429.html.haml | 5 ++ config/initializers/rack_attack.rb | 1 - config/locales/en.yml | 2 +- .../account_follow_controller_spec.rb | 2 +- .../api/v1/statuses_controller_spec.rb | 46 +++++++++++- 23 files changed, 273 insertions(+), 51 deletions(-) create mode 100644 app/lib/rate_limiter.rb create mode 100644 app/models/concerns/rate_limitable.rb create mode 100644 app/views/errors/429.html.haml diff --git a/app/controllers/account_follow_controller.rb b/app/controllers/account_follow_controller.rb index 185a355f8..33394074d 100644 --- a/app/controllers/account_follow_controller.rb +++ b/app/controllers/account_follow_controller.rb @@ -6,7 +6,7 @@ class AccountFollowController < ApplicationController before_action :authenticate_user! def create - FollowService.new.call(current_user.account, @account.acct) + FollowService.new.call(current_user.account, @account, with_rate_limit: true) redirect_to account_path(@account) end end diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb index 68bf425f4..153ade253 100644 --- a/app/controllers/api/base_controller.rb +++ b/app/controllers/api/base_controller.rb @@ -44,6 +44,10 @@ class Api::BaseController < ApplicationController render json: { error: 'There was a temporary problem serving your request, please try again' }, status: 503 end + rescue_from Mastodon::RateLimitExceededError do + render json: { error: I18n.t('errors.429') }, status: 429 + end + rescue_from ActionController::ParameterMissing do |e| render json: { error: e.to_s }, status: 400 end diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb index f5b06862b..0080faf33 100644 --- a/app/controllers/api/v1/accounts_controller.rb +++ b/app/controllers/api/v1/accounts_controller.rb @@ -14,6 +14,8 @@ class Api::V1::AccountsController < Api::BaseController skip_before_action :require_authenticated_user!, only: :create + override_rate_limit_headers :follow, family: :follows + def show render json: @account, serializer: REST::AccountSerializer end @@ -29,7 +31,7 @@ class Api::V1::AccountsController < Api::BaseController end def follow - FollowService.new.call(current_user.account, @account, reblogs: truthy_param?(:reblogs)) + FollowService.new.call(current_user.account, @account, reblogs: truthy_param?(:reblogs), with_rate_limit: true) options = @account.locked? || current_user.account.silenced? ? {} : { following_map: { @account.id => { reblogs: truthy_param?(:reblogs) } }, requested_map: { @account.id => false } } diff --git a/app/controllers/api/v1/statuses/reblogs_controller.rb b/app/controllers/api/v1/statuses/reblogs_controller.rb index 9abeb0759..7fa774a4d 100644 --- a/app/controllers/api/v1/statuses/reblogs_controller.rb +++ b/app/controllers/api/v1/statuses/reblogs_controller.rb @@ -7,8 +7,11 @@ class Api::V1::Statuses::ReblogsController < Api::BaseController before_action :require_user! before_action :set_reblog + override_rate_limit_headers :create, family: :statuses + def create @status = ReblogService.new.call(current_account, @reblog, reblog_params) + render json: @status, serializer: REST::StatusSerializer end diff --git a/app/controllers/api/v1/statuses_controller.rb b/app/controllers/api/v1/statuses_controller.rb index 85521fadf..2f55e95fd 100644 --- a/app/controllers/api/v1/statuses_controller.rb +++ b/app/controllers/api/v1/statuses_controller.rb @@ -8,6 +8,8 @@ class Api::V1::StatusesController < Api::BaseController before_action :require_user!, except: [:show, :context] before_action :set_status, only: [:show, :context] + override_rate_limit_headers :create, family: :statuses + # This API was originally unlimited, pagination cannot be introduced without # breaking backwards-compatibility. Arbitrarily high number to cover most # conversations as quasi-unlimited, it would be too much work to render more @@ -42,7 +44,8 @@ class Api::V1::StatusesController < Api::BaseController scheduled_at: status_params[:scheduled_at], application: doorkeeper_token.application, poll: status_params[:poll], - idempotency: request.headers['Idempotency-Key']) + idempotency: request.headers['Idempotency-Key'], + with_rate_limit: true) render json: @status, serializer: @status.is_a?(ScheduledStatus) ? REST::ScheduledStatusSerializer : REST::StatusSerializer end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 0cfa2b386..973db6aca 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -29,6 +29,7 @@ class ApplicationController < ActionController::Base rescue_from Mastodon::NotPermittedError, with: :forbidden rescue_from HTTP::Error, OpenSSL::SSL::SSLError, with: :internal_server_error rescue_from Mastodon::RaceConditionError, with: :service_unavailable + rescue_from Mastodon::RateLimitExceededError, with: :too_many_requests before_action :store_current_location, except: :raise_not_found, unless: :devise_controller? before_action :require_functional!, if: :user_signed_in? @@ -111,6 +112,10 @@ class ApplicationController < ActionController::Base respond_with_error(503) end + def too_many_requests + respond_with_error(429) + end + def single_user_mode? @single_user_mode ||= Rails.configuration.x.single_user_mode && Account.where('id > 0').exists? end diff --git a/app/controllers/authorize_interactions_controller.rb b/app/controllers/authorize_interactions_controller.rb index e27366ea3..29c0288d0 100644 --- a/app/controllers/authorize_interactions_controller.rb +++ b/app/controllers/authorize_interactions_controller.rb @@ -20,7 +20,7 @@ class AuthorizeInteractionsController < ApplicationController end def create - if @resource.is_a?(Account) && FollowService.new.call(current_account, @resource) + if @resource.is_a?(Account) && FollowService.new.call(current_account, @resource, with_rate_limit: true) render :success else render :error diff --git a/app/controllers/concerns/rate_limit_headers.rb b/app/controllers/concerns/rate_limit_headers.rb index b79c558d8..86fe58a71 100644 --- a/app/controllers/concerns/rate_limit_headers.rb +++ b/app/controllers/concerns/rate_limit_headers.rb @@ -3,6 +3,20 @@ module RateLimitHeaders extend ActiveSupport::Concern + class_methods do + def override_rate_limit_headers(method_name, options = {}) + around_action(only: method_name, if: :current_account) do |_controller, block| + begin + block.call + ensure + rate_limiter = RateLimiter.new(current_account, options) + rate_limit_headers = rate_limiter.to_headers + response.headers.merge!(rate_limit_headers) unless response.headers['X-RateLimit-Remaining'].present? && rate_limit_headers['X-RateLimit-Remaining'].to_i > response.headers['X-RateLimit-Remaining'].to_i + end + end + end + end + included do before_action :set_rate_limit_headers, if: :rate_limited_request? end @@ -44,7 +58,7 @@ module RateLimitHeaders end def api_throttle_data - most_limited_type, = request.env['rack.attack.throttle_data'].min_by { |_, v| v[:limit] } + most_limited_type, = request.env['rack.attack.throttle_data'].min_by { |_, v| v[:limit] - v[:count] } request.env['rack.attack.throttle_data'][most_limited_type] end diff --git a/app/lib/exceptions.rb b/app/lib/exceptions.rb index 01346bfe5..3362576b0 100644 --- a/app/lib/exceptions.rb +++ b/app/lib/exceptions.rb @@ -8,6 +8,7 @@ module Mastodon class LengthValidationError < ValidationError; end class DimensionsValidationError < ValidationError; end class RaceConditionError < Error; end + class RateLimitExceededError < Error; end class UnexpectedResponseError < Error def initialize(response = nil) diff --git a/app/lib/rate_limiter.rb b/app/lib/rate_limiter.rb new file mode 100644 index 000000000..68dae9add --- /dev/null +++ b/app/lib/rate_limiter.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +class RateLimiter + include Redisable + + FAMILIES = { + follows: { + limit: 400, + period: 24.hours.freeze, + }.freeze, + + statuses: { + limit: 300, + period: 3.hours.freeze, + }.freeze, + + media: { + limit: 30, + period: 30.minutes.freeze, + }.freeze, + }.freeze + + def initialize(by, options = {}) + @by = by + @family = options[:family] + @limit = FAMILIES[@family][:limit] + @period = FAMILIES[@family][:period].to_i + end + + def record! + count = redis.get(key) + + if count.nil? + redis.set(key, 0) + redis.expire(key, (@period - (last_epoch_time % @period) + 1).to_i) + end + + raise Mastodon::RateLimitExceededError if count.present? && count.to_i >= @limit + + redis.incr(key) + end + + def rollback! + redis.decr(key) + end + + def to_headers(now = Time.now.utc) + { + 'X-RateLimit-Limit' => @limit.to_s, + 'X-RateLimit-Remaining' => (@limit - (redis.get(key) || 0).to_i).to_s, + 'X-RateLimit-Reset' => (now + (@period - now.to_i % @period)).iso8601(6), + } + end + + private + + def key + @key ||= "rate_limit:#{@by.id}:#{@family}:#{(last_epoch_time / @period).to_i}" + end + + def last_epoch_time + @last_epoch_time ||= Time.now.to_i + end +end diff --git a/app/models/concerns/account_interactions.rb b/app/models/concerns/account_interactions.rb index 14bcf7bb1..32fcb5397 100644 --- a/app/models/concerns/account_interactions.rb +++ b/app/models/concerns/account_interactions.rb @@ -87,10 +87,10 @@ module AccountInteractions has_many :announcement_mutes, dependent: :destroy end - def follow!(other_account, reblogs: nil, uri: nil) + def follow!(other_account, reblogs: nil, uri: nil, rate_limit: false) reblogs = true if reblogs.nil? - rel = active_relationships.create_with(show_reblogs: reblogs, uri: uri) + rel = active_relationships.create_with(show_reblogs: reblogs, uri: uri, rate_limit: rate_limit) .find_or_create_by!(target_account: other_account) rel.update!(show_reblogs: reblogs) @@ -99,6 +99,18 @@ module AccountInteractions rel end + def request_follow!(other_account, reblogs: nil, uri: nil, rate_limit: false) + reblogs = true if reblogs.nil? + + rel = follow_requests.create_with(show_reblogs: reblogs, uri: uri, rate_limit: rate_limit) + .find_or_create_by!(target_account: other_account) + + rel.update!(show_reblogs: reblogs) + remove_potential_friendship(other_account) + + rel + end + def block!(other_account, uri: nil) remove_potential_friendship(other_account) block_relationships.create_with(uri: uri) diff --git a/app/models/concerns/rate_limitable.rb b/app/models/concerns/rate_limitable.rb new file mode 100644 index 000000000..ad1b5e44e --- /dev/null +++ b/app/models/concerns/rate_limitable.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +module RateLimitable + extend ActiveSupport::Concern + + def rate_limit=(value) + @rate_limit = value + end + + def rate_limit? + @rate_limit + end + + def rate_limiter(by, options = {}) + return @rate_limiter if defined?(@rate_limiter) + + @rate_limiter = RateLimiter.new(by, options) + end + + class_methods do + def rate_limit(options = {}) + after_create do + by = public_send(options[:by]) + + if rate_limit? && by&.local? + rate_limiter(by, options).record! + @rate_limit_recorded = true + end + end + + after_rollback do + rate_limiter(public_send(options[:by]), options).rollback! if @rate_limit_recorded + end + end + end +end diff --git a/app/models/follow.rb b/app/models/follow.rb index 87fa11425..f3e48a2ed 100644 --- a/app/models/follow.rb +++ b/app/models/follow.rb @@ -15,6 +15,9 @@ class Follow < ApplicationRecord include Paginable include RelationshipCacheable + include RateLimitable + + rate_limit by: :account, family: :follows belongs_to :account belongs_to :target_account, class_name: 'Account' diff --git a/app/models/follow_request.rb b/app/models/follow_request.rb index 96ac7eaa5..3325e264c 100644 --- a/app/models/follow_request.rb +++ b/app/models/follow_request.rb @@ -15,6 +15,9 @@ class FollowRequest < ApplicationRecord include Paginable include RelationshipCacheable + include RateLimitable + + rate_limit by: :account, family: :follows belongs_to :account belongs_to :target_account, class_name: 'Account' diff --git a/app/models/status.rb b/app/models/status.rb index 1e630196b..1610da245 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -32,6 +32,9 @@ class Status < ApplicationRecord include Paginable include Cacheable include StatusThreadingConcern + include RateLimitable + + rate_limit by: :account, family: :statuses self.discard_column = :deleted_at diff --git a/app/services/follow_service.rb b/app/services/follow_service.rb index 4d19002c4..311ae7fa6 100644 --- a/app/services/follow_service.rb +++ b/app/services/follow_service.rb @@ -7,54 +7,68 @@ class FollowService < BaseService # Follow a remote user, notify remote user about the follow # @param [Account] source_account From which to follow # @param [String, Account] uri User URI to follow in the form of username@domain (or account record) - # @param [true, false, nil] reblogs Whether or not to show reblogs, defaults to true - def call(source_account, target_account, reblogs: nil, bypass_locked: false) - reblogs = true if reblogs.nil? - target_account = ResolveAccountService.new.call(target_account, skip_webfinger: true) + # @param [Hash] options + # @option [Boolean] :reblogs Whether or not to show reblogs, defaults to true + # @option [Boolean] :bypass_locked + # @option [Boolean] :with_rate_limit + def call(source_account, target_account, options = {}) + @source_account = source_account + @target_account = ResolveAccountService.new.call(target_account, skip_webfinger: true) + @options = { reblogs: true, bypass_locked: false, with_rate_limit: false }.merge(options) - raise ActiveRecord::RecordNotFound if target_account.nil? || target_account.id == source_account.id || target_account.suspended? - raise Mastodon::NotPermittedError if target_account.blocking?(source_account) || source_account.blocking?(target_account) || target_account.moved? || (!target_account.local? && target_account.ostatus?) || source_account.domain_blocking?(target_account.domain) + raise ActiveRecord::RecordNotFound if following_not_possible? + raise Mastodon::NotPermittedError if following_not_allowed? - if source_account.following?(target_account) - # We're already following this account, but we'll call follow! again to - # make sure the reblogs status is set correctly. - return source_account.follow!(target_account, reblogs: reblogs) - elsif source_account.requested?(target_account) - # This isn't managed by a method in AccountInteractions, so we modify it - # ourselves if necessary. - req = source_account.follow_requests.find_by(target_account: target_account) - req.update!(show_reblogs: reblogs) - return req + if @source_account.following?(@target_account) + return change_follow_options! + elsif @source_account.requested?(@target_account) + return change_follow_request_options! end ActivityTracker.increment('activity:interactions') - if (target_account.locked? && !bypass_locked) || source_account.silenced? || target_account.activitypub? - request_follow(source_account, target_account, reblogs: reblogs) - elsif target_account.local? - direct_follow(source_account, target_account, reblogs: reblogs) + if (@target_account.locked? && !@options[:bypass_locked]) || @source_account.silenced? || @target_account.activitypub? + request_follow! + elsif @target_account.local? + direct_follow! end end private - def request_follow(source_account, target_account, reblogs: true) - follow_request = FollowRequest.create!(account: source_account, target_account: target_account, show_reblogs: reblogs) + def following_not_possible? + @target_account.nil? || @target_account.id == @source_account.id || @target_account.suspended? + end - if target_account.local? - LocalNotificationWorker.perform_async(target_account.id, follow_request.id, follow_request.class.name) - elsif target_account.activitypub? - ActivityPub::DeliveryWorker.perform_async(build_json(follow_request), source_account.id, target_account.inbox_url) + def following_not_allowed? + @target_account.blocking?(@source_account) || @source_account.blocking?(@target_account) || @target_account.moved? || (!@target_account.local? && @target_account.ostatus?) || @source_account.domain_blocking?(@target_account.domain) + end + + def change_follow_options! + @source_account.follow!(@target_account, reblogs: @options[:reblogs]) + end + + def change_follow_request_options! + @source_account.request_follow!(@target_account, reblogs: @options[:reblogs]) + end + + def request_follow! + follow_request = @source_account.request_follow!(@target_account, reblogs: @options[:reblogs], rate_limit: @options[:with_rate_limit]) + + if @target_account.local? + LocalNotificationWorker.perform_async(@target_account.id, follow_request.id, follow_request.class.name) + elsif @target_account.activitypub? + ActivityPub::DeliveryWorker.perform_async(build_json(follow_request), @source_account.id, @target_account.inbox_url) end follow_request end - def direct_follow(source_account, target_account, reblogs: true) - follow = source_account.follow!(target_account, reblogs: reblogs) + def direct_follow! + follow = @source_account.follow!(@target_account, reblogs: @options[:reblogs], rate_limit: @options[:with_rate_limit]) - LocalNotificationWorker.perform_async(target_account.id, follow.id, follow.class.name) - MergeWorker.perform_async(target_account.id, source_account.id) + LocalNotificationWorker.perform_async(@target_account.id, follow.id, follow.class.name) + MergeWorker.perform_async(@target_account.id, @source_account.id) follow end diff --git a/app/services/post_status_service.rb b/app/services/post_status_service.rb index a0a650d62..1bbd625b4 100644 --- a/app/services/post_status_service.rb +++ b/app/services/post_status_service.rb @@ -19,6 +19,7 @@ class PostStatusService < BaseService # @option [Enumerable] :media_ids Optional array of media IDs to attach # @option [Doorkeeper::Application] :application # @option [String] :idempotency Optional idempotency key + # @option [Boolean] :with_rate_limit # @return [Status] def call(account, options = {}) @account = account @@ -160,6 +161,7 @@ class PostStatusService < BaseService visibility: @visibility, language: language_from_option(@options[:language]) || @account.user&.setting_default_language&.presence || LanguageDetector.instance.detect(@text, @account), application: @options[:application], + rate_limit: @options[:with_rate_limit], }.compact end @@ -179,10 +181,11 @@ class PostStatusService < BaseService def scheduled_options @options.tap do |options_hash| - options_hash[:in_reply_to_id] = options_hash.delete(:thread)&.id - options_hash[:application_id] = options_hash.delete(:application)&.id - options_hash[:scheduled_at] = nil - options_hash[:idempotency] = nil + options_hash[:in_reply_to_id] = options_hash.delete(:thread)&.id + options_hash[:application_id] = options_hash.delete(:application)&.id + options_hash[:scheduled_at] = nil + options_hash[:idempotency] = nil + options_hash[:with_rate_limit] = false end end end diff --git a/app/services/reblog_service.rb b/app/services/reblog_service.rb index 3bb460fca..4b5ae9492 100644 --- a/app/services/reblog_service.rb +++ b/app/services/reblog_service.rb @@ -8,6 +8,8 @@ class ReblogService < BaseService # @param [Account] account Account to reblog from # @param [Status] reblogged_status Status to be reblogged # @param [Hash] options + # @option [String] :visibility + # @option [Boolean] :with_rate_limit # @return [Status] def call(account, reblogged_status, options = {}) reblogged_status = reblogged_status.reblog if reblogged_status.reblog? @@ -18,9 +20,15 @@ class ReblogService < BaseService return reblog unless reblog.nil? - visibility = options[:visibility] || account.user&.setting_default_privacy - visibility = reblogged_status.visibility if reblogged_status.hidden? - reblog = account.statuses.create!(reblog: reblogged_status, text: '', visibility: visibility) + visibility = begin + if reblogged_status.hidden? + reblogged_status.visibility + else + options[:visibility] || account.user&.setting_default_privacy + end + end + + reblog = account.statuses.create!(reblog: reblogged_status, text: '', visibility: visibility, rate_limit: options[:with_rate_limit]) DistributionWorker.perform_async(reblog.id) ActivityPub::DistributionWorker.perform_async(reblog.id) @@ -45,7 +53,9 @@ class ReblogService < BaseService def bump_potential_friendship(account, reblog) ActivityTracker.increment('activity:interactions') + return if account.following?(reblog.reblog.account_id) + PotentialFriendshipTracker.record(account.id, reblog.reblog.account_id, :reblog) end diff --git a/app/views/errors/429.html.haml b/app/views/errors/429.html.haml new file mode 100644 index 000000000..2df4f4175 --- /dev/null +++ b/app/views/errors/429.html.haml @@ -0,0 +1,5 @@ +- content_for :page_title do + = t('errors.429') + +- content_for :content do + = t('errors.429') diff --git a/config/initializers/rack_attack.rb b/config/initializers/rack_attack.rb index 3cd7ea3a6..8bc1104d4 100644 --- a/config/initializers/rack_attack.rb +++ b/config/initializers/rack_attack.rb @@ -70,7 +70,6 @@ class Rack::Attack req.remote_ip if req.post? && req.path == '/api/v1/accounts' end - # Throttle paging, as it is mainly used for public pages and AP collections throttle('throttle_authenticated_paging', limit: 300, period: 15.minutes) do |req| req.authenticated_user_id if req.paging_request? end diff --git a/config/locales/en.yml b/config/locales/en.yml index 1d2580101..99a80431a 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -725,7 +725,7 @@ en: '422': content: Security verification failed. Are you blocking cookies? title: Security verification failed - '429': Throttled + '429': Too many requests '500': content: We're sorry, but something went wrong on our end. title: This page is not correct diff --git a/spec/controllers/account_follow_controller_spec.rb b/spec/controllers/account_follow_controller_spec.rb index ac15499be..9a93e1ebe 100644 --- a/spec/controllers/account_follow_controller_spec.rb +++ b/spec/controllers/account_follow_controller_spec.rb @@ -25,7 +25,7 @@ describe AccountFollowController do sign_in(user) subject - expect(service).to have_received(:call).with(user.account, 'alice') + expect(service).to have_received(:call).with(user.account, alice, with_rate_limit: true) expect(response).to redirect_to(account_path(alice)) end end diff --git a/spec/controllers/api/v1/statuses_controller_spec.rb b/spec/controllers/api/v1/statuses_controller_spec.rb index 9ff5fcd3b..df8037038 100644 --- a/spec/controllers/api/v1/statuses_controller_spec.rb +++ b/spec/controllers/api/v1/statuses_controller_spec.rb @@ -39,12 +39,50 @@ RSpec.describe Api::V1::StatusesController, type: :controller do describe 'POST #create' do let(:scopes) { 'write:statuses' } - before do - post :create, params: { status: 'Hello world' } + context do + before do + post :create, params: { status: 'Hello world' } + end + + it 'returns http success' do + expect(response).to have_http_status(200) + end + + it 'returns rate limit headers' do + expect(response.headers['X-RateLimit-Limit']).to eq RateLimiter::FAMILIES[:statuses][:limit].to_s + expect(response.headers['X-RateLimit-Remaining']).to eq (RateLimiter::FAMILIES[:statuses][:limit] - 1).to_s + end end - it 'returns http success' do - expect(response).to have_http_status(200) + context 'with missing parameters' do + before do + post :create, params: {} + end + + it 'returns http unprocessable entity' do + expect(response).to have_http_status(422) + end + + it 'returns rate limit headers' do + expect(response.headers['X-RateLimit-Limit']).to eq RateLimiter::FAMILIES[:statuses][:limit].to_s + end + end + + context 'when exceeding rate limit' do + before do + rate_limiter = RateLimiter.new(user.account, family: :statuses) + 300.times { rate_limiter.record! } + post :create, params: { status: 'Hello world' } + end + + it 'returns http too many requests' do + expect(response).to have_http_status(429) + end + + it 'returns rate limit headers' do + expect(response.headers['X-RateLimit-Limit']).to eq RateLimiter::FAMILIES[:statuses][:limit].to_s + expect(response.headers['X-RateLimit-Remaining']).to eq '0' + end end end From 2e18b1a2a2976f04f84e92d187b0620223a64fa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9lanie=20Chauvel=20=28ariasuni=29?= Date: Sun, 8 Mar 2020 15:36:50 +0100 Subject: [PATCH 15/29] Fix text area above/right of emoji picker being accidentally clickable in web UI (#13148) --- app/javascript/styles/mastodon/components.scss | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 456929f3a..7d3644d16 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -388,8 +388,8 @@ .emoji-picker-dropdown { position: absolute; - top: 5px; - right: 5px; + top: 0; + right: 0; } .compose-form__autosuggest-wrapper { @@ -4061,10 +4061,7 @@ a.status-card.compact:hover { .emoji-button { display: block; - font-size: 24px; - line-height: 24px; - margin-left: 2px; - width: 24px; + padding: 5px 5px 2px 2px; outline: 0; cursor: pointer; @@ -4080,7 +4077,6 @@ a.status-card.compact:hover { margin: 0; width: 22px; height: 22px; - margin-top: 2px; } &:hover, From 4a4cd686c1d556e7b5246ddc309085243b4a051b Mon Sep 17 00:00:00 2001 From: ThibG Date: Sun, 8 Mar 2020 15:39:13 +0100 Subject: [PATCH 16/29] Add sorting by username, creation and last activity in moderation view (#13076) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add ability to order accounts in moderation view * Display last status date in “Most recent activity” for remote users --- app/models/account.rb | 1 + app/models/account_filter.rb | 27 +++++++++++++++++---- app/views/admin/accounts/_account.html.haml | 2 ++ app/views/admin/accounts/index.html.haml | 6 +++++ 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/app/models/account.rb b/app/models/account.rb index 778429b0d..a1b4a065b 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -102,6 +102,7 @@ class Account < ApplicationRecord scope :discoverable, -> { searchable.without_silenced.where(discoverable: true).left_outer_joins(:account_stat) } scope :tagged_with, ->(tag) { joins(:accounts_tags).where(accounts_tags: { tag_id: tag }) } scope :by_recent_status, -> { order(Arel.sql('(case when account_stats.last_status_at is null then 1 else 0 end) asc, account_stats.last_status_at desc, accounts.id desc')) } + scope :by_recent_sign_in, -> { order(Arel.sql('(case when users.current_sign_in_at is null then 1 else 0 end) asc, users.current_sign_in_at desc, accounts.id desc')) } scope :popular, -> { order('account_stats.followers_count desc') } scope :by_domain_and_subdomains, ->(domain) { where(domain: domain).or(where(arel_table[:domain].matches('%.' + domain))) } scope :not_excluded_by_account, ->(account) { where.not(id: account.excluded_from_timeline_account_ids) } diff --git a/app/models/account_filter.rb b/app/models/account_filter.rb index c7bf07787..7b6012e0f 100644 --- a/app/models/account_filter.rb +++ b/app/models/account_filter.rb @@ -14,6 +14,7 @@ class AccountFilter email ip staff + order ).freeze attr_reader :params @@ -24,7 +25,7 @@ class AccountFilter end def results - scope = Account.recent.includes(:user) + scope = Account.includes(:user).reorder(nil) params.each do |key, value| scope.merge!(scope_for(key, value.to_s.strip)) if value.present? @@ -38,6 +39,7 @@ class AccountFilter def set_defaults! params['local'] = '1' if params['remote'].blank? params['active'] = '1' if params['suspended'].blank? && params['silenced'].blank? && params['pending'].blank? + params['order'] = 'recent' if params['order'].blank? end def scope_for(key, value) @@ -51,9 +53,9 @@ class AccountFilter when 'active' Account.without_suspended when 'pending' - accounts_with_users.merge User.pending + accounts_with_users.merge(User.pending) when 'disabled' - accounts_with_users.merge User.disabled + accounts_with_users.merge(User.disabled) when 'silenced' Account.silenced when 'suspended' @@ -63,16 +65,31 @@ class AccountFilter when 'display_name' Account.matches_display_name(value) when 'email' - accounts_with_users.merge User.matches_email(value) + accounts_with_users.merge(User.matches_email(value)) when 'ip' valid_ip?(value) ? accounts_with_users.merge(User.matches_ip(value)) : Account.none when 'staff' - accounts_with_users.merge User.staff + accounts_with_users.merge(User.staff) + when 'order' + order_scope(value) else raise "Unknown filter: #{key}" end end + def order_scope(value) + case value + when 'active' + params['remote'] ? Account.joins(:account_stat).by_recent_status : Account.joins(:user).by_recent_sign_in + when 'recent' + Account.recent + when 'alphabetic' + Account.alphabetic + else + raise "Unknown order: #{value}" + end + end + def accounts_with_users Account.joins(:user) end diff --git a/app/views/admin/accounts/_account.html.haml b/app/views/admin/accounts/_account.html.haml index b057d3e42..44b10af6e 100644 --- a/app/views/admin/accounts/_account.html.haml +++ b/app/views/admin/accounts/_account.html.haml @@ -11,6 +11,8 @@ %td - if account.user_current_sign_in_at %time.time-ago{ datetime: account.user_current_sign_in_at.iso8601, title: l(account.user_current_sign_in_at) }= l account.user_current_sign_in_at + - elsif account.last_status_at.present? + %time.time-ago{ datetime: account.last_status_at.iso8601, title: l(account.last_status_at) }= l account.last_status_at - else \- %td diff --git a/app/views/admin/accounts/index.html.haml b/app/views/admin/accounts/index.html.haml index 3a85324c9..7592161c9 100644 --- a/app/views/admin/accounts/index.html.haml +++ b/app/views/admin/accounts/index.html.haml @@ -19,6 +19,12 @@ %ul %li= filter_link_to t('admin.accounts.moderation.all'), staff: nil %li= filter_link_to t('admin.accounts.roles.staff'), staff: '1' + .filter-subset + %strong= t 'generic.order_by' + %ul + %li= filter_link_to t('relationships.most_recent'), order: nil + %li= filter_link_to t('admin.accounts.username'), order: 'alphabetic' + %li= filter_link_to t('relationships.last_active'), order: 'active' = form_tag admin_accounts_url, method: 'GET', class: 'simple_form' do .fields-group From 6185bff4b3c2fec7b84aee8a9d6747d42ad865c0 Mon Sep 17 00:00:00 2001 From: ThibG Date: Sun, 8 Mar 2020 15:42:20 +0100 Subject: [PATCH 17/29] Fix error when searching for URLs that contain the mention syntax (#13151) Fixes #13150 --- app/services/account_search_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/account_search_service.rb b/app/services/account_search_service.rb index d217dabb3..493813aab 100644 --- a/app/services/account_search_service.rb +++ b/app/services/account_search_service.rb @@ -171,7 +171,7 @@ class AccountSearchService < BaseService end def username_complete? - query.include?('@') && "@#{query}" =~ Account::MENTION_RE + query.include?('@') && "@#{query}" =~ /\A#{Account::MENTION_RE}\Z/ end def likely_acct? From 05d83cb07da9edc8df59f7316772e176752110f4 Mon Sep 17 00:00:00 2001 From: David Cook Date: Sun, 8 Mar 2020 09:45:19 -0500 Subject: [PATCH 18/29] Set BUNDLE_PATH in CircleCI (#13214) --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3ba027d95..a343fc654 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -6,6 +6,7 @@ aliases: - image: circleci/ruby:2.7-buster-node environment: &ruby_environment BUNDLE_APP_CONFIG: ./.bundle/ + BUNDLE_PATH: ./vendor/bundle/ DB_HOST: localhost DB_USER: root RAILS_ENV: test From 4063f9f27805de0a12904071e521094122b9f725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9lanie=20Chauvel=20=28ariasuni=29?= Date: Sun, 8 Mar 2020 15:59:55 +0100 Subject: [PATCH 19/29] Change description of privacy levels to be more intuitive in web UI (#13197) * Improve description of privacy levels in compose interface * Change strings in defaultMessage and source as well as english Co-authored-by: Thibaut Girka --- .../features/compose/components/privacy_dropdown.js | 8 ++++---- app/javascript/mastodon/locales/defaultMessages.json | 8 ++++---- app/javascript/mastodon/locales/en.json | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/javascript/mastodon/features/compose/components/privacy_dropdown.js b/app/javascript/mastodon/features/compose/components/privacy_dropdown.js index 7cbfe463a..de030b7a2 100644 --- a/app/javascript/mastodon/features/compose/components/privacy_dropdown.js +++ b/app/javascript/mastodon/features/compose/components/privacy_dropdown.js @@ -11,13 +11,13 @@ import Icon from 'mastodon/components/icon'; const messages = defineMessages({ public_short: { id: 'privacy.public.short', defaultMessage: 'Public' }, - public_long: { id: 'privacy.public.long', defaultMessage: 'Post to public timelines' }, + public_long: { id: 'privacy.public.long', defaultMessage: 'Visible for all, shown in public timelines' }, unlisted_short: { id: 'privacy.unlisted.short', defaultMessage: 'Unlisted' }, - unlisted_long: { id: 'privacy.unlisted.long', defaultMessage: 'Do not show in public timelines' }, + unlisted_long: { id: 'privacy.unlisted.long', defaultMessage: 'Visible for all, but not in public timelines' }, private_short: { id: 'privacy.private.short', defaultMessage: 'Followers-only' }, - private_long: { id: 'privacy.private.long', defaultMessage: 'Post to followers only' }, + private_long: { id: 'privacy.private.long', defaultMessage: 'Visible for followers only' }, direct_short: { id: 'privacy.direct.short', defaultMessage: 'Direct' }, - direct_long: { id: 'privacy.direct.long', defaultMessage: 'Post to mentioned users only' }, + direct_long: { id: 'privacy.direct.long', defaultMessage: 'Visible for mentioned users only' }, change_privacy: { id: 'privacy.change', defaultMessage: 'Adjust status privacy' }, }); diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json index 4c1fe94c5..d35fb9eb5 100644 --- a/app/javascript/mastodon/locales/defaultMessages.json +++ b/app/javascript/mastodon/locales/defaultMessages.json @@ -1073,7 +1073,7 @@ "id": "privacy.public.short" }, { - "defaultMessage": "Post to public timelines", + "defaultMessage": "Visible for all, shown in public timelines", "id": "privacy.public.long" }, { @@ -1081,7 +1081,7 @@ "id": "privacy.unlisted.short" }, { - "defaultMessage": "Do not show in public timelines", + "defaultMessage": "Visible for all, but not in public timelines", "id": "privacy.unlisted.long" }, { @@ -1089,7 +1089,7 @@ "id": "privacy.private.short" }, { - "defaultMessage": "Post to followers only", + "defaultMessage": "Visible for followers only", "id": "privacy.private.long" }, { @@ -1097,7 +1097,7 @@ "id": "privacy.direct.short" }, { - "defaultMessage": "Post to mentioned users only", + "defaultMessage": "Visible for mentioned users only", "id": "privacy.direct.long" }, { diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index fff449a51..7457bc3ad 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -319,13 +319,13 @@ "poll_button.add_poll": "Add a poll", "poll_button.remove_poll": "Remove poll", "privacy.change": "Adjust status privacy", - "privacy.direct.long": "Post to mentioned users only", + "privacy.direct.long": "Visible for mentioned users only", "privacy.direct.short": "Direct", - "privacy.private.long": "Post to followers only", + "privacy.private.long": "Visible for followers only", "privacy.private.short": "Followers-only", - "privacy.public.long": "Post to public timelines", + "privacy.public.long": "Visible for all, shown in public timelines", "privacy.public.short": "Public", - "privacy.unlisted.long": "Do not post to public timelines", + "privacy.unlisted.long": "Visible for all, but not in public timelines", "privacy.unlisted.short": "Unlisted", "refresh": "Refresh", "regeneration_indicator.label": "Loading…", From 2423d2f6772da39c0a76612dd2be299c445eb9f8 Mon Sep 17 00:00:00 2001 From: ThibG Date: Sun, 8 Mar 2020 16:00:24 +0100 Subject: [PATCH 20/29] Add ability to delete files uploaded for settings in admin UI (#13192) * Allow deleting site uploads * Refactor and move links into hints * Fix i18n tests * Fix HTML output of site_upload_delete_hint --- .../admin/site_uploads_controller.rb | 21 +++++++++++++++++++ app/helpers/admin/settings_helper.rb | 11 ++++++++++ app/policies/settings_policy.rb | 4 ++++ app/views/admin/settings/edit.html.haml | 6 +++--- config/locales/en.yml | 3 +++ config/routes.rb | 1 + 6 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 app/controllers/admin/site_uploads_controller.rb create mode 100644 app/helpers/admin/settings_helper.rb diff --git a/app/controllers/admin/site_uploads_controller.rb b/app/controllers/admin/site_uploads_controller.rb new file mode 100644 index 000000000..cacecedb0 --- /dev/null +++ b/app/controllers/admin/site_uploads_controller.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +module Admin + class SiteUploadsController < BaseController + before_action :set_site_upload + + def destroy + authorize :settings, :destroy? + + @site_upload.destroy! + + redirect_to edit_admin_settings_path, notice: I18n.t('admin.site_uploads.destroyed_msg') + end + + private + + def set_site_upload + @site_upload = SiteUpload.find(params[:id]) + end + end +end diff --git a/app/helpers/admin/settings_helper.rb b/app/helpers/admin/settings_helper.rb new file mode 100644 index 000000000..baf14ab25 --- /dev/null +++ b/app/helpers/admin/settings_helper.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Admin::SettingsHelper + def site_upload_delete_hint(hint, var) + upload = SiteUpload.find_by(var: var.to_s) + return hint unless upload + + link = link_to t('admin.site_uploads.delete'), admin_site_upload_path(upload), data: { method: :delete } + safe_join([hint, link], '
'.html_safe) + end +end diff --git a/app/policies/settings_policy.rb b/app/policies/settings_policy.rb index 2dcb79f51..874f97bab 100644 --- a/app/policies/settings_policy.rb +++ b/app/policies/settings_policy.rb @@ -8,4 +8,8 @@ class SettingsPolicy < ApplicationPolicy def show? admin? end + + def destroy? + admin? + end end diff --git a/app/views/admin/settings/edit.html.haml b/app/views/admin/settings/edit.html.haml index d7b493051..dc08f0141 100644 --- a/app/views/admin/settings/edit.html.haml +++ b/app/views/admin/settings/edit.html.haml @@ -30,13 +30,13 @@ .fields-row .fields-row__column.fields-row__column-6.fields-group - = f.input :thumbnail, as: :file, wrapper: :with_block_label, label: t('admin.settings.thumbnail.title'), hint: t('admin.settings.thumbnail.desc_html') + = f.input :thumbnail, as: :file, wrapper: :with_block_label, label: t('admin.settings.thumbnail.title'), hint: site_upload_delete_hint(t('admin.settings.thumbnail.desc_html'), :thumbnail) .fields-row__column.fields-row__column-6.fields-group - = f.input :hero, as: :file, wrapper: :with_block_label, label: t('admin.settings.hero.title'), hint: t('admin.settings.hero.desc_html') + = f.input :hero, as: :file, wrapper: :with_block_label, label: t('admin.settings.hero.title'), hint: site_upload_delete_hint(t('admin.settings.hero.desc_html'), :hero) .fields-row .fields-row__column.fields-row__column-6.fields-group - = f.input :mascot, as: :file, wrapper: :with_block_label, label: t('admin.settings.mascot.title'), hint: t('admin.settings.mascot.desc_html') + = f.input :mascot, as: :file, wrapper: :with_block_label, label: t('admin.settings.mascot.title'), hint: site_upload_delete_hint(t('admin.settings.mascot.desc_html'), :mascot) %hr.spacer/ diff --git a/config/locales/en.yml b/config/locales/en.yml index 99a80431a..8440b471c 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -537,6 +537,9 @@ en: trends: desc_html: Publicly display previously reviewed hashtags that are currently trending title: Trending hashtags + site_uploads: + delete: Delete uploaded file + destroyed_msg: Site upload successfully deleted! statuses: back_to_account: Back to account page batch: diff --git a/config/routes.rb b/config/routes.rb index c22efc1e1..2de31e2db 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -186,6 +186,7 @@ Rails.application.routes.draw do end resource :settings, only: [:edit, :update] + resources :site_uploads, only: [:destroy] resources :invites, only: [:index, :create, :destroy] do collection do From 4e524218d3086e4f930e2005f1ce2d82f29e1a20 Mon Sep 17 00:00:00 2001 From: tateisu Date: Mon, 9 Mar 2020 00:01:07 +0900 Subject: [PATCH 21/29] Add `--skip-media-remove` option to `tootctl statuses remove` (#13080) * Add skip_media_remove option to tootctl statuses remove * Add skip_media_remove option to tootctl statuses remove Co-authored-by: tateisu --- lib/mastodon/statuses_cli.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/mastodon/statuses_cli.rb b/lib/mastodon/statuses_cli.rb index ecaac17e3..b9dccdd8a 100644 --- a/lib/mastodon/statuses_cli.rb +++ b/lib/mastodon/statuses_cli.rb @@ -14,6 +14,7 @@ module Mastodon option :days, type: :numeric, default: 90 option :clean_followed, type: :boolean + option :skip_media_remove, type: :boolean desc 'remove', 'Remove unreferenced statuses' long_desc <<~LONG_DESC Remove statuses that are not referenced by local user activity, such as @@ -58,9 +59,10 @@ module Mastodon scope.in_batches.delete_all - say('Beginning removal of now-orphaned media attachments to free up disk space...') - - Scheduler::MediaCleanupScheduler.new.perform + unless options[:skip_media_remove] + say('Beginning removal of now-orphaned media attachments to free up disk space...') + Scheduler::MediaCleanupScheduler.new.perform + end say("Done after #{Time.now.to_f - start_at}s", :green) ensure From fd76955f3942bbd7ec830ab535bc31621cac14a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A8r=20Kessels?= Date: Sun, 8 Mar 2020 16:02:36 +0100 Subject: [PATCH 22/29] Code style improvements in JavaScript (#13159) * JS-linter: fix trailing comma's * Configure eslinter to ignore this onchange error. --- app/javascript/mastodon/actions/accounts.js | 2 +- .../mastodon/components/intersection_observer_article.js | 2 +- app/javascript/mastodon/features/blocks/index.js | 2 +- .../mastodon/features/compose/components/poll_form.js | 1 + app/javascript/mastodon/features/domain_blocks/index.js | 2 +- app/javascript/mastodon/features/favourites/index.js | 2 +- app/javascript/mastodon/features/follow_requests/index.js | 2 +- app/javascript/mastodon/features/followers/index.js | 2 +- app/javascript/mastodon/features/following/index.js | 2 +- app/javascript/mastodon/features/getting_started/index.js | 8 ++++---- app/javascript/mastodon/features/lists/index.js | 2 +- app/javascript/mastodon/features/mutes/index.js | 2 +- app/javascript/mastodon/features/reblogs/index.js | 2 +- .../mastodon/features/status/components/card.js | 2 +- .../features/ui/components/__tests__/column-test.js | 2 +- app/javascript/mastodon/reducers/notifications.js | 4 ++-- app/javascript/mastodon/reducers/timelines.js | 4 ++-- app/javascript/mastodon/selectors/index.js | 2 +- .../mastodon/service_worker/web_push_notifications.js | 2 +- app/javascript/mastodon/store/configureStore.js | 2 +- config/webpack/development.js | 2 +- config/webpack/shared.js | 4 ++-- 22 files changed, 28 insertions(+), 27 deletions(-) diff --git a/app/javascript/mastodon/actions/accounts.js b/app/javascript/mastodon/actions/accounts.js index d4a824e2c..4af36e998 100644 --- a/app/javascript/mastodon/actions/accounts.js +++ b/app/javascript/mastodon/actions/accounts.js @@ -106,7 +106,7 @@ export function fetchAccount(id) { dispatch, getState, db.transaction('accounts', 'read').objectStore('accounts').index('id'), - id + id, ).then(() => db.close(), error => { db.close(); throw error; diff --git a/app/javascript/mastodon/components/intersection_observer_article.js b/app/javascript/mastodon/components/intersection_observer_article.js index e453730ba..124b34b02 100644 --- a/app/javascript/mastodon/components/intersection_observer_article.js +++ b/app/javascript/mastodon/components/intersection_observer_article.js @@ -44,7 +44,7 @@ export default class IntersectionObserverArticle extends React.Component { intersectionObserverWrapper.observe( id, this.node, - this.handleIntersection + this.handleIntersection, ); this.componentMounted = true; diff --git a/app/javascript/mastodon/features/blocks/index.js b/app/javascript/mastodon/features/blocks/index.js index 051431ed2..870c0de09 100644 --- a/app/javascript/mastodon/features/blocks/index.js +++ b/app/javascript/mastodon/features/blocks/index.js @@ -68,7 +68,7 @@ class Blocks extends ImmutablePureComponent { bindToDocument={!multiColumn} > {accountIds.map(id => - + , )} diff --git a/app/javascript/mastodon/features/compose/components/poll_form.js b/app/javascript/mastodon/features/compose/components/poll_form.js index 01df31d3a..fa2b0609e 100644 --- a/app/javascript/mastodon/features/compose/components/poll_form.js +++ b/app/javascript/mastodon/features/compose/components/poll_form.js @@ -155,6 +155,7 @@ class PollForm extends ImmutablePureComponent {
+ {/* eslint-disable-next-line jsx-a11y/no-onchange */}