From 640421f661ee4d7e76a2aab607e7b15687940b6f Mon Sep 17 00:00:00 2001 From: Andy Piper Date: Sat, 7 Oct 2023 20:12:21 +0100 Subject: [PATCH 01/58] Add 4.2.x to supported versions in SECURITY.md (#27317) --- SECURITY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/SECURITY.md b/SECURITY.md index 9a08c4e251..3e13377db6 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -15,6 +15,7 @@ A "vulnerability in Mastodon" is a vulnerability in the code distributed through | Version | Supported | | ------- | ---------------- | +| 4.2.x | Yes | | 4.1.x | Yes | | 4.0.x | Until 2023-10-31 | | 3.5.x | Until 2023-12-31 | From eabe839744da759522e424c00f4936fefabffb3c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 9 Oct 2023 09:43:42 +0200 Subject: [PATCH 02/58] Update eslint (non-major) (#27328) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 148 ++++++++++++++++++++++++++---------------------------- 1 file changed, 71 insertions(+), 77 deletions(-) diff --git a/yarn.lock b/yarn.lock index 8604dcce25..08a0d60763 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1305,15 +1305,10 @@ dependencies: eslint-visitor-keys "^3.3.0" -"@eslint-community/regexpp@^4.5.1": - version "4.9.0" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.9.0.tgz#7ccb5f58703fa61ffdcbf39e2c604a109e781162" - integrity sha512-zJmuCWj2VLBt4c25CfBIbMZLGLyhkvs7LznyVX5HfpzeocThgIj5XQK4L+g3U36mMcx8bPMhGyPpwCATamC4jQ== - -"@eslint-community/regexpp@^4.6.1": - version "4.8.1" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.8.1.tgz#8c4bb756cc2aa7eaf13cfa5e69c83afb3260c20c" - integrity sha512-PWiOzLIUAjN/w5K17PoF4n6sKBw0gqLHPhywmYHP4t1VFQQVYeb1yWsJwnMVEMl3tUHME7X/SJPZLmtG7XBDxQ== +"@eslint-community/regexpp@^4.5.1", "@eslint-community/regexpp@^4.6.1": + version "4.9.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.9.1.tgz#449dfa81a57a1d755b09aa58d826c1262e4283b4" + integrity sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA== "@eslint/eslintrc@^2.1.2": version "2.1.2" @@ -1330,10 +1325,10 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@8.50.0": - version "8.50.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.50.0.tgz#9e93b850f0f3fa35f5fa59adfd03adae8488e484" - integrity sha512-NCC3zz2+nvYd+Ckfh87rA47zfu2QsQpvc6k1yzTk+b9KzRj0wkGa8LSoGOXN6Zv4lRf/EIoZ80biDh9HOI+RNQ== +"@eslint/js@8.51.0": + version "8.51.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.51.0.tgz#6d419c240cfb2b66da37df230f7e7eef801c32fa" + integrity sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg== "@floating-ui/core@^1.3.1": version "1.3.1" @@ -2624,15 +2619,15 @@ "@types/yargs-parser" "*" "@typescript-eslint/eslint-plugin@^6.0.0": - version "6.7.3" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.3.tgz#d98046e9f7102d49a93d944d413c6055c47fafd7" - integrity sha512-vntq452UHNltxsaaN+L9WyuMch8bMd9CqJ3zhzTPXXidwbf5mqqKCVXEuvRZUqLJSTLeWE65lQwyXsRGnXkCTA== + version "6.7.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.4.tgz#057338df21b6062c2f2fc5999fbea8af9973ac6d" + integrity sha512-DAbgDXwtX+pDkAHwiGhqP3zWUGpW49B7eqmgpPtg+BKJXwdct79ut9+ifqOFPJGClGKSHXn2PTBatCnldJRUoA== dependencies: "@eslint-community/regexpp" "^4.5.1" - "@typescript-eslint/scope-manager" "6.7.3" - "@typescript-eslint/type-utils" "6.7.3" - "@typescript-eslint/utils" "6.7.3" - "@typescript-eslint/visitor-keys" "6.7.3" + "@typescript-eslint/scope-manager" "6.7.4" + "@typescript-eslint/type-utils" "6.7.4" + "@typescript-eslint/utils" "6.7.4" + "@typescript-eslint/visitor-keys" "6.7.4" debug "^4.3.4" graphemer "^1.4.0" ignore "^5.2.4" @@ -2641,31 +2636,31 @@ ts-api-utils "^1.0.1" "@typescript-eslint/parser@^6.0.0": - version "6.7.3" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.7.3.tgz#aaf40092a32877439e5957e18f2d6a91c82cc2fd" - integrity sha512-TlutE+iep2o7R8Lf+yoer3zU6/0EAUc8QIBB3GYBc1KGz4c4TRm83xwXUZVPlZ6YCLss4r77jbu6j3sendJoiQ== + version "6.7.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.7.4.tgz#23d1dd4fe5d295c7fa2ab651f5406cd9ad0bd435" + integrity sha512-I5zVZFY+cw4IMZUeNCU7Sh2PO5O57F7Lr0uyhgCJmhN/BuTlnc55KxPonR4+EM3GBdfiCyGZye6DgMjtubQkmA== dependencies: - "@typescript-eslint/scope-manager" "6.7.3" - "@typescript-eslint/types" "6.7.3" - "@typescript-eslint/typescript-estree" "6.7.3" - "@typescript-eslint/visitor-keys" "6.7.3" + "@typescript-eslint/scope-manager" "6.7.4" + "@typescript-eslint/types" "6.7.4" + "@typescript-eslint/typescript-estree" "6.7.4" + "@typescript-eslint/visitor-keys" "6.7.4" debug "^4.3.4" -"@typescript-eslint/scope-manager@6.7.3": - version "6.7.3" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.7.3.tgz#07e5709c9bdae3eaf216947433ef97b3b8b7d755" - integrity sha512-wOlo0QnEou9cHO2TdkJmzF7DFGvAKEnB82PuPNHpT8ZKKaZu6Bm63ugOTn9fXNJtvuDPanBc78lGUGGytJoVzQ== +"@typescript-eslint/scope-manager@6.7.4": + version "6.7.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.7.4.tgz#a484a17aa219e96044db40813429eb7214d7b386" + integrity sha512-SdGqSLUPTXAXi7c3Ob7peAGVnmMoGzZ361VswK2Mqf8UOYcODiYvs8rs5ILqEdfvX1lE7wEZbLyELCW+Yrql1A== dependencies: - "@typescript-eslint/types" "6.7.3" - "@typescript-eslint/visitor-keys" "6.7.3" + "@typescript-eslint/types" "6.7.4" + "@typescript-eslint/visitor-keys" "6.7.4" -"@typescript-eslint/type-utils@6.7.3": - version "6.7.3" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.7.3.tgz#c2c165c135dda68a5e70074ade183f5ad68f3400" - integrity sha512-Fc68K0aTDrKIBvLnKTZ5Pf3MXK495YErrbHb1R6aTpfK5OdSFj0rVN7ib6Tx6ePrZ2gsjLqr0s98NG7l96KSQw== +"@typescript-eslint/type-utils@6.7.4": + version "6.7.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.7.4.tgz#847cd3b59baf948984499be3e0a12ff07373e321" + integrity sha512-n+g3zi1QzpcAdHFP9KQF+rEFxMb2KxtnJGID3teA/nxKHOVi3ylKovaqEzGBbVY2pBttU6z85gp0D00ufLzViQ== dependencies: - "@typescript-eslint/typescript-estree" "6.7.3" - "@typescript-eslint/utils" "6.7.3" + "@typescript-eslint/typescript-estree" "6.7.4" + "@typescript-eslint/utils" "6.7.4" debug "^4.3.4" ts-api-utils "^1.0.1" @@ -2674,10 +2669,10 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== -"@typescript-eslint/types@6.7.3": - version "6.7.3" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.7.3.tgz#0402b5628a63f24f2dc9d4a678e9a92cc50ea3e9" - integrity sha512-4g+de6roB2NFcfkZb439tigpAMnvEIg3rIjWQ+EM7IBaYt/CdJt6em9BJ4h4UpdgaBWdmx2iWsafHTrqmgIPNw== +"@typescript-eslint/types@6.7.4": + version "6.7.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.7.4.tgz#5d358484d2be986980c039de68e9f1eb62ea7897" + integrity sha512-o9XWK2FLW6eSS/0r/tgjAGsYasLAnOWg7hvZ/dGYSSNjCh+49k5ocPN8OmG5aZcSJ8pclSOyVKP2x03Sj+RrCA== "@typescript-eslint/typescript-estree@5.62.0": version "5.62.0" @@ -2692,30 +2687,30 @@ semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/typescript-estree@6.7.3": - version "6.7.3" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.3.tgz#ec5bb7ab4d3566818abaf0e4a8fa1958561b7279" - integrity sha512-YLQ3tJoS4VxLFYHTw21oe1/vIZPRqAO91z6Uv0Ss2BKm/Ag7/RVQBcXTGcXhgJMdA4U+HrKuY5gWlJlvoaKZ5g== +"@typescript-eslint/typescript-estree@6.7.4": + version "6.7.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.4.tgz#f2baece09f7bb1df9296e32638b2e1130014ef1a" + integrity sha512-ty8b5qHKatlNYd9vmpHooQz3Vki3gG+3PchmtsA4TgrZBKWHNjWfkQid7K7xQogBqqc7/BhGazxMD5vr6Ha+iQ== dependencies: - "@typescript-eslint/types" "6.7.3" - "@typescript-eslint/visitor-keys" "6.7.3" + "@typescript-eslint/types" "6.7.4" + "@typescript-eslint/visitor-keys" "6.7.4" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" semver "^7.5.4" ts-api-utils "^1.0.1" -"@typescript-eslint/utils@6.7.3": - version "6.7.3" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.7.3.tgz#96c655816c373135b07282d67407cb577f62e143" - integrity sha512-vzLkVder21GpWRrmSR9JxGZ5+ibIUSudXlW52qeKpzUEQhRSmyZiVDDj3crAth7+5tmN1ulvgKaCU2f/bPRCzg== +"@typescript-eslint/utils@6.7.4": + version "6.7.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.7.4.tgz#2236f72b10e38277ee05ef06142522e1de470ff2" + integrity sha512-PRQAs+HUn85Qdk+khAxsVV+oULy3VkbH3hQ8hxLRJXWBEd7iI+GbQxH5SEUSH7kbEoTp6oT1bOwyga24ELALTA== dependencies: "@eslint-community/eslint-utils" "^4.4.0" "@types/json-schema" "^7.0.12" "@types/semver" "^7.5.0" - "@typescript-eslint/scope-manager" "6.7.3" - "@typescript-eslint/types" "6.7.3" - "@typescript-eslint/typescript-estree" "6.7.3" + "@typescript-eslint/scope-manager" "6.7.4" + "@typescript-eslint/types" "6.7.4" + "@typescript-eslint/typescript-estree" "6.7.4" semver "^7.5.4" "@typescript-eslint/visitor-keys@5.62.0": @@ -2726,12 +2721,12 @@ "@typescript-eslint/types" "5.62.0" eslint-visitor-keys "^3.3.0" -"@typescript-eslint/visitor-keys@6.7.3": - version "6.7.3" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.3.tgz#83809631ca12909bd2083558d2f93f5747deebb2" - integrity sha512-HEVXkU9IB+nk9o63CeICMHxFWbHWr3E1mpilIQBe9+7L/lH97rleFLVtYsfnWB+JVMaiFnEaxvknvmIzX+CqVg== +"@typescript-eslint/visitor-keys@6.7.4": + version "6.7.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.4.tgz#80dfecf820fc67574012375859085f91a4dff043" + integrity sha512-pOW37DUhlTZbvph50x5zZCkFn3xzwkGtNoJHzIM3svpiSkJzwOYr/kVBaXmf+RAQiUDs1AHEZVNPg6UJCJpwRA== dependencies: - "@typescript-eslint/types" "6.7.3" + "@typescript-eslint/types" "6.7.4" eslint-visitor-keys "^3.4.1" "@webassemblyjs/ast@1.9.0": @@ -5528,14 +5523,14 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4 integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== eslint@^8.41.0: - version "8.50.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.50.0.tgz#2ae6015fee0240fcd3f83e1e25df0287f487d6b2" - integrity sha512-FOnOGSuFuFLv/Sa+FDVRZl4GGVAAFFi8LecRsI5a1tMO5HIE8nCm4ivAlzt4dT3ol/PaaGC0rJEEXQmHJBGoOg== + version "8.51.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.51.0.tgz#4a82dae60d209ac89a5cff1604fea978ba4950f3" + integrity sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA== dependencies: "@eslint-community/eslint-utils" "^4.2.0" "@eslint-community/regexpp" "^4.6.1" "@eslint/eslintrc" "^2.1.2" - "@eslint/js" "8.50.0" + "@eslint/js" "8.51.0" "@humanwhocodes/config-array" "^0.11.11" "@humanwhocodes/module-importer" "^1.0.1" "@nodelib/fs.walk" "^1.2.8" @@ -6001,15 +5996,15 @@ findup-sync@^3.0.0: resolve-dir "^1.0.1" flat-cache@^3.0.4: - version "3.1.0" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.1.0.tgz#0e54ab4a1a60fe87e2946b6b00657f1c99e1af3f" - integrity sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew== + version "3.1.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.1.1.tgz#a02a15fdec25a8f844ff7cc658f03dd99eb4609b" + integrity sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q== dependencies: - flatted "^3.2.7" + flatted "^3.2.9" keyv "^4.5.3" rimraf "^3.0.2" -flatted@^3.2.7: +flatted@^3.2.9: version "3.2.9" resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf" integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ== @@ -6308,9 +6303,9 @@ globals@^11.1.0: integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== globals@^13.19.0: - version "13.22.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.22.0.tgz#0c9fcb9c48a2494fbb5edbfee644285543eba9d8" - integrity sha512-H1Ddc/PbZHTDVJSnj8kWptIRSD6AM3pK+mKytuIVF4uoBV7rshFlhhvA58ceJ5wp3Er58w6zj7bykMpYXt3ETw== + version "13.23.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.23.0.tgz#ef31673c926a0976e1f61dab4dca57e0c0a8af02" + integrity sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA== dependencies: type-fest "^0.20.2" @@ -8019,9 +8014,9 @@ keycode@^2.1.7: integrity sha512-Rdgz9Hl9Iv4QKi8b0OlCRQEzp4AgVxyCtz5S/+VIHezDmrDhkp2N2TqBWOLz0/gbeREXOOiI9/4b8BY9uw2vFg== keyv@^4.5.3: - version "4.5.3" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.3.tgz#00873d2b046df737963157bd04f294ca818c9c25" - integrity sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug== + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== dependencies: json-buffer "3.0.1" @@ -11478,7 +11473,6 @@ stringz@^2.1.0: char-regex "^1.0.2" "strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: - name strip-ansi-cjs version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== From 5fc5a548b483fb1d7bbf308375bbb1ad43b8f4ca Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 9 Oct 2023 10:19:13 +0200 Subject: [PATCH 03/58] Update DefinitelyTyped types (non-major) (#27327) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/yarn.lock b/yarn.lock index 08a0d60763..b69e7b65f0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2381,9 +2381,9 @@ integrity sha512-xrO9OoVPqFuYyR/loIHjnbvvyRZREYKLjxV4+dY6v3FQR3stQ9ZxIGkaclF7YhI9hfjpuTbu14hZEy94qKLtOA== "@types/react-dom@^18.0.0", "@types/react-dom@^18.2.4": - version "18.2.8" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.8.tgz#338f1b0a646c9f10e0a97208c1d26b9f473dffd6" - integrity sha512-bAIvO5lN/U8sPGvs1Xm61rlRHHaq5rp5N3kp9C+NJ/Q41P8iqjkXSu0+/qu8POsjH9pNWb0OYabFez7taP7omw== + version "18.2.11" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.11.tgz#4332c315544698a0875dfdb6e320dda59e1b3d58" + integrity sha512-zq6Dy0EiCuF9pWFW6I6k6W2LdpUixLE4P6XjXU1QHLfak3GPACQfLwEuHzY5pOYa4hzj1d0GxX/P141aFjZsyg== dependencies: "@types/react" "*" @@ -2483,9 +2483,9 @@ "@types/react" "*" "@types/react@*", "@types/react@16 || 17 || 18", "@types/react@>=16.9.11", "@types/react@^18.0.26", "@types/react@^18.2.7": - version "18.2.24" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.24.tgz#3c7d68c02e0205a472f04abe4a0c1df35d995c05" - integrity sha512-Ee0Jt4sbJxMu1iDcetZEIKQr99J1Zfb6D4F3qfUWoR1JpInkY1Wdg4WwCyBjL257D0+jGqSl1twBjV8iCaC0Aw== + version "18.2.25" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.25.tgz#99fa44154132979e870ff409dc5b6e67f06f0199" + integrity sha512-24xqse6+VByVLIr+xWaQ9muX1B4bXJKXBbjszbld/UEDslGLY53+ZucF44HCmLbMPejTzGG9XgR+3m2/Wqu1kw== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" @@ -2576,14 +2576,14 @@ integrity sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA== "@types/uuid@^9.0.0": - version "9.0.4" - resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.4.tgz#e884a59338da907bda8d2ed03e01c5c49d036f1c" - integrity sha512-zAuJWQflfx6dYJM62vna+Sn5aeSWhh3OB+wfUEACNcqUSc0AGc5JKl+ycL1vrH7frGTXhJchYjE1Hak8L819dA== + version "9.0.5" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.5.tgz#25a71eb73eba95ac0e559ff3dd018fc08294acf6" + integrity sha512-xfHdwa1FMJ082prjSJpoEI57GZITiQz10r3vEJCHa2khEFQjKy91aWKz6+zybzssCvXUwE1LQWgWVwZ4nYUvHQ== "@types/warning@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/warning/-/warning-3.0.0.tgz#0d2501268ad8f9962b740d387c4654f5f8e23e52" - integrity sha512-t/Tvs5qR47OLOr+4E9ckN8AmP2Tf16gWq+/qA4iUGS/OOyHVO8wv2vjJuX8SNOUTJyWb+2t7wJm6cXILFnOROA== + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/warning/-/warning-3.0.1.tgz#a62d1d2b7f34376da84ee0afe0145152e62b9699" + integrity sha512-ywJmriP+nvjBKNBEMaNZgj2irZHoxcKeYcyMLbqhYKbDVn8yCIULy2Ol/tvIb37O3IBeZj3RU4tXqQTtGwoAMg== "@types/webpack-sources@*": version "3.2.1" @@ -2612,9 +2612,9 @@ integrity sha512-axdPBuLuEJt0c4yI5OZssC19K2Mq1uKdrfZBzuxLvaztgqUtFYZUNw7lETExPYJR9jdEoIg4mb7RQKRQzOkeGQ== "@types/yargs@^17.0.24", "@types/yargs@^17.0.8": - version "17.0.26" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.26.tgz#388e5002a8b284ad7b4599ba89920a6d74d8d79a" - integrity sha512-Y3vDy2X6zw/ZCumcwLpdhM5L7jmyGpmBCTYMHDLqT2IKVMYRRLdv6ZakA+wxhra6Z/3bwhNbNl9bDGXaFU+6rw== + version "17.0.28" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.28.tgz#d106e4301fbacde3d1796ab27374dd16588ec851" + integrity sha512-N3e3fkS86hNhtk6BEnc0rj3zcehaxx8QWhCROJkqpl5Zaoi7nAic3jH8q94jVD3zu5LGk+PUB6KAiDmimYOEQw== dependencies: "@types/yargs-parser" "*" From 89b48681cf7996bfa6ab973bbbcdf8797f908cea Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 9 Oct 2023 10:32:06 +0200 Subject: [PATCH 04/58] New Crowdin Translations (automated) (#27321) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/my.json | 2 ++ app/javascript/mastodon/locales/si.json | 21 +++++++++++++----- config/locales/devise.si.yml | 2 +- config/locales/si.yml | 29 +++++++++++++------------ config/locales/simple_form.my.yml | 1 + config/locales/simple_form.si.yml | 7 ++++-- 6 files changed, 39 insertions(+), 23 deletions(-) diff --git a/app/javascript/mastodon/locales/my.json b/app/javascript/mastodon/locales/my.json index 8e0b7ab41e..103f4e0f8d 100644 --- a/app/javascript/mastodon/locales/my.json +++ b/app/javascript/mastodon/locales/my.json @@ -312,6 +312,7 @@ "home.hide_announcements": "ကြေညာချက်များကို ဖျောက်ပါ", "home.pending_critical_update.body": "သင့် Mastodon ဆာဗာ အမြန်ဆုံး အပ်ဒိတ်လုပ်ပါ။", "home.pending_critical_update.link": "အပ်ဒိတ်များကြည့်ရန်", + "home.pending_critical_update.title": "အရေးကြီးသည့် လုံခြုံရေးအပ်ဒိတ် ရနိုင်ပါမည်။", "home.show_announcements": "ကြေညာချက်များကို ပြပါ", "interaction_modal.description.favourite": "Mastodon အကောင့်ဖြင့် ဤပို့စ်ကို သင် favorite ပြုလုပ်ကြောင်း စာရေးသူအား အသိပေးပြီး နောက်ပိုင်းတွင် သိမ်းဆည်းနိုင်သည်။", "interaction_modal.description.follow": "Mastodon အကောင့်ဖြင့် သင်၏ ပင်မစာမျက်နှာတွင် ၎င်းတို့၏ ပို့စ်များကို ရရှိရန်အတွက် {name} ကို စောင့်ကြည့်နိုင်ပါသည်။", @@ -594,6 +595,7 @@ "search_popout.options": "ရွေးချယ်ထားသည်များ ရှာဖွေရန်", "search_popout.quick_actions": "အမြန်လုပ်ဆောင်မှုများ", "search_popout.recent": "လတ်တလော ရှာဖွေမှုများ", + "search_popout.specific_date": "သီးခြားရက်စွဲ", "search_popout.user": "အသုံးပြုသူ", "search_results.accounts": "စာမျက်နှာ", "search_results.all": "အားလုံး", diff --git a/app/javascript/mastodon/locales/si.json b/app/javascript/mastodon/locales/si.json index 632e716bca..43bd5a1bb5 100644 --- a/app/javascript/mastodon/locales/si.json +++ b/app/javascript/mastodon/locales/si.json @@ -6,6 +6,7 @@ "about.rules": "සේවාදායකයේ නීති", "account.account_note_header": "සටහන", "account.add_or_remove_from_list": "ලැයිස්තු වලින් එකතු හෝ ඉවත් කරන්න", + "account.badges.bot": "ස්වයංක්‍රියයි", "account.badges.group": "සමූහය", "account.block": "@{name} අවහිර කරන්න", "account.block_domain": "{domain} වසම අවහිර කරන්න", @@ -21,14 +22,15 @@ "account.follow": "අනුගමනය", "account.followers": "අනුගාමිකයින්", "account.followers.empty": "කිසිවෙක් අනුගමනය කර නැත.", - "account.following": "අනුගමනය", - "account.following_counter": "{count, plural, one {අනුගාමිකයින් {counter}} other {අනුගාමිකයින් {counter}}}", + "account.followers_counter": "{count, plural, one {අනුගාමිකයින් {counter}} other {අනුගාමිකයින් {counter}}}", + "account.following": "අනුගමන", + "account.following_counter": "{count, plural, one {අනුගමන {counter}} other {අනුගමන {counter}}}", "account.follows.empty": "තවමත් කිසිවෙක් අනුගමනය නොකරයි.", "account.follows_you": "ඔබව අනුගමනය කරයි", "account.go_to_profile": "පැතිකඩට යන්න", "account.joined_short": "එක් වූ දිනය", "account.link_verified_on": "මෙම සබැඳියේ අයිතිය {date} දී පරීක්‍ෂා කෙරිණි", - "account.media": "මාධ්‍යය", + "account.media": "මාධ්‍ය", "account.mention": "@{name} සඳහන් කරන්ක", "account.mute": "@{name} නිහඬ කරන්න", "account.mute_short": "නිහඬ", @@ -37,6 +39,7 @@ "account.posts_with_replies": "ලිපි සහ පිළිතුරු", "account.report": "@{name} වාර්තා කරන්න", "account.share": "@{name} ගේ පැතිකඩ බෙදාගන්න", + "account.statuses_counter": "{count, plural, one {ලිපි {counter}} other {ලිපි {counter}}}", "account.unblock": "@{name} අනවහිර කරන්න", "account.unblock_domain": "{domain} වසම අනවහිර කරන්න", "account.unblock_short": "අනවහිර", @@ -53,11 +56,17 @@ "audio.hide": "හඬපටය සඟවන්න", "autosuggest_hashtag.per_week": "සතියකට {count}", "boost_modal.combo": "ඊළඟ වතාවේ මෙය මඟ හැරීමට {combo} එබීමට හැකිය", + "bundle_column_error.copy_stacktrace": "දෝෂ වාර්තාවේ පිටපතක්", + "bundle_column_error.error.title": "අපොයි!", + "bundle_column_error.network.title": "ජාලයේ දෝෂයකි", "bundle_column_error.retry": "නැවත උත්සාහ කරන්න", + "bundle_column_error.return": "ආපසු මුලට යන්න", + "bundle_column_error.routing.title": "404", "bundle_modal_error.close": "වසන්න", "bundle_modal_error.message": "මෙම සංරචකය පූරණයේ දී යම් දෙයක් වැරදී ඇත.", "bundle_modal_error.retry": "නැවත උත්සාහ කරන්න", "closed_registrations_modal.find_another_server": "වෙනත් සේවාදායක", + "closed_registrations_modal.title": "මාස්ටඩන් හි ලියාපදිංචි වන්න", "column.about": "පිලිබඳව", "column.blocks": "අවහිර කළ අය", "column.bookmarks": "පොත්යොමු", @@ -159,7 +168,7 @@ "empty_column.domain_blocks": "අවහිර කරන ලද වසම් නැත.", "empty_column.explore_statuses": "දැන් කිසිවක් නැඹුරු නොවේ. පසුව නැවත පරීක්ෂා කරන්න!", "empty_column.follow_requests": "ඔබට තවමත් අනුගමන ඉල්ලීම් ලැබී නැත. ඉල්ලීමක් ලැබුණු විට, එය මෙහි පෙන්වනු ඇත.", - "empty_column.home": "ඔබගේ මුල් පිටුව හිස් ය! මෙය පිරවීමට බොහෝ පුද්ගලයින් අනුගමනය කරන්න.", + "empty_column.home": "මුල් පිටුව හිස් ය! මෙය පිරවීමට බොහෝ පුද්ගලයින් අනුගමනය කරන්න.", "empty_column.lists": "ඔබට තවමත් ලැයිස්තු කිසිවක් නැත. ඔබ එකක් සාදන විට, එය මෙහි පෙන්වනු ඇත.", "empty_column.mutes": "ඔබ තවමත් කිසිදු පරිශීලකයෙකු නිහඬ කර නැත.", "empty_column.notifications": "ඔබට දැනුම්දීම් ලැබී නැත. අන් අය සහ ඔබ අතර අන්‍යෝන්‍ය බලපවත්වන දෑ මෙහි දිස්වනු ඇත.", @@ -264,7 +273,7 @@ "navigation_bar.favourites": "ප්‍රියතමයන්", "navigation_bar.filters": "නිහඬ කළ වචන", "navigation_bar.follow_requests": "අනුගමන ඉල්ලීම්", - "navigation_bar.follows_and_followers": "අනුගමනය හා අනුගාමිකයින්", + "navigation_bar.follows_and_followers": "අනුගමන හා අනුගාමික", "navigation_bar.lists": "ලැයිස්තු", "navigation_bar.logout": "නික්මෙන්න", "navigation_bar.mutes": "නිහඬ කළ අය", @@ -445,7 +454,7 @@ "time_remaining.seconds": "{number, plural, one {තත්පර #} other {තත්පර #}} ක් ඉතිරිය", "timeline_hint.remote_resource_not_displayed": "වෙනත් සේවාදායකයන්ගෙන් {resource} දර්ශනය නොවේ.", "timeline_hint.resources.followers": "අනුගාමිකයින්", - "timeline_hint.resources.follows": "අනුගමනය", + "timeline_hint.resources.follows": "අනුගමන", "timeline_hint.resources.statuses": "පරණ ලිපි", "trends.trending_now": "දැන් නැගී එන", "ui.beforeunload": "ඔබ මාස්ටඩන් හැර ගියහොත් කටුපිටපත අහිමි වේ.", diff --git a/config/locales/devise.si.yml b/config/locales/devise.si.yml index c866bed0e9..362f97b8a9 100644 --- a/config/locales/devise.si.yml +++ b/config/locales/devise.si.yml @@ -86,7 +86,7 @@ si: signed_up_but_locked: ඔබ සාර්ථකව ලියාපදිංචි වී ඇත. කෙසේ වෙතත්, ඔබගේ ගිණුම අගුලු දමා ඇති නිසා අපට ඔබව පුරනය කිරීමට නොහැකි විය. signed_up_but_pending: තහවුරු කිරීමේ සබැඳියක් සහිත පණිවිඩයක් ඔබගේ විද්‍යුත් තැපැල් ලිපිනයට යවා ඇත. ඔබ සබැඳිය ක්ලික් කළ පසු, අපි ඔබගේ අයදුම්පත සමාලෝචනය කරන්නෙමු. එය අනුමත වුවහොත් ඔබට දැනුම් දෙනු ලැබේ. signed_up_but_unconfirmed: තහවුරු කිරීමේ සබැඳියක් සහිත පණිවිඩයක් ඔබගේ විද්‍යුත් තැපැල් ලිපිනයට යවා ඇත. ඔබගේ ගිණුම සක්‍රිය කිරීමට කරුණාකර සබැඳිය අනුගමනය කරන්න. ඔබට මෙම විද්‍යුත් තැපෑල නොලැබුනේ නම් කරුණාකර ඔබගේ අයාචිත තැපැල් ෆෝල්ඩරය පරීක්ෂා කරන්න. - update_needs_confirmation: ඔබගේ ගිණුම සාර්ථකව යාවත්කාලීන වුවද අපට නව වි-තැපැල් ලිපිනය තහවුරු කර ගැනීමට වුවමනා කෙරේ. කරුණාකර ඔබගේ වි-තැපෑල පරීක්‍ෂා කර ඊට අදාළ සබැඳිය අනුගමනය කර ඔබගේ නව වි-තැපැල් ලිපිනය තහවුරු කරන්න. ඔබට මෙම වි-තැපෑල නොලැබුණේ නම් කරුණාකර අයාචිත තැපැල් බහාලුම බලන්න. + update_needs_confirmation: ඔබගේ ගිණුම සාර්ථකව යාවත්කාලීන වුවද අපට නව වි-තැපැල් ලිපිනය සත්‍යාපනය කර ගැනීමට වුවමනා කෙරේ. කරුණාකර ඔබගේ වි-තැපෑල පරීක්‍ෂා කර ඊට අදාළ සබැඳිය අනුගමනය කර ඔබගේ නව වි-තැපැල් ලිපිනය තහවුරු කරන්න. ඔබට මෙම වි-තැපෑල නොලැබුණේ නම් කරුණාකර අයාචිත තැපැල් බහාලුම බලන්න. updated: ඔබගේ ගිණුම සාර්ථකව යාවත්කාලීන කර ඇත. sessions: already_signed_out: සාර්ථකව නික්මිණි. diff --git a/config/locales/si.yml b/config/locales/si.yml index 51e1b838f3..8f04533519 100644 --- a/config/locales/si.yml +++ b/config/locales/si.yml @@ -11,7 +11,7 @@ si: followers: one: අනුගාමිකයා other: අනුගාමිකයින් - following: අනුගමනය + following: අනුගමන instance_actor_flash: මෙම ගිණුම සේවාදායකයම නියෝජනය කිරීමට භාවිතා කරන අතථ්‍ය නළුවෙකු වන අතර කිසිදු තනි පරිශීලකයෙකු නොවේ. එය ෆෙඩරේෂන් අරමුණු සඳහා භාවිතා කරන අතර අත්හිටුවිය යුතු නොවේ. last_active: අවසාන ක්රියාකාරී link_verified_on: මෙම සබැඳියේ හිමිකාරිත්වය %{date}හි පරීක්ෂා කරන ලදී @@ -383,7 +383,7 @@ si: status: තත්‍වය suppress: අනුගමනය නිර්දේශය යටපත් කරන්න suppressed: යටපත් කළා - title: නිර්දේශ අනුගමනය කරන්න + title: අනුගමනයට නිර්දේශ unsuppress: නිර්දේශ පිළිපැදීම ප්‍රතිසාධනය කරන්න instances: availability: @@ -622,7 +622,7 @@ si: history: අනුවාද ඉතිහාසය language: භාෂාව media: - title: මාධ්‍යය + title: මාධ්‍ය metadata: පාරදත්ත no_status_selected: කිසිවක් නොතේරූ බැවින් ලිපි කිසිවක් වෙනස් කර නැත open: ලිපිය අරින්න @@ -788,7 +788,7 @@ si: localization: body: මාස්ටඩන් ස්වේච්ඡාවෙන් පරිවර්තනය කර ඇත. guide_link: https://crowdin.com/project/mastodon - guide_link_text: සෑම කෙනෙකුටම දායක විය හැකිය. + guide_link_text: පරිවර්තකයින්ට දායක වීමට හැකිය. sensitive_content: සංවේදී අන්තර්ගත application_mailer: notification_preferences: ඊමේල් මනාප වෙනස් කරන්න @@ -1192,7 +1192,7 @@ si: relationships: activity: ගිණුමේ ක්‍රියාකාරකම් dormant: නිදිමතයි - follow_selected_followers: තෝරාගත් අනුගාමිකයින් අනුගමනය කරන්න + follow_selected_followers: තේරූ අනුගාමිකයින් අනුගමනය කරන්න followers: අනුගාමිකයින් following: අනුගමනය invited: ආරාධනා කළා @@ -1202,9 +1202,9 @@ si: mutual: අන්යෝන්ය primary: ප්‍රාථමික relationship: සම්බන්ධතාවය - remove_selected_domains: තෝරාගත් වසම් වලින් සියලුම අනුගාමිකයින් ඉවත් කරන්න - remove_selected_followers: තෝරාගත් අනුගාමිකයින් ඉවත් කරන්න - remove_selected_follows: තෝරාගත් පරිශීලකයින් අනුගමනය නොකරන්න + remove_selected_domains: තේරූ වසම් වල සියලුම අනුගාමිකයින් ඉවත් කරන්න + remove_selected_followers: තේරූ අනුගාමිකයින් ඉවත් කරන්න + remove_selected_follows: තේරූ අය අනුගමනය නොකරන්න status: ගිණුමේ තත්‍වය remote_follow: missing_resource: ඔබගේ ගිණුම සඳහා අවශ්‍ය යළි-යොමුවීම් URL එක සොයා ගැනීමට නොහැකි විය @@ -1280,7 +1280,7 @@ si: notifications: දැනුම්දීම් preferences: අභිප්‍රේත profile: ප්‍රසිද්ධ පැතිකඩ - relationships: අනුගාමිකයින් සහ අනුගාමිකයින් + relationships: අනුගමන හා අනුගාමික statuses_cleanup: ස්වයංක්‍රීය ලිපි මැකීම two_factor_authentication: ද්වි සාධක Aut webauthn_authentication: ආරක්‍ෂණ යතුරු @@ -1325,7 +1325,7 @@ si: title: '%{name}: "%{quote}"' visibilities: direct: සෘජු - private: අනුගාමිකයින්-පමණි + private: අනුගාමිකයින් පමණි private_long: අනුගාමිකයින්ට පමණක් පෙන්වන්න public: ප්‍රසිද්ධ public_long: හැමෝටම පේනවා @@ -1337,12 +1337,13 @@ si: ignore_favs: ප්‍රියතමයන් නොසලකන්න interaction_exceptions: අන්තර්ක්‍රියා මත පදනම් වූ ව්‍යතිරේක keep_direct: සෘජු පණිවිඩ තබාගන්න - keep_direct_hint: ඔබගේ සෘජු පණිවිඩ කිසිවක් මැකෙන්නේ නැත + keep_direct_hint: ඔබගේ සෘජු පණිවිඩ කිසිවක් නොමැකෙයි keep_media: මාධ්‍ය ඇමුණුම් සහිත ලිපි තබාගන්න - keep_media_hint: මාධ්‍ය ඇමුණුම් සහිත ඔබගේ ලිපි කිසිවක් මැකෙන්නේ නැත + keep_media_hint: මාධ්‍ය ඇමුණුම් සහිත ඔබගේ ලිපි කිසිවක් නොමැකෙයි keep_pinned: ඇමිණූ ලිපි තබාගන්න keep_pinned_hint: ඔබ ඇමිණූ ලිපි කිසිවක් නොමැකෙයි - keep_polls_hint: ඔබගේ මත විමසුම් මැකෙන්නේ නැත + keep_polls: මත විමසුම් තබාගන්න + keep_polls_hint: ඔබගේ මත විමසුම් නොමැකෙයි keep_self_bookmark: ඔබ පොත්යොමු තැබූ ලිපි තබාගන්න keep_self_bookmark_hint: ඔබගේම ලිපි වලට පොත්යොමු තබා ඇත්නම් ඒවා මකා නොදැමෙයි keep_self_fav: ඔබ ප්‍රිය කළ ලිපි තබාගන්න @@ -1356,7 +1357,7 @@ si: '604800': සති 1 '63113904': අවුරුදු 2 '7889238': මාස 3 - min_age_label: වයස් සීමාව + min_age_label: කාල සීමාව min_favs: අවම වශයෙන් ප්‍රිය කළ ලිපි තබාගන්න stream_entries: sensitive_content: සංවේදී අන්තර්ගතයකි diff --git a/config/locales/simple_form.my.yml b/config/locales/simple_form.my.yml index cf15616d24..80b234c17c 100644 --- a/config/locales/simple_form.my.yml +++ b/config/locales/simple_form.my.yml @@ -323,6 +323,7 @@ my: url: URL ဆုံးမှတ် 'no': မလုပ်ပါ not_recommended: ထောက်ခံထားမှုမရှိ + overridden: ပယ်ဖျက် recommended: ထောက်ခံထားပြီး required: mark: "*" diff --git a/config/locales/simple_form.si.yml b/config/locales/simple_form.si.yml index 7e529c0eee..ededa85bcc 100644 --- a/config/locales/simple_form.si.yml +++ b/config/locales/simple_form.si.yml @@ -90,6 +90,8 @@ si: fields: name: නම්පත value: අන්තර්ගතය + show_collections: අනුගමන හා අනුගාමිකයින් පැතිකඩෙහි පෙන්වන්න + unlocked: නව අනුගාමිකයින් ස්වයංක්‍රීයව පිළිගන්න account_alias: acct: පැරණි ගිණුමේ හැසිරවීම account_migration: @@ -118,8 +120,9 @@ si: appeal: text: මෙම තීරණය ආපසු හැරවිය යුත්තේ මන්දැයි පැහැදිලි කරන්න defaults: - autofollow: ඔබගේ ගිණුම අනුගමනය කිරීමට ආරාධනා කරන්න + autofollow: ඔබගේ ගිණුම අනුගමනයයට ආරාධනා කරන්න avatar: පැතිකඩ ඡායාරූපය + bot: මෙම ගිණුම ස්වයංක්‍රියයි chosen_languages: භාෂා පෙරන්න confirm_new_password: නව මුරපදය තහවුරු කරන්න confirm_password: මුරපදය තහවුරු කරන්න @@ -140,7 +143,7 @@ si: otp_attempt: ද්වි සාධක කේතය password: මුරපදය phrase: මූල පදය හෝ වාක්‍ය ඛණ්ඩය - setting_advanced_layout: උසස් වෙබ් අතුරු මුහුණත සබල කරන්න + setting_advanced_layout: සංකීර්ණ අතුරු මුහුණත සබල කරන්න setting_always_send_emails: සෑම විටම විද්‍යුත් තැපැල් දැනුම්දීම් යවන්න setting_auto_play_gif: සජීවිකරණ GIF ස්වයංක්‍රීයව ධාවනය කරන්න setting_default_language: ලිපිවල භාෂාව From c310374a2f83a890520ace50e41c1e3d046e15e1 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 9 Oct 2023 12:21:02 +0200 Subject: [PATCH 05/58] Fix clicking on already-opened thread post scrolling to the top of the thread (#27331) --- .../mastodon/features/status/index.jsx | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/app/javascript/mastodon/features/status/index.jsx b/app/javascript/mastodon/features/status/index.jsx index 799354d183..482323e089 100644 --- a/app/javascript/mastodon/features/status/index.jsx +++ b/app/javascript/mastodon/features/status/index.jsx @@ -607,6 +607,22 @@ class Status extends ImmutablePureComponent { this.setState({ fullscreen: isFullscreen() }); }; + shouldUpdateScroll = (prevRouterProps, { location }) => { + // Do not change scroll when opening a modal + if (location.state?.mastodonModalKey && location.state?.mastodonModalKey !== prevRouterProps?.location?.state?.mastodonModalKey) { + return false; + } + + // Scroll to focused post if it is loaded + const child = this.node?.querySelector('.detailed-status__wrapper'); + if (child) { + return [0, child.offsetTop]; + } + + // Do not scroll otherwise, `componentDidUpdate` will take care of that + return false; + }; + render () { let ancestors, descendants; const { isLoading, status, ancestorsIds, descendantsIds, intl, domain, multiColumn, pictureInPicture } = this.props; @@ -660,7 +676,7 @@ class Status extends ImmutablePureComponent { )} /> - +
{ancestors} From 774e1189d26fffd914107a4236f6287043c988f8 Mon Sep 17 00:00:00 2001 From: Renaud Chaput Date: Mon, 9 Oct 2023 13:38:29 +0200 Subject: [PATCH 06/58] Change `eslint` config to autofix missing comma and indentation in JS files (#26711) --- .eslintrc.js | 3 ++- app/javascript/mastodon/actions/alerts.js | 2 +- .../mastodon/actions/importer/normalizer.js | 6 +++--- app/javascript/mastodon/components/column.jsx | 2 +- app/javascript/mastodon/components/poll.jsx | 2 +- app/javascript/mastodon/components/status.jsx | 2 +- .../compose/components/navigation_bar.jsx | 2 +- .../features/compose/components/search.jsx | 16 ++++++++-------- .../mastodon/features/explore/results.jsx | 6 +++--- .../mastodon/features/firehose/index.jsx | 2 +- .../features/interaction_modal/index.jsx | 8 ++++---- .../mastodon/features/reblogs/index.jsx | 2 +- .../mastodon/features/report/comment.jsx | 2 +- .../status/components/detailed_status.jsx | 2 +- .../mastodon/features/ui/components/header.jsx | 4 ++-- .../features/ui/components/modal_root.jsx | 2 +- .../features/ui/components/sign_in_banner.jsx | 2 +- app/javascript/packs/application.js | 2 +- streaming/index.js | 10 +++++----- 19 files changed, 39 insertions(+), 38 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index d5f0ae1ac5..3bac9ed694 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -9,7 +9,6 @@ module.exports = { 'plugin:import/recommended', 'plugin:promise/recommended', 'plugin:jsdoc/recommended', - 'plugin:prettier/recommended', ], env: { @@ -63,7 +62,9 @@ module.exports = { 'consistent-return': 'error', 'dot-notation': 'error', eqeqeq: ['error', 'always', { 'null': 'ignore' }], + 'indent': ['error', 2], 'jsx-quotes': ['error', 'prefer-single'], + 'semi': ['error', 'always'], 'no-case-declarations': 'off', 'no-catch-shadow': 'error', 'no-console': [ diff --git a/app/javascript/mastodon/actions/alerts.js b/app/javascript/mastodon/actions/alerts.js index 051a9675b3..42834146bf 100644 --- a/app/javascript/mastodon/actions/alerts.js +++ b/app/javascript/mastodon/actions/alerts.js @@ -56,4 +56,4 @@ export const showAlertForError = (error, skipNotFound = false) => { title: messages.unexpectedTitle, message: messages.unexpectedMessage, }); -} +}; diff --git a/app/javascript/mastodon/actions/importer/normalizer.js b/app/javascript/mastodon/actions/importer/normalizer.js index e6b361c0c9..a72142a86f 100644 --- a/app/javascript/mastodon/actions/importer/normalizer.js +++ b/app/javascript/mastodon/actions/importer/normalizer.js @@ -104,7 +104,7 @@ export function normalizeStatus(status, normalOldStatus) { normalStatus.media_attachments.forEach(item => { const oldItem = list.find(i => i.get('id') === item.id); if (oldItem && oldItem.get('description') === item.description) { - item.translation = oldItem.get('translation') + item.translation = oldItem.get('translation'); } }); } @@ -137,13 +137,13 @@ export function normalizePoll(poll, normalOldPoll) { ...option, voted: poll.own_votes && poll.own_votes.includes(index), titleHtml: emojify(escapeTextContentForBrowser(option.title), emojiMap), - } + }; if (normalOldPoll && normalOldPoll.getIn(['options', index, 'title']) === option.title) { normalOption.translation = normalOldPoll.getIn(['options', index, 'translation']); } - return normalOption + return normalOption; }); return normalPoll; diff --git a/app/javascript/mastodon/components/column.jsx b/app/javascript/mastodon/components/column.jsx index cf9df3ba27..abc87a57e5 100644 --- a/app/javascript/mastodon/components/column.jsx +++ b/app/javascript/mastodon/components/column.jsx @@ -22,7 +22,7 @@ export default class Column extends PureComponent { scrollable = document.scrollingElement; } else { scrollable = this.node.querySelector('.scrollable'); - } + } if (!scrollable) { return; diff --git a/app/javascript/mastodon/components/poll.jsx b/app/javascript/mastodon/components/poll.jsx index 4304f9acd4..2d992d73ae 100644 --- a/app/javascript/mastodon/components/poll.jsx +++ b/app/javascript/mastodon/components/poll.jsx @@ -132,7 +132,7 @@ class Poll extends ImmutablePureComponent { handleReveal = () => { this.setState({ revealed: true }); - } + }; renderOption (option, optionIndex, showResults) { const { poll, lang, disabled, intl } = this.props; diff --git a/app/javascript/mastodon/components/status.jsx b/app/javascript/mastodon/components/status.jsx index 4a5ad54a1c..49d00ca7c9 100644 --- a/app/javascript/mastodon/components/status.jsx +++ b/app/javascript/mastodon/components/status.jsx @@ -199,7 +199,7 @@ class Status extends ImmutablePureComponent { } else if (attachments.getIn([0, 'type']) === 'audio') { return '16 / 9'; } else { - return (attachments.size === 1 && attachments.getIn([0, 'meta', 'small', 'aspect'])) ? attachments.getIn([0, 'meta', 'small', 'aspect']) : '3 / 2' + return (attachments.size === 1 && attachments.getIn([0, 'meta', 'small', 'aspect'])) ? attachments.getIn([0, 'meta', 'small', 'aspect']) : '3 / 2'; } } diff --git a/app/javascript/mastodon/features/compose/components/navigation_bar.jsx b/app/javascript/mastodon/features/compose/components/navigation_bar.jsx index 5af38da43c..e842ab1f8d 100644 --- a/app/javascript/mastodon/features/compose/components/navigation_bar.jsx +++ b/app/javascript/mastodon/features/compose/components/navigation_bar.jsx @@ -20,7 +20,7 @@ export default class NavigationBar extends ImmutablePureComponent { }; render () { - const username = this.props.account.get('acct') + const username = this.props.account.get('acct'); return (
diff --git a/app/javascript/mastodon/features/compose/components/search.jsx b/app/javascript/mastodon/features/compose/components/search.jsx index 7e1d8b7609..dfbfa98f5e 100644 --- a/app/javascript/mastodon/features/compose/components/search.jsx +++ b/app/javascript/mastodon/features/compose/components/search.jsx @@ -57,14 +57,14 @@ class Search extends PureComponent { }; defaultOptions = [ - { label: <>has: , action: e => { e.preventDefault(); this._insertText('has:') } }, - { label: <>is: , action: e => { e.preventDefault(); this._insertText('is:') } }, - { label: <>language: , action: e => { e.preventDefault(); this._insertText('language:') } }, - { label: <>from: , action: e => { e.preventDefault(); this._insertText('from:') } }, - { label: <>before: , action: e => { e.preventDefault(); this._insertText('before:') } }, - { label: <>during: , action: e => { e.preventDefault(); this._insertText('during:') } }, - { label: <>after: , action: e => { e.preventDefault(); this._insertText('after:') } }, - { label: <>in: , action: e => { e.preventDefault(); this._insertText('in:') } } + { label: <>has: , action: e => { e.preventDefault(); this._insertText('has:'); } }, + { label: <>is: , action: e => { e.preventDefault(); this._insertText('is:'); } }, + { label: <>language: , action: e => { e.preventDefault(); this._insertText('language:'); } }, + { label: <>from: , action: e => { e.preventDefault(); this._insertText('from:'); } }, + { label: <>before: , action: e => { e.preventDefault(); this._insertText('before:'); } }, + { label: <>during: , action: e => { e.preventDefault(); this._insertText('during:'); } }, + { label: <>after: , action: e => { e.preventDefault(); this._insertText('after:'); } }, + { label: <>in: , action: e => { e.preventDefault(); this._insertText('in:'); } } ]; setRef = c => { diff --git a/app/javascript/mastodon/features/explore/results.jsx b/app/javascript/mastodon/features/explore/results.jsx index 4c23d6422d..a3c6adee9d 100644 --- a/app/javascript/mastodon/features/explore/results.jsx +++ b/app/javascript/mastodon/features/explore/results.jsx @@ -80,7 +80,7 @@ class Results extends PureComponent { } return null; - }; + } handleSelectAll = () => { const { submittedType, dispatch } = this.props; @@ -116,7 +116,7 @@ class Results extends PureComponent { } this.setState({ type: 'hashtags' }); - } + }; handleSelectStatuses = () => { const { submittedType, dispatch } = this.props; @@ -128,7 +128,7 @@ class Results extends PureComponent { } this.setState({ type: 'statuses' }); - } + }; handleLoadMoreAccounts = () => this._loadMore('accounts'); handleLoadMoreStatuses = () => this._loadMore('statuses'); diff --git a/app/javascript/mastodon/features/firehose/index.jsx b/app/javascript/mastodon/features/firehose/index.jsx index efde58a5c0..849ee38f5f 100644 --- a/app/javascript/mastodon/features/firehose/index.jsx +++ b/app/javascript/mastodon/features/firehose/index.jsx @@ -199,7 +199,7 @@ const Firehose = ({ feedType, multiColumn }) => { ); -} +}; Firehose.propTypes = { multiColumn: PropTypes.bool, diff --git a/app/javascript/mastodon/features/interaction_modal/index.jsx b/app/javascript/mastodon/features/interaction_modal/index.jsx index 2a9fa0e33e..69bbd8cd87 100644 --- a/app/javascript/mastodon/features/interaction_modal/index.jsx +++ b/app/javascript/mastodon/features/interaction_modal/index.jsx @@ -27,9 +27,9 @@ const mapStateToProps = (state, { accountId }) => ({ const mapDispatchToProps = (dispatch) => ({ onSignupClick() { dispatch(closeModal({ - modalType: undefined, - ignoreFocus: false, - })); + modalType: undefined, + ignoreFocus: false, + })); dispatch(openModal({ modalType: 'CLOSED_REGISTRATIONS' })); }, }); @@ -187,7 +187,7 @@ class LoginForm extends React.PureComponent { setIFrameRef = (iframe) => { this.iframeRef = iframe; - } + }; handleFocus = () => { this.setState({ expanded: true }); diff --git a/app/javascript/mastodon/features/reblogs/index.jsx b/app/javascript/mastodon/features/reblogs/index.jsx index 0c4e6dbb93..9de905790a 100644 --- a/app/javascript/mastodon/features/reblogs/index.jsx +++ b/app/javascript/mastodon/features/reblogs/index.jsx @@ -45,7 +45,7 @@ class Reblogs extends ImmutablePureComponent { if (!this.props.accountIds) { this.props.dispatch(fetchReblogs(this.props.params.statusId)); } - }; + } handleRefresh = () => { this.props.dispatch(fetchReblogs(this.props.params.statusId)); diff --git a/app/javascript/mastodon/features/report/comment.jsx b/app/javascript/mastodon/features/report/comment.jsx index 98ac4caa0a..ca9ea9d268 100644 --- a/app/javascript/mastodon/features/report/comment.jsx +++ b/app/javascript/mastodon/features/report/comment.jsx @@ -104,7 +104,7 @@ const Comment = ({ comment, domain, statusIds, isRemote, isSubmitting, selectedD
); -} +}; Comment.propTypes = { comment: PropTypes.string.isRequired, diff --git a/app/javascript/mastodon/features/status/components/detailed_status.jsx b/app/javascript/mastodon/features/status/components/detailed_status.jsx index 3927aba2f5..e590ddb821 100644 --- a/app/javascript/mastodon/features/status/components/detailed_status.jsx +++ b/app/javascript/mastodon/features/status/components/detailed_status.jsx @@ -132,7 +132,7 @@ class DetailedStatus extends ImmutablePureComponent { } else if (attachments.getIn([0, 'type']) === 'audio') { return '16 / 9'; } else { - return (attachments.size === 1 && attachments.getIn([0, 'meta', 'small', 'aspect'])) ? attachments.getIn([0, 'meta', 'small', 'aspect']) : '3 / 2' + return (attachments.size === 1 && attachments.getIn([0, 'meta', 'small', 'aspect'])) ? attachments.getIn([0, 'meta', 'small', 'aspect']) : '3 / 2'; } } diff --git a/app/javascript/mastodon/features/ui/components/header.jsx b/app/javascript/mastodon/features/ui/components/header.jsx index 68484b59ab..8c6cd600e8 100644 --- a/app/javascript/mastodon/features/ui/components/header.jsx +++ b/app/javascript/mastodon/features/ui/components/header.jsx @@ -76,8 +76,8 @@ class Header extends PureComponent { if (sso_redirect) { content = ( - - ) + + ); } else { let signupButton; diff --git a/app/javascript/mastodon/features/ui/components/modal_root.jsx b/app/javascript/mastodon/features/ui/components/modal_root.jsx index f6de5dad35..46f0dc706f 100644 --- a/app/javascript/mastodon/features/ui/components/modal_root.jsx +++ b/app/javascript/mastodon/features/ui/components/modal_root.jsx @@ -117,7 +117,7 @@ export default class ModalRoot extends PureComponent { {(SpecificComponent) => { const ref = typeof SpecificComponent !== 'function' ? this.setModalRef : undefined; - return + return ; }} diff --git a/app/javascript/mastodon/features/ui/components/sign_in_banner.jsx b/app/javascript/mastodon/features/ui/components/sign_in_banner.jsx index d5f0c00dca..4216f3da38 100644 --- a/app/javascript/mastodon/features/ui/components/sign_in_banner.jsx +++ b/app/javascript/mastodon/features/ui/components/sign_in_banner.jsx @@ -25,7 +25,7 @@ const SignInBanner = () => {

- ) + ); } if (registrationsOpen) { diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js index f26321c41a..d13388b479 100644 --- a/app/javascript/packs/application.js +++ b/app/javascript/packs/application.js @@ -1,5 +1,5 @@ import './public-path'; -import main from "mastodon/main" +import main from "mastodon/main"; import { start } from '../mastodon/common'; import { loadLocale } from '../mastodon/locales'; diff --git a/streaming/index.js b/streaming/index.js index 3565ed2783..b3765531c6 100644 --- a/streaming/index.js +++ b/streaming/index.js @@ -256,7 +256,7 @@ const startServer = async () => { CHANNEL_NAMES.forEach(( channel ) => { connectedChannels.set({ type: 'websocket', channel }, 0); connectedChannels.set({ type: 'eventsource', channel }, 0); - }) + }); // Prime the counters so that we don't loose metrics between restarts. // Unfortunately counters don't support the set() API, so instead I'm using @@ -1296,7 +1296,7 @@ const startServer = async () => { log.verbose(request.requestId, 'Subscription error:', err.toString()); socket.send(JSON.stringify({ error: err.toString() })); }); - } + }; const removeSubscription = (subscriptions, channelIds, request) => { @@ -1316,7 +1316,7 @@ const startServer = async () => { subscription.stopHeartbeat(); delete subscriptions[channelIds.join(';')]; - } + }; /** * @param {WebSocketSession} session @@ -1336,7 +1336,7 @@ const startServer = async () => { socket.send(JSON.stringify({ error: "Error unsubscribing from channel" })); } }); - } + }; /** * @param {WebSocketSession} session @@ -1414,7 +1414,7 @@ const startServer = async () => { const subscriptions = Object.keys(session.subscriptions); subscriptions.forEach(channelIds => { - removeSubscription(session.subscriptions, channelIds.split(';'), req) + removeSubscription(session.subscriptions, channelIds.split(';'), req); }); // Decrement the metrics for connected clients: From 4c2aca777f6ae6942d0cf11aee56a925694ccdef Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 9 Oct 2023 16:46:09 +0200 Subject: [PATCH 07/58] Fix clicking on already-loaded thread scrolling to the top of the thread (#27338) --- .../mastodon/features/status/index.jsx | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/app/javascript/mastodon/features/status/index.jsx b/app/javascript/mastodon/features/status/index.jsx index 482323e089..39823268b2 100644 --- a/app/javascript/mastodon/features/status/index.jsx +++ b/app/javascript/mastodon/features/status/index.jsx @@ -220,6 +220,8 @@ class Status extends ImmutablePureComponent { componentDidMount () { attachFullscreenListener(this.onFullScreenChange); + + this._scrollStatusIntoView(); } UNSAFE_componentWillReceiveProps (nextProps) { @@ -579,10 +581,10 @@ class Status extends ImmutablePureComponent { this.node = c; }; - componentDidUpdate (prevProps) { - const { status, ancestorsIds, multiColumn } = this.props; + _scrollStatusIntoView () { + const { status, multiColumn } = this.props; - if (status && (ancestorsIds.size > prevProps.ancestorsIds.size || prevProps.status?.get('id') !== status.get('id'))) { + if (status) { window.requestAnimationFrame(() => { this.node?.querySelector('.detailed-status__wrapper')?.scrollIntoView(true); @@ -599,6 +601,14 @@ class Status extends ImmutablePureComponent { } } + componentDidUpdate (prevProps) { + const { status, ancestorsIds } = this.props; + + if (status && (ancestorsIds.size > prevProps.ancestorsIds.size || prevProps.status?.get('id') !== status.get('id'))) { + this._scrollStatusIntoView(); + } + } + componentWillUnmount () { detachFullscreenListener(this.onFullScreenChange); } From 1745c582f8eed1d1dacef5b5c7c735e4fd80574a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 10 Oct 2023 09:52:09 +0200 Subject: [PATCH 08/58] Update dependency sidekiq to v6.5.11 (#27345) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index c64487c2e1..affe1bf7f2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -671,7 +671,7 @@ GEM rubyzip (>= 1.2.2, < 3.0) websocket (~> 1.0) semantic_range (3.0.0) - sidekiq (6.5.10) + sidekiq (6.5.11) connection_pool (>= 2.2.5, < 3) rack (~> 2.0) redis (>= 4.5.0, < 5) From 1a2a4c389fedf4e16457c10d9dbd6aa39fc3f794 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 10 Oct 2023 10:06:37 +0200 Subject: [PATCH 09/58] New Crowdin Translations (automated) (#27347) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/ko.json | 2 +- app/javascript/mastodon/locales/uk.json | 30 ++++++++++++------------- config/locales/simple_form.es-MX.yml | 2 +- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json index 5b37324f7d..f2237d693e 100644 --- a/app/javascript/mastodon/locales/ko.json +++ b/app/javascript/mastodon/locales/ko.json @@ -102,7 +102,7 @@ "bundle_modal_error.message": "컴포넌트를 불러오는 중 문제가 발생했습니다.", "bundle_modal_error.retry": "다시 시도", "closed_registrations.other_server_instructions": "마스토돈은 분산화 되어 있기 때문에, 다른 서버에서 계정을 만들더라도 이 서버와 상호작용 할 수 있습니다.", - "closed_registrations_modal.description": "{domain}은 현재 가입이 막혀있는 상태입니다, 만약 마스토돈을 이용하기 위해 꼭 {domain}을 사용할 필요는 없다는 사실을 인지해 두세요.", + "closed_registrations_modal.description": "{domain}은 현재 가입이 막혀있는 상태입니다, 마스토돈을 이용하기 위해 꼭 {domain}을 사용할 필요는 없다는 사실을 인지해 두세요.", "closed_registrations_modal.find_another_server": "다른 서버 찾기", "closed_registrations_modal.preamble": "마스토돈은 분산화 되어 있습니다, 그렇기 때문에 어디에서 계정을 생성하든, 이 서버에 있는 누구와도 팔로우와 상호작용을 할 수 있습니다. 심지어는 스스로 서버를 만드는 것도 가능합니다!", "closed_registrations_modal.title": "마스토돈에서 가입", diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json index 48e76141d8..aa17e12545 100644 --- a/app/javascript/mastodon/locales/uk.json +++ b/app/javascript/mastodon/locales/uk.json @@ -79,16 +79,16 @@ "admin.impact_report.instance_accounts": "Профілі облікових записів буде видалено", "admin.impact_report.instance_followers": "Підписники, яких можуть втратити наші користувачі", "admin.impact_report.instance_follows": "Підписники, яких можуть втратити їхні користувачі", - "admin.impact_report.title": "Наслідки", - "alert.rate_limited.message": "Спробуйте ще раз через {retry_time, time, medium}.", + "admin.impact_report.title": "Підсумки впливу", + "alert.rate_limited.message": "Спробуйте ще раз за {retry_time, time, medium}.", "alert.rate_limited.title": "Швидкість обмежена", "alert.unexpected.message": "Сталася неочікувана помилка.", "alert.unexpected.title": "Ой!", "announcement.announcement": "Оголошення", "attachments_list.unprocessed": "(не оброблено)", "audio.hide": "Сховати аудіо", - "autosuggest_hashtag.per_week": "{count} в тиждень", - "boost_modal.combo": "Ви можете натиснути {combo}, щоб пропустити це наступного разу", + "autosuggest_hashtag.per_week": "{count} на тиждень", + "boost_modal.combo": "Ви можете натиснути {combo}, щоби пропустити це наступного разу", "bundle_column_error.copy_stacktrace": "Копіювати звіт про помилку", "bundle_column_error.error.body": "Неможливо показати запитану сторінку. Це може бути спричинено помилкою у нашому коді, або через проблему сумісності з браузером.", "bundle_column_error.error.title": "О, ні!", @@ -140,7 +140,7 @@ "compose.saved.body": "Допис збережено.", "compose_form.direct_message_warning_learn_more": "Дізнатися більше", "compose_form.encryption_warning": "Дописи на Mastodon не захищені шифруванням. Не поширюйте жодну делікатну інформацію.", - "compose_form.hashtag_warning": "Цей допис не буде зображений у жодній стрічці гештеґу, оскільки він прихований. Тільки публічні дописи можуть бути знайдені за гештеґом.", + "compose_form.hashtag_warning": "Цього допису не буде під жодним гештеґом, оскільки він не є загальнодоступним. За гештеґом можна шукати лише публічні дописи.", "compose_form.lock_disclaimer": "Ваш обліковий запис не {locked}. Будь-який користувач може підписатися на вас та переглядати ваші дописи для підписників.", "compose_form.lock_disclaimer.lock": "приватний", "compose_form.placeholder": "Що у вас на думці?", @@ -151,7 +151,7 @@ "compose_form.poll.switch_to_multiple": "Дозволити вибір декількох відповідей", "compose_form.poll.switch_to_single": "Перемкнути у режим вибору однієї відповіді", "compose_form.publish": "Опублікувати", - "compose_form.publish_form": "Опублікувати", + "compose_form.publish_form": "Новий допис", "compose_form.publish_loud": "{publish}!", "compose_form.save_changes": "Зберегти зміни", "compose_form.sensitive.hide": "{count, plural, one {Позначити медіа делікатним} other {Позначити медіа делікатними}}", @@ -206,7 +206,7 @@ "dismissable_banner.explore_tags": "Ці хештеги зараз набирають популярності серед людей на цьому та інших серверах децентралізованої мережі. Хештеги, які використовуються більшою кількістю людей, мають вищий рейтинг.", "dismissable_banner.public_timeline": "Це найновіші загальнодоступні дописи від людей в соціальній мережі, на які підписані люди в {domain}.", "embed.instructions": "Вбудуйте цей допис до вашого вебсайту, скопіювавши код нижче.", - "embed.preview": "Ось як він виглядатиме:", + "embed.preview": "Ось який вигляд це матиме:", "emoji_button.activity": "Діяльність", "emoji_button.clear": "Очистити", "emoji_button.custom": "Власні", @@ -227,7 +227,7 @@ "empty_column.account_unavailable": "Профіль недоступний", "empty_column.blocks": "Ви ще не заблокували жодного користувача.", "empty_column.bookmarked_statuses": "У вас ще немає дописів у закладках. Коли ви щось додасте до закладок, воно з'явиться тут.", - "empty_column.community": "Локальна стрічка пуста. Напишіть щось, щоб розігріти народ!", + "empty_column.community": "Локальна стрічка порожня. Напишіть щось, щоб розігріти народ!", "empty_column.direct": "У вас ще немає жодних особистих згадок. Коли ви надсилаєте чи отримуєте повідомлення, воно з'явиться тут.", "empty_column.domain_blocks": "Тут поки немає прихованих доменів.", "empty_column.explore_statuses": "Нема нічого популярного. Подивіться пізніше!", @@ -240,10 +240,10 @@ "empty_column.list": "Цей список порожній. Коли його учасники додадуть нові дописи, вони з'являться тут.", "empty_column.lists": "У вас ще немає списків. Коли ви їх створите, вони з'являться тут.", "empty_column.mutes": "Ви ще не приховали жодного користувача.", - "empty_column.notifications": "У вас ще немає сповіщень. Переписуйтесь з іншими користувачами, щоб почати розмову.", + "empty_column.notifications": "У вас ще немає сповіщень. Коли інші люди почнуть взаємодіяти з вами, ви побачите їх тут.", "empty_column.public": "Тут поки нічого немає! Опублікуйте щось, або вручну підпишіться на користувачів інших серверів, щоб заповнити стрічку", "error.unexpected_crash.explanation": "Через помилку у нашому коді або несумісність браузера, ця сторінка не може бути зображена коректно.", - "error.unexpected_crash.explanation_addons": "Неможливо правильно показати цю сторінку. Ймовірно, цю помилку викликано додатком браузера або автоматичним засобом перекладу.", + "error.unexpected_crash.explanation_addons": "Неможливо правильно показати цю сторінку. Ймовірно, цю помилку спричинило розширення браузера або автоматичний засіб перекладу.", "error.unexpected_crash.next_steps": "Спробуйте перезавантажити сторінку. Якщо це не допоможе, ви все ще зможете використовувати Mastodon через інший браузер або рідний застосунок.", "error.unexpected_crash.next_steps_addons": "Спробуйте їх вимкнути та оновити сторінку. Якщо це не допомагає, ви можете використовувати Mastodon через інший браузер або окремий застосунок.", "errors.unexpected_crash.copy_stacktrace": "Скопіювати трасування стека у буфер обміну", @@ -394,7 +394,7 @@ "moved_to_account_banner.text": "Ваш обліковий запис {disabledAccount} наразі вимкнений, оскільки вас перенесено до {movedToAccount}.", "mute_modal.duration": "Тривалість", "mute_modal.hide_notifications": "Сховати сповіщення цього користувача?", - "mute_modal.indefinite": "Назавжди", + "mute_modal.indefinite": "Невизначений строк", "navigation_bar.about": "Про застосунок", "navigation_bar.advanced_interface": "Відкрити в розширеному вебінтерфейсі", "navigation_bar.blocks": "Заблоковані користувачі", @@ -428,7 +428,7 @@ "notification.follow": "{name} підписалися на вас", "notification.follow_request": "{name} відправили запит на підписку", "notification.mention": "{name} згадали вас", - "notification.own_poll": "Ваше опитування завершено", + "notification.own_poll": "Ваше опитування завершилося", "notification.poll": "Опитування, у якому ви голосували, скінчилося", "notification.reblog": "{name} поширює ваш допис", "notification.status": "{name} щойно дописує", @@ -480,7 +480,7 @@ "onboarding.follows.title": "Персоналізуйте домашню стрічку", "onboarding.share.lead": "Розкажіть людям про те, як вони можуть знайти вас на Mastodon!", "onboarding.share.message": "Я {username} на #Mastodon! Стежте за мною на {url}", - "onboarding.share.next_steps": "Можливі наступні кроки:", + "onboarding.share.next_steps": "Можливі такі кроки:", "onboarding.share.title": "Поділитися своїм профілем", "onboarding.start.lead": "Тепер ви — частина Mastodon, унікальної децентралізованої платформи соціальних медіа, де ви, а не алгоритми керують вашими вподобаннями. Розпочнімо роботу:", "onboarding.start.skip": "Хочете пропустити?", @@ -694,7 +694,7 @@ "units.short.thousand": "{count} тис", "upload_area.title": "Перетягніть сюди, щоб завантажити", "upload_button.label": "Додати зображення, відео або аудіо", - "upload_error.limit": "Ліміт завантаження файлів перевищено.", + "upload_error.limit": "Ви перевищили ліміт завантаження файлів.", "upload_error.poll": "Не можна завантажувати файли до опитувань.", "upload_form.audio_description": "Опишіть для людей із вадами слуху", "upload_form.description": "Опишіть для людей з вадами зору", @@ -713,7 +713,7 @@ "upload_modal.hint": "Клацніть або перетягніть коло на превʼю, щоб обрати точку, яку буде завжди видно на мініатюрах.", "upload_modal.preparing_ocr": "Підготовка OCR…", "upload_modal.preview_label": "Переглянути ({ratio})", - "upload_progress.label": "Завантаження...", + "upload_progress.label": "Вивантаження...", "upload_progress.processing": "Обробка…", "username.taken": "Це ім'я користувача вже зайнято. Спробуйте інше", "video.close": "Закрити відео", diff --git a/config/locales/simple_form.es-MX.yml b/config/locales/simple_form.es-MX.yml index 0ed471a1f8..932ed6c59a 100644 --- a/config/locales/simple_form.es-MX.yml +++ b/config/locales/simple_form.es-MX.yml @@ -323,7 +323,7 @@ es-MX: url: URL de Endpoint 'no': 'No' not_recommended: No recomendado - overridden: Sobrescrito + overridden: Reemplazado recommended: Recomendado required: mark: "*" From 9d1c3d06783b9f7707e7e57d3d75553a02e8a9f5 Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 10 Oct 2023 11:35:32 +0200 Subject: [PATCH 10/58] Fix scroll position in thread view reseting when closing a modal (#27350) --- app/javascript/mastodon/features/status/index.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/mastodon/features/status/index.jsx b/app/javascript/mastodon/features/status/index.jsx index 39823268b2..d6a6deeb76 100644 --- a/app/javascript/mastodon/features/status/index.jsx +++ b/app/javascript/mastodon/features/status/index.jsx @@ -619,7 +619,7 @@ class Status extends ImmutablePureComponent { shouldUpdateScroll = (prevRouterProps, { location }) => { // Do not change scroll when opening a modal - if (location.state?.mastodonModalKey && location.state?.mastodonModalKey !== prevRouterProps?.location?.state?.mastodonModalKey) { + if (location.state?.mastodonModalKey !== prevRouterProps?.location?.state?.mastodonModalKey) { return false; } From 27e84c069112a3d2abfad947642457cc997a261a Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 10 Oct 2023 16:00:50 +0200 Subject: [PATCH 11/58] Fix duplicate reports being sent when reporting some remote posts (#27355) --- app/services/report_service.rb | 2 +- spec/services/report_service_spec.rb | 21 ++++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/app/services/report_service.rb b/app/services/report_service.rb index 22d788d543..b4015d1cbf 100644 --- a/app/services/report_service.rb +++ b/app/services/report_service.rb @@ -57,7 +57,7 @@ class ReportService < BaseService def forward_to_replied_to! # Send report to servers to which the account was replying to, so they also have a chance to act - inbox_urls = Account.remote.where(domain: forward_to_domains).where(id: Status.where(id: reported_status_ids).where.not(in_reply_to_account_id: nil).select(:in_reply_to_account_id)).inboxes - [@target_account.inbox_url] + inbox_urls = Account.remote.where(domain: forward_to_domains).where(id: Status.where(id: reported_status_ids).where.not(in_reply_to_account_id: nil).select(:in_reply_to_account_id)).inboxes - [@target_account.inbox_url, @target_account.shared_inbox_url] inbox_urls.each do |inbox_url| ActivityPub::DeliveryWorker.perform_async(payload, some_local_account.id, inbox_url) diff --git a/spec/services/report_service_spec.rb b/spec/services/report_service_spec.rb index 616368bf48..d3bcd5d31c 100644 --- a/spec/services/report_service_spec.rb +++ b/spec/services/report_service_spec.rb @@ -36,7 +36,7 @@ RSpec.describe ReportService, type: :service do expect(report.uri).to_not be_nil end - context 'when reporting a reply' do + context 'when reporting a reply on a different remote server' do let(:remote_thread_account) { Fabricate(:account, domain: 'foo.com', protocol: :activitypub, inbox_url: 'http://foo.com/inbox') } let(:reported_status) { Fabricate(:status, account: remote_account, thread: Fabricate(:status, account: remote_thread_account)) } @@ -67,6 +67,25 @@ RSpec.describe ReportService, type: :service do end end end + + context 'when reporting a reply on the same remote server as the person being replied-to' do + let(:remote_thread_account) { Fabricate(:account, domain: 'example.com', protocol: :activitypub, inbox_url: 'http://example.com/inbox') } + let(:reported_status) { Fabricate(:status, account: remote_account, thread: Fabricate(:status, account: remote_thread_account)) } + + context 'when forward_to_domains includes both the replied-to domain and the origin domain' do + it 'sends ActivityPub payload only once' do + subject.call(source_account, remote_account, status_ids: [reported_status.id], forward: forward, forward_to_domains: [remote_account.domain]) + expect(a_request(:post, 'http://example.com/inbox')).to have_been_made.once + end + end + + context 'when forward_to_domains does not include the replied-to domain' do + it 'sends ActivityPub payload only once' do + subject.call(source_account, remote_account, status_ids: [reported_status.id], forward: forward) + expect(a_request(:post, 'http://example.com/inbox')).to have_been_made.once + end + end + end end context 'when forward is false' do From 74dd325112ddccdad6be2d3191ffb991bdafd1be Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 10 Oct 2023 18:23:31 +0200 Subject: [PATCH 12/58] Fix duplicate reports being sent when reporting some remote posts (port to v4.2.1) (#27356) --- CHANGELOG.md | 1 + app/services/report_service.rb | 2 +- spec/services/report_service_spec.rb | 21 ++++++++++++++++++++- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6eebe5c85d..f9303f0115 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ All notable changes to this project will be documented in this file. ### Fixed +- Fix duplicate reports being sent when reporting some remote posts ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27355)) - Fix clicking on already-opened thread post scrolling to the top of the thread ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27331), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/27338), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/27350)) - Fix some remote posts getting truncated ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27307)) - Fix some cases of infinite scroll code trying to fetch inaccessible posts in a loop ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27286)) diff --git a/app/services/report_service.rb b/app/services/report_service.rb index 22d788d543..b4015d1cbf 100644 --- a/app/services/report_service.rb +++ b/app/services/report_service.rb @@ -57,7 +57,7 @@ class ReportService < BaseService def forward_to_replied_to! # Send report to servers to which the account was replying to, so they also have a chance to act - inbox_urls = Account.remote.where(domain: forward_to_domains).where(id: Status.where(id: reported_status_ids).where.not(in_reply_to_account_id: nil).select(:in_reply_to_account_id)).inboxes - [@target_account.inbox_url] + inbox_urls = Account.remote.where(domain: forward_to_domains).where(id: Status.where(id: reported_status_ids).where.not(in_reply_to_account_id: nil).select(:in_reply_to_account_id)).inboxes - [@target_account.inbox_url, @target_account.shared_inbox_url] inbox_urls.each do |inbox_url| ActivityPub::DeliveryWorker.perform_async(payload, some_local_account.id, inbox_url) diff --git a/spec/services/report_service_spec.rb b/spec/services/report_service_spec.rb index 616368bf48..d3bcd5d31c 100644 --- a/spec/services/report_service_spec.rb +++ b/spec/services/report_service_spec.rb @@ -36,7 +36,7 @@ RSpec.describe ReportService, type: :service do expect(report.uri).to_not be_nil end - context 'when reporting a reply' do + context 'when reporting a reply on a different remote server' do let(:remote_thread_account) { Fabricate(:account, domain: 'foo.com', protocol: :activitypub, inbox_url: 'http://foo.com/inbox') } let(:reported_status) { Fabricate(:status, account: remote_account, thread: Fabricate(:status, account: remote_thread_account)) } @@ -67,6 +67,25 @@ RSpec.describe ReportService, type: :service do end end end + + context 'when reporting a reply on the same remote server as the person being replied-to' do + let(:remote_thread_account) { Fabricate(:account, domain: 'example.com', protocol: :activitypub, inbox_url: 'http://example.com/inbox') } + let(:reported_status) { Fabricate(:status, account: remote_account, thread: Fabricate(:status, account: remote_thread_account)) } + + context 'when forward_to_domains includes both the replied-to domain and the origin domain' do + it 'sends ActivityPub payload only once' do + subject.call(source_account, remote_account, status_ids: [reported_status.id], forward: forward, forward_to_domains: [remote_account.domain]) + expect(a_request(:post, 'http://example.com/inbox')).to have_been_made.once + end + end + + context 'when forward_to_domains does not include the replied-to domain' do + it 'sends ActivityPub payload only once' do + subject.call(source_account, remote_account, status_ids: [reported_status.id], forward: forward) + expect(a_request(:post, 'http://example.com/inbox')).to have_been_made.once + end + end + end end context 'when forward is false' do From 7d2cd7195bfc53a3bf2b57359fcfcb570813fe3d Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 11 Oct 2023 15:14:18 +0200 Subject: [PATCH 13/58] Add variable delay before link verification of remote account links (#27351) --- app/services/update_account_service.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/services/update_account_service.rb b/app/services/update_account_service.rb index 4604d71b2b..a98f4d31e4 100644 --- a/app/services/update_account_service.rb +++ b/app/services/update_account_service.rb @@ -28,7 +28,13 @@ class UpdateAccountService < BaseService end def check_links(account) - VerifyAccountLinksWorker.perform_async(account.id) if account.fields.any?(&:requires_verification?) + return unless account.fields.any?(&:requires_verification?) + + if account.local? + VerifyAccountLinksWorker.perform_async(account.id) + else + VerifyAccountLinksWorker.perform_in(rand(10.minutes.to_i), account.id) + end end def process_hashtags(account) From 66becf9a1e8d44c5579e777a546421a54d15dbb0 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Wed, 11 Oct 2023 09:58:33 -0400 Subject: [PATCH 14/58] Fix haml-lint `InstanceVariables` rule for admin/reports/actions (#27339) --- .haml-lint_todo.yml | 7 +++---- app/views/admin/reports/_actions.html.haml | 8 ++++---- app/views/admin/reports/show.html.haml | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/.haml-lint_todo.yml b/.haml-lint_todo.yml index 69937c4c48..4a141b2e1d 100644 --- a/.haml-lint_todo.yml +++ b/.haml-lint_todo.yml @@ -1,13 +1,13 @@ # This configuration was generated by # `haml-lint --auto-gen-config` -# on 2023-10-03 08:32:28 -0400 using Haml-Lint version 0.51.0. +# on 2023-10-09 10:24:59 -0400 using Haml-Lint version 0.51.0. # The point is for the user to remove these configuration records # one by one as the lints are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of Haml-Lint, may require this file to be generated again. linters: - # Offense count: 944 + # Offense count: 945 LineLength: enabled: false @@ -26,10 +26,9 @@ linters: - 'app/views/admin/reports/show.html.haml' - 'app/views/disputes/strikes/show.html.haml' - # Offense count: 15 + # Offense count: 11 InstanceVariables: exclude: - - 'app/views/admin/reports/_actions.html.haml' - 'app/views/auth/registrations/_status.html.haml' - 'app/views/auth/sessions/two_factor/_otp_authentication_form.html.haml' - 'app/views/relationships/_account.html.haml' diff --git a/app/views/admin/reports/_actions.html.haml b/app/views/admin/reports/_actions.html.haml index aad4416257..da9ac89315 100644 --- a/app/views/admin/reports/_actions.html.haml +++ b/app/views/admin/reports/_actions.html.haml @@ -1,11 +1,11 @@ -= form_tag preview_admin_report_actions_path(@report), method: :post do += form_tag preview_admin_report_actions_path(report), method: :post do .report-actions .report-actions__item .report-actions__item__button - = link_to t('admin.reports.mark_as_resolved'), resolve_admin_report_path(@report), method: :post, class: 'button' + = link_to t('admin.reports.mark_as_resolved'), resolve_admin_report_path(report), method: :post, class: 'button' .report-actions__item__description = t('admin.reports.actions.resolve_description_html') - - if @statuses.any? { |status| (status.with_media? || status.with_preview_card?) && !status.discarded? } + - if statuses.any? { |status| (status.with_media? || status.with_preview_card?) && !status.discarded? } .report-actions__item .report-actions__item__button = button_tag t('admin.reports.mark_as_sensitive'), name: :mark_as_sensitive, class: 'button' @@ -28,6 +28,6 @@ = t('admin.reports.actions.suspend_description_html') .report-actions__item .report-actions__item__button - = link_to t('admin.accounts.custom'), new_admin_account_action_path(@report.target_account_id, report_id: @report.id), class: 'button' + = link_to t('admin.accounts.custom'), new_admin_account_action_path(report.target_account_id, report_id: report.id), class: 'button' .report-actions__item__description = t('admin.reports.actions.other_description_html') diff --git a/app/views/admin/reports/show.html.haml b/app/views/admin/reports/show.html.haml index 2508bc2b5b..41ce73cfcf 100644 --- a/app/views/admin/reports/show.html.haml +++ b/app/views/admin/reports/show.html.haml @@ -179,7 +179,7 @@ %p#actions= t(@report.target_account.local? ? 'admin.reports.actions_description_html' : 'admin.reports.actions_description_remote_html') - = render partial: 'admin/reports/actions' + = render partial: 'admin/reports/actions', locals: { report: @report, statuses: @statuses } - unless @action_logs.empty? %hr.spacer/ From 0111e48893f1f29568ea86ae34ca82fa23d6ae0a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 11 Oct 2023 16:02:51 +0200 Subject: [PATCH 15/58] Update dependency sidekiq to v6.5.12 (#27358) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index affe1bf7f2..8dd61ae5e9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -671,7 +671,7 @@ GEM rubyzip (>= 1.2.2, < 3.0) websocket (~> 1.0) semantic_range (3.0.0) - sidekiq (6.5.11) + sidekiq (6.5.12) connection_pool (>= 2.2.5, < 3) rack (~> 2.0) redis (>= 4.5.0, < 5) From f9abe700e73df76963aa0f74a87e518ddc5c4584 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Wed, 11 Oct 2023 10:20:26 -0400 Subject: [PATCH 16/58] Fix haml-lint `InstanceVariables` rule for auth/registrations/status (#27341) --- .haml-lint_todo.yml | 5 ++--- app/views/auth/registrations/_status.html.haml | 18 +++++++++--------- app/views/auth/registrations/edit.html.haml | 2 +- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/.haml-lint_todo.yml b/.haml-lint_todo.yml index 4a141b2e1d..cfa39a24e2 100644 --- a/.haml-lint_todo.yml +++ b/.haml-lint_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `haml-lint --auto-gen-config` -# on 2023-10-09 10:24:59 -0400 using Haml-Lint version 0.51.0. +# on 2023-10-11 10:00:39 -0400 using Haml-Lint version 0.51.0. # The point is for the user to remove these configuration records # one by one as the lints are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -26,10 +26,9 @@ linters: - 'app/views/admin/reports/show.html.haml' - 'app/views/disputes/strikes/show.html.haml' - # Offense count: 11 + # Offense count: 2 InstanceVariables: exclude: - - 'app/views/auth/registrations/_status.html.haml' - 'app/views/auth/sessions/two_factor/_otp_authentication_form.html.haml' - 'app/views/relationships/_account.html.haml' diff --git a/app/views/auth/registrations/_status.html.haml b/app/views/auth/registrations/_status.html.haml index 759bbc41c0..8f44eee015 100644 --- a/app/views/auth/registrations/_status.html.haml +++ b/app/views/auth/registrations/_status.html.haml @@ -1,30 +1,30 @@ -- if !@user.confirmed? +- if !user.confirmed? .flash-message.warning = t('auth.status.confirming') = link_to t('auth.didnt_get_confirmation'), new_user_confirmation_path -- elsif !@user.approved? +- elsif !user.approved? .flash-message.warning = t('auth.status.pending') -- elsif @user.account.moved_to_account_id.present? +- elsif user.account.moved_to_account_id.present? .flash-message.warning - = t('auth.status.redirecting_to', acct: @user.account.moved_to_account.pretty_acct) + = t('auth.status.redirecting_to', acct: user.account.moved_to_account.pretty_acct) = link_to t('migrations.cancel'), settings_migration_path %h3= t('auth.status.account_status') %p.hint - - if @user.account.suspended? + - if user.account.suspended? %span.negative-hint= t('user_mailer.warning.explanation.suspend') - - elsif @user.disabled? + - elsif user.disabled? %span.negative-hint= t('user_mailer.warning.explanation.disable') - - elsif @user.account.silenced? + - elsif user.account.silenced? %span.warning-hint= t('user_mailer.warning.explanation.silence') - else %span.positive-hint= t('auth.status.functional') -= render partial: 'account_warning', collection: @strikes += render partial: 'account_warning', collection: strikes -- if @user.account.strikes.exists? +- if user.account.strikes.exists? %hr.spacer/ %p.muted-hint diff --git a/app/views/auth/registrations/edit.html.haml b/app/views/auth/registrations/edit.html.haml index 3e9b0cb6bd..908119a21a 100644 --- a/app/views/auth/registrations/edit.html.haml +++ b/app/views/auth/registrations/edit.html.haml @@ -1,7 +1,7 @@ - content_for :page_title do = t('settings.account_settings') -= render 'status' += render partial: 'status', locals: { user: @user, strikes: @strikes } %h3= t('auth.security') From 1afb7f41049ebcea9d92a3ec8953c5eba708725a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 11 Oct 2023 16:21:59 +0200 Subject: [PATCH 17/58] Update dependency lograge to v0.14.0 (#27363) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 8dd61ae5e9..1533484646 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -412,12 +412,12 @@ GEM llhttp-ffi (0.4.0) ffi-compiler (~> 1.0) rake (~> 13.0) - lograge (0.13.0) + lograge (0.14.0) actionpack (>= 4) activesupport (>= 4) railties (>= 4) request_store (~> 1.0) - loofah (2.21.3) + loofah (2.21.4) crass (~> 1.0.2) nokogiri (>= 1.12.0) mail (2.8.1) @@ -440,7 +440,7 @@ GEM mime-types-data (3.2023.0808) mini_mime (1.1.5) mini_portile2 (2.8.4) - minitest (5.19.0) + minitest (5.20.0) msgpack (1.7.1) multi_json (1.15.0) multipart-post (2.3.0) @@ -554,7 +554,7 @@ GEM actionpack (>= 5.0.1.rc1) actionview (>= 5.0.1.rc1) activesupport (>= 5.0.1.rc1) - rails-dom-testing (2.1.1) + rails-dom-testing (2.2.0) activesupport (>= 5.0.0) minitest nokogiri (>= 1.6) @@ -789,7 +789,7 @@ GEM xorcist (1.1.3) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.6.11) + zeitwerk (2.6.12) PLATFORMS ruby From 608cd6623935e1846e315d76a6cf08df866fa659 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Hodierne?= Date: Wed, 11 Oct 2023 16:24:28 +0200 Subject: [PATCH 18/58] Update README requirements from node 14 to node 16 (#27369) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8d6d344797..ce9b5cfbdc 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ Mastodon acts as an OAuth2 provider, so 3rd party apps can use the REST and Stre - **PostgreSQL** 9.5+ - **Redis** 4+ - **Ruby** 2.7+ -- **Node.js** 14+ +- **Node.js** 16+ The repository includes deployment configurations for **Docker and docker-compose** as well as specific platforms like **Heroku**, **Scalingo**, and **Nanobox**. For Helm charts, reference the [mastodon/chart repository](https://github.com/mastodon/chart). The [**standalone** installation guide](https://docs.joinmastodon.org/admin/install/) is available in the documentation. From d0a3331caafe61327350ef4b4eddc27271302509 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 11 Oct 2023 16:36:50 +0200 Subject: [PATCH 19/58] Update dependency rubocop to v1.57.0 (#27371) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 1533484646..fa84bdc5e1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -493,7 +493,7 @@ GEM orm_adapter (0.5.0) ox (2.14.17) parallel (1.23.0) - parser (3.2.2.3) + parser (3.2.2.4) ast (~> 2.4.1) racc parslet (2.0.0) @@ -583,7 +583,7 @@ GEM redis (>= 4) redlock (1.3.2) redis (>= 3.0.0, < 6.0) - regexp_parser (2.8.1) + regexp_parser (2.8.2) request_store (1.5.1) rack (>= 1.4) responders (3.1.0) @@ -620,12 +620,12 @@ GEM sidekiq (>= 5, < 8) rspec-support (3.12.1) rspec_chunked (0.6) - rubocop (1.56.4) + rubocop (1.57.0) base64 (~> 0.1.1) json (~> 2.3) language_server-protocol (>= 3.17.0) parallel (~> 1.10) - parser (>= 3.2.2.3) + parser (>= 3.2.2.4) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 1.8, < 3.0) rexml (>= 3.2.5, < 4.0) From f1ae72ba4622e48809a9f5b4692efb122d6b3c85 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 11 Oct 2023 16:37:01 +0200 Subject: [PATCH 20/58] New Crowdin Translations (automated) (#27364) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/fi.json | 50 +++++++++++----------- app/javascript/mastodon/locales/gd.json | 2 +- app/javascript/mastodon/locales/ja.json | 2 +- app/javascript/mastodon/locales/oc.json | 37 ++++++++++++++++ app/javascript/mastodon/locales/zh-TW.json | 2 +- config/locales/activerecord.fi.yml | 2 +- config/locales/fi.yml | 20 ++++----- config/locales/simple_form.fi.yml | 10 ++--- 8 files changed, 81 insertions(+), 44 deletions(-) diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json index 87d7c90c41..cef2250339 100644 --- a/app/javascript/mastodon/locales/fi.json +++ b/app/javascript/mastodon/locales/fi.json @@ -1,6 +1,6 @@ { "about.blocks": "Valvotut palvelimet", - "about.contact": "Yhteydenotto:", + "about.contact": "Ota yhteyttä:", "about.disclaimer": "Mastodon on vapaa avoimen lähdekoodin ohjelmisto ja Mastodon gGmbH:n tavaramerkki.", "about.domain_blocks.no_reason_available": "Syytä ei ole ilmoitettu", "about.domain_blocks.preamble": "Mastodonin avulla voidaan yleensä tarkastella minkä tahansa fediversumiin kuuluvan palvelimen sisältöä ja vuorovaikuttaa eri palvelinten käyttäjien kanssa. Nämä ovat tälle palvelimelle määritetyt poikkeukset.", @@ -31,10 +31,10 @@ "account.featured_tags.last_status_never": "Ei julkaisuja", "account.featured_tags.title": "Käyttäjän {name} esille nostetut aihetunnisteet", "account.follow": "Seuraa", - "account.followers": "seuraaja(t)", + "account.followers": "Seuraajat", "account.followers.empty": "Kukaan ei seuraa tätä käyttäjää vielä.", "account.followers_counter": "{count, plural, one {{counter} seuraaja} other {{counter} seuraajaa}}", - "account.following": "Seurataan", + "account.following": "Seuratut", "account.following_counter": "{count, plural, one {{counter} seurattu} other {{counter} seurattua}}", "account.follows.empty": "Tämä käyttäjä ei vielä seuraa ketään.", "account.follows_you": "Seuraa sinua", @@ -194,7 +194,7 @@ "copypaste.copied": "Kopioitu", "copypaste.copy_to_clipboard": "Kopioi leikepöydälle", "directory.federated": "Koko tunnettu fediversumi", - "directory.local": "Vain palvelusta {domain}", + "directory.local": "Vain palvelimelta {domain}", "directory.new_arrivals": "Äskettäin saapuneet", "directory.recently_active": "Hiljattain aktiiviset", "disabled_account_banner.account_settings": "Tilin asetukset", @@ -266,7 +266,7 @@ "filter_modal.select_filter.context_mismatch": "ei sovellu tähän kontekstiin", "filter_modal.select_filter.expired": "vanhentunut", "filter_modal.select_filter.prompt_new": "Uusi luokka: {name}", - "filter_modal.select_filter.search": "Etsi tai luo", + "filter_modal.select_filter.search": "Hae tai luo", "filter_modal.select_filter.subtitle": "Käytä olemassa olevaa luokkaa tai luo uusi", "filter_modal.select_filter.title": "Suodata tämä julkaisu", "filter_modal.title.status": "Suodata julkaisu", @@ -336,9 +336,9 @@ "keyboard_shortcuts.blocked": "Avaa estettyjen käyttäjien luettelo", "keyboard_shortcuts.boost": "Tehosta julkaisua", "keyboard_shortcuts.column": "Kohdista sarakkeeseen", - "keyboard_shortcuts.compose": "siirry tekstinsyöttöön", + "keyboard_shortcuts.compose": "Kohdista kirjoituskenttään", "keyboard_shortcuts.description": "Kuvaus", - "keyboard_shortcuts.direct": "avataksesi yksityisten mainintojen sarakkeen", + "keyboard_shortcuts.direct": "Avaa yksityisten mainintojen sarake", "keyboard_shortcuts.down": "Siirry listassa alaspäin", "keyboard_shortcuts.enter": "Avaa julkaisu", "keyboard_shortcuts.favourite": "Lisää julkaisu suosikkeihin", @@ -347,22 +347,22 @@ "keyboard_shortcuts.heading": "Pikanäppäimet", "keyboard_shortcuts.home": "Avaa kotiaikajana", "keyboard_shortcuts.hotkey": "Pikanäppäin", - "keyboard_shortcuts.legend": "Näytä tämä selite", + "keyboard_shortcuts.legend": "Näytä tämä ohje", "keyboard_shortcuts.local": "Avaa paikallinen aikajana", - "keyboard_shortcuts.mention": "Mainitse julkaisija", - "keyboard_shortcuts.muted": "Avaa lista mykistetyistä käyttäjistä", + "keyboard_shortcuts.mention": "Mainitse kirjoittaja", + "keyboard_shortcuts.muted": "Avaa mykistettyjen käyttäjien luettelo", "keyboard_shortcuts.my_profile": "Avaa profiilisi", - "keyboard_shortcuts.notifications": "Avaa ilmoitukset-valikko", + "keyboard_shortcuts.notifications": "Avaa ilmoitussarake", "keyboard_shortcuts.open_media": "Avaa media", "keyboard_shortcuts.pinned": "Avaa kiinnitettyjen julkaisujen luettelo", "keyboard_shortcuts.profile": "Avaa kirjoittajan profiili", "keyboard_shortcuts.reply": "Vastaa julkaisuun", "keyboard_shortcuts.requests": "Avaa seuraamispyyntöjen luettelo", - "keyboard_shortcuts.search": "siirry hakukenttään", + "keyboard_shortcuts.search": "Kohdista hakukenttään", "keyboard_shortcuts.spoilers": "Näytä/piilota sisältövaroituskenttä", - "keyboard_shortcuts.start": "avaa \"Aloitus\"", - "keyboard_shortcuts.toggle_hidden": "näytä/piilota sisältövaroituksella merkitty teksti", - "keyboard_shortcuts.toggle_sensitivity": "näytä/piilota media", + "keyboard_shortcuts.start": "Avaa Näin pääset alkuun -sarake", + "keyboard_shortcuts.toggle_hidden": "Näytä/piilota sisältövaroituksella merkitty teksti", + "keyboard_shortcuts.toggle_sensitivity": "Näytä/piilota media", "keyboard_shortcuts.toot": "Luo uusi julkaisu", "keyboard_shortcuts.unfocus": "Poistu teksti-/hakukentästä", "keyboard_shortcuts.up": "Siirry listassa ylöspäin", @@ -419,7 +419,7 @@ "navigation_bar.pins": "Kiinnitetyt julkaisut", "navigation_bar.preferences": "Asetukset", "navigation_bar.public_timeline": "Yleinen aikajana", - "navigation_bar.search": "Haku", + "navigation_bar.search": "Hae", "navigation_bar.security": "Turvallisuus", "not_signed_in_indicator.not_signed_in": "Sinun on kirjauduttava sisään käyttääksesi resurssia.", "notification.admin.report": "{name} teki ilmoituksen käytäjästä {target}", @@ -475,11 +475,11 @@ "onboarding.actions.go_to_explore": "Siirry suosituimpien aiheiden syötteeseen", "onboarding.actions.go_to_home": "Siirry kotisyötteeseeni", "onboarding.compose.template": "Tervehdys #Mastodon!", - "onboarding.follows.empty": "Valitettavasti tuloksia ei voida näyttää juuri nyt. Voit kokeilla hakua tai selata tutustumissivua löytääksesi seurattavaa, tai yrittää myöhemmin uudelleen.", + "onboarding.follows.empty": "Valitettavasti tuloksia ei voida näyttää juuri nyt. Voit kokeilla hakua tai selata tutustumissivua löytääksesi seurattavaa tai yrittää myöhemmin uudelleen.", "onboarding.follows.lead": "Kokoat oman kotisyötteesi itse. Mitä enemmän ihmisiä seuraat, sitä aktiivisempi ja kiinnostavampi syöte on. Nämä profiilit voivat olla alkuun hyvä lähtökohta — voit aina lopettaa niiden seuraamisen myöhemmin!", "onboarding.follows.title": "Mukauta kotisyötettäsi", "onboarding.share.lead": "Kerro ihmisille, kuinka he voivat löytää sinut Mastodonista!", - "onboarding.share.message": "Olen {username} #Mastodon'issa! Seuraa minua osoitteessa {url}", + "onboarding.share.message": "Olen {username} #Mastodon⁠issa! Seuraa minua osoitteessa {url}", "onboarding.share.next_steps": "Mahdolliset seuraavat vaiheet:", "onboarding.share.title": "Jaa profiilisi", "onboarding.start.lead": "Uusi Mastodon-tilisi on nyt valmiina käyttöön. Kyseessä on ainutlaatuinen, hajautettu sosiaalisen median alusta, jolla sinä itse – algoritmin sijaan – määrität käyttökokemuksesi. Näin hyödyt Mastodonista eniten:", @@ -584,17 +584,17 @@ "report_notification.open": "Avaa raportti", "search.no_recent_searches": "Ei viimeaikaisia hakuja", "search.placeholder": "Hae", - "search.quick_action.account_search": "Profiilit, jotka vastaavat hakua {x}", - "search.quick_action.go_to_account": "Avaa profiili {x}", + "search.quick_action.account_search": "Profiilit haulla {x}", + "search.quick_action.go_to_account": "Siirry profiiliin {x}", "search.quick_action.go_to_hashtag": "Siirry aihetunnisteeseen {x}", "search.quick_action.open_url": "Avaa URL-osoite Mastodonissa", "search.quick_action.status_search": "Julkaisut haulla {x}", - "search.search_or_paste": "Etsi tai kirjoita URL-osoite", + "search.search_or_paste": "Hae tai kirjoita URL-osoite", "search_popout.full_text_search_disabled_message": "Ei saatavilla palvelimella {domain}.", "search_popout.language_code": "ISO-kielikoodi", "search_popout.options": "Haun asetukset", "search_popout.quick_actions": "Pikatoiminnot", - "search_popout.recent": "Viime haut", + "search_popout.recent": "Viimeaikaiset haut", "search_popout.specific_date": "tietty päivämäärä", "search_popout.user": "käyttäjä", "search_results.accounts": "Profiilit", @@ -637,7 +637,7 @@ "status.history.created": "{name} luotu {date}", "status.history.edited": "{name} muokkasi {date}", "status.load_more": "Lataa lisää", - "status.media.open": "Napsauta avataksesi", + "status.media.open": "Avaa napsauttamalla", "status.media.show": "Napsauta näyttääksesi", "status.media_hidden": "Media piilotettu", "status.mention": "Mainitse @{name}", @@ -654,7 +654,7 @@ "status.reblogs.empty": "Kukaan ei ole vielä tehostanut tätä julkaisua. Kun joku tekee niin, tulee hän tähän näkyviin.", "status.redraft": "Poista ja palauta muokattavaksi", "status.remove_bookmark": "Poista kirjanmerkki", - "status.replied_to": "Vastattu {name}", + "status.replied_to": "Vastaus käyttäjälle {name}", "status.reply": "Vastaa", "status.replyAll": "Vastaa ketjuun", "status.report": "Raportoi @{name}", @@ -715,7 +715,7 @@ "upload_modal.preview_label": "Esikatselu ({ratio})", "upload_progress.label": "Ladataan...", "upload_progress.processing": "Käsitellään…", - "username.taken": "Käyttäjätunnus on jo varattu. Kokeile toista", + "username.taken": "Käyttäjänimi on jo varattu. Kokeile toista", "video.close": "Sulje video", "video.download": "Lataa tiedosto", "video.exit_fullscreen": "Poistu koko näytön tilasta", diff --git a/app/javascript/mastodon/locales/gd.json b/app/javascript/mastodon/locales/gd.json index ea1ce59e84..4f485cfc55 100644 --- a/app/javascript/mastodon/locales/gd.json +++ b/app/javascript/mastodon/locales/gd.json @@ -7,7 +7,7 @@ "about.domain_blocks.silenced.explanation": "San fharsaingeachd, chan fhaic thu pròifilean agus susbaint an fhrithealaiche seo ach ma nì thu lorg no ma tha thu ga leantainn.", "about.domain_blocks.silenced.title": "Cuingichte", "about.domain_blocks.suspended.explanation": "Cha dèid dàta sam bith on fhrithealaiche seo a phròiseasadh, a stòradh no iomlaid agus chan urrainn do na cleachdaichean on fhrithealaiche sin conaltradh no eadar-ghnìomh a ghabhail an-seo.", - "about.domain_blocks.suspended.title": "’Na dhàil", + "about.domain_blocks.suspended.title": "À rèim", "about.not_available": "Cha deach am fiosrachadh seo a sholar air an fhrithealaiche seo.", "about.powered_by": "Lìonra sòisealta sgaoilte le cumhachd {mastodon}", "about.rules": "Riaghailtean an fhrithealaiche", diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json index 0bf0a96a27..0c8e417b91 100644 --- a/app/javascript/mastodon/locales/ja.json +++ b/app/javascript/mastodon/locales/ja.json @@ -250,7 +250,7 @@ "errors.unexpected_crash.report_issue": "問題を報告", "explore.search_results": "検索結果", "explore.suggested_follows": "ユーザー", - "explore.title": "エクスプローラー", + "explore.title": "探索する", "explore.trending_links": "ニュース", "explore.trending_statuses": "投稿", "explore.trending_tags": "ハッシュタグ", diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json index 1a22194554..6b82654500 100644 --- a/app/javascript/mastodon/locales/oc.json +++ b/app/javascript/mastodon/locales/oc.json @@ -65,6 +65,7 @@ "account.unendorse": "Mostrar pas pel perfil", "account.unfollow": "Quitar de sègre", "account.unmute": "Quitar de rescondre @{name}", + "account.unmute_notifications_short": "Restablir las notificacions", "account.unmute_short": "Tornar afichar", "account_note.placeholder": "Clicar per ajustar una nòta", "admin.dashboard.retention.average": "Mejana", @@ -97,6 +98,8 @@ "column.direct": "Mencions privadas", "column.directory": "Percórrer los perfils", "column.domain_blocks": "Domenis resconduts", + "column.favourites": "Favorits", + "column.firehose": "Tuts en dirèct", "column.follow_requests": "Demandas d’abonament", "column.home": "Acuèlh", "column.lists": "Listas", @@ -117,6 +120,7 @@ "community.column_settings.remote_only": "Sonque alonhat", "compose.language.change": "Cambiar de lenga", "compose.language.search": "Recercar de lengas...", + "compose.published.body": "Tut publicat.", "compose.published.open": "Dobrir", "compose.saved.body": "Publicacion enregistrada.", "compose_form.direct_message_warning_learn_more": "Ne saber mai", @@ -170,6 +174,7 @@ "conversation.open": "Veire la conversacion", "conversation.with": "Amb {names}", "copypaste.copied": "Copiat", + "copypaste.copy_to_clipboard": "Copiar al quichapapièr", "directory.federated": "Del fediverse conegut", "directory.local": "Solament de {domain}", "directory.new_arrivals": "Nòus-venguts", @@ -220,6 +225,7 @@ "errors.unexpected_crash.copy_stacktrace": "Copiar las traças al quichapapièrs", "errors.unexpected_crash.report_issue": "Senhalar un problèma", "explore.search_results": "Resultats de recèrca", + "explore.suggested_follows": "Personas", "explore.title": "Explorar", "explore.trending_links": "Novèlas", "explore.trending_statuses": "Publicacions", @@ -234,6 +240,7 @@ "filter_modal.select_filter.search": "Cercar o crear", "filter_modal.select_filter.title": "Filtrar aquesta publicacion", "filter_modal.title.status": "Filtrar una publicacion", + "firehose.local": "Aqueste servidor", "follow_request.authorize": "Acceptar", "follow_request.reject": "Regetar", "follow_requests.unlocked_explanation": "Encara que vòstre compte siasque pas verrolhat, la còla de {domain} pensèt que volriatz benlèu repassar las demandas d’abonament d’aquestes comptes.", @@ -257,12 +264,19 @@ "hashtag.column_settings.tag_mode.any": "Un d’aquestes", "hashtag.column_settings.tag_mode.none": "Cap d’aquestes", "hashtag.column_settings.tag_toggle": "Inclure las etiquetas suplementàrias dins aquesta colomna", + "hashtag.counter_by_accounts": "{count, plural, one {{counter} participant} other {{counter} participants}}", + "hashtag.counter_by_uses": "{count, plural, one {{counter} tut} other {{counter} tuts}}", + "hashtag.counter_by_uses_today": "{count, plural, one {{counter} tut} other {{counter} tuts}} uèi", "hashtag.follow": "Sègre l’etiqueta", "hashtag.unfollow": "Quitar de sègre l’etiqueta", + "hashtags.and_other": "…e {count, plural, one {}other {# de mai}}", + "home.actions.go_to_explore": "Agachatz las tendéncias", + "home.actions.go_to_suggestions": "Trobatz de monde de sègre", "home.column_settings.basic": "Basic", "home.column_settings.show_reblogs": "Mostrar los partatges", "home.column_settings.show_replies": "Mostrar las responsas", "home.hide_announcements": "Rescondre las anóncias", + "home.pending_critical_update.link": "Veire las mesas a jorn", "home.show_announcements": "Mostrar las anóncias", "interaction_modal.on_another_server": "Sus un autre servidor", "interaction_modal.on_this_server": "Sus aqueste servidor", @@ -332,14 +346,17 @@ "mute_modal.hide_notifications": "Rescondre las notificacions d’aquesta persona ?", "mute_modal.indefinite": "Cap de data de fin", "navigation_bar.about": "A prepaus", + "navigation_bar.advanced_interface": "Dobrir l’interfàcia web avançada", "navigation_bar.blocks": "Personas blocadas", "navigation_bar.bookmarks": "Marcadors", "navigation_bar.community_timeline": "Flux public local", "navigation_bar.compose": "Escriure un nòu tut", + "navigation_bar.direct": "Mencions privadas", "navigation_bar.discover": "Trobar", "navigation_bar.domain_blocks": "Domenis resconduts", "navigation_bar.edit_profile": "Modificar lo perfil", "navigation_bar.explore": "Explorar", + "navigation_bar.favourites": "Favorits", "navigation_bar.filters": "Mots ignorats", "navigation_bar.follow_requests": "Demandas d’abonament", "navigation_bar.followed_tags": "Etiquetas seguidas", @@ -369,6 +386,7 @@ "notifications.column_settings.admin.report": "Senhalaments novèls :", "notifications.column_settings.admin.sign_up": "Nòus inscrits :", "notifications.column_settings.alert": "Notificacions localas", + "notifications.column_settings.favourite": "Favorits :", "notifications.column_settings.filter_bar.advanced": "Mostrar totas las categorias", "notifications.column_settings.filter_bar.category": "Barra de recèrca rapida", "notifications.column_settings.filter_bar.show_bar": "Afichar la barra de filtres", @@ -386,6 +404,7 @@ "notifications.column_settings.update": "Modificacions :", "notifications.filter.all": "Totas", "notifications.filter.boosts": "Partages", + "notifications.filter.favourites": "Favorits", "notifications.filter.follows": "Seguiments", "notifications.filter.mentions": "Mencions", "notifications.filter.polls": "Resultats del sondatge", @@ -399,15 +418,21 @@ "notifications_permission_banner.enable": "Activar las notificacions burèu", "notifications_permission_banner.how_to_control": "Per recebre las notificacions de Mastodon quand es pas dobèrt, activatz las notificacions de burèu. Podètz precisar quin tipe de notificacion generarà una notificacion de burèu via lo boton {icon} dessús un còp activadas.", "notifications_permission_banner.title": "Manquetz pas jamai res", + "onboarding.action.back": "Tornar en rèire", + "onboarding.actions.back": "Tornar en rèire", "onboarding.actions.go_to_explore": "See what's trending", "onboarding.actions.go_to_home": "Go to your home feed", + "onboarding.compose.template": "Adiu #Mastodon !", "onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!", "onboarding.follows.title": "Popular on Mastodon", + "onboarding.share.title": "Partejar vòstre perfil", "onboarding.start.lead": "Your new Mastodon account is ready to go. Here's how you can make the most of it:", "onboarding.start.skip": "Want to skip right ahead?", + "onboarding.start.title": "Tot es prèst !", "onboarding.steps.follow_people.body": "You curate your own feed. Lets fill it with interesting people.", "onboarding.steps.follow_people.title": "Follow {count, plural, one {one person} other {# people}}", "onboarding.steps.publish_status.body": "Say hello to the world.", + "onboarding.steps.publish_status.title": "Escrivètz vòstre primièr tut", "onboarding.steps.setup_profile.body": "Others are more likely to interact with you with a filled out profile.", "onboarding.steps.setup_profile.title": "Customize your profile", "onboarding.steps.share_profile.body": "Let your friends know how to find you on Mastodon!", @@ -415,6 +440,7 @@ "picture_in_picture.restore": "Lo tornar", "poll.closed": "Tampat", "poll.refresh": "Actualizar", + "poll.reveal": "Veire los resultats", "poll.total_people": "{count, plural, one {# persona} other {# personas}}", "poll.total_votes": "{count, plural, one {# vòte} other {# vòtes}}", "poll.vote": "Votar", @@ -482,11 +508,17 @@ "report_notification.open": "Dobrir lo senhalament", "search.placeholder": "Recercar", "search.search_or_paste": "Recercar o picar una URL", + "search_popout.language_code": "Còdi ISO de lenga", + "search_popout.options": "Opcions de recèrca", + "search_popout.quick_actions": "Accions rapidas", + "search_popout.recent": "Recèrcas recentas", + "search_popout.specific_date": "data especifica", "search_popout.user": "utilizaire", "search_results.accounts": "Perfils", "search_results.all": "Tot", "search_results.hashtags": "Etiquetas", "search_results.nothing_found": "Cap de resultat per aquestes tèrmes de recèrca", + "search_results.see_all": "O veire tot", "search_results.statuses": "Tuts", "search_results.title": "Recèrca : {q}", "server_banner.active_users": "utilizaires actius", @@ -506,16 +538,20 @@ "status.copy": "Copiar lo ligam de l’estatut", "status.delete": "Escafar", "status.detailed_status": "Vista detalhada de la convèrsa", + "status.direct_indicator": "Mencion privada", "status.edit": "Modificar", "status.edited": "Modificat {date}", "status.edited_x_times": "Modificat {count, plural, un {{count} còp} other {{count} còps}}", "status.embed": "Embarcar", + "status.favourite": "Apondre als favorits", "status.filter": "Filtrar aquesta publicacion", "status.filtered": "Filtrat", "status.hide": "Amagar la publicacion", "status.history.created": "{name} o creèt lo {date}", "status.history.edited": "{name} o modifiquèt lo {date}", "status.load_more": "Cargar mai", + "status.media.open": "Clicar per dobrir", + "status.media.show": "Clicar per mostar", "status.media_hidden": "Mèdia rescondut", "status.mention": "Mencionar", "status.more": "Mai", @@ -546,6 +582,7 @@ "status.title.with_attachments": "{user} posted {attachmentCount, plural, one {an attachment} other {# attachments}}", "status.translate": "Traduire", "status.translated_from_with": "Traduch del {lang} amb {provider}", + "status.uncached_media_warning": "Apercebut indisponible", "status.unmute_conversation": "Tornar mostrar la conversacion", "status.unpin": "Tirar del perfil", "subscribed_languages.lead": "Sonque las publicacions dins las lengas seleccionadas apreissaràn dins vòstre acuèlh e linha cronologica aprèp aqueste cambiament. Seleccionatz pas res per recebre las publicacions en quina lenga que siá.", diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json index 8b5f7de2f3..27fd0ad35e 100644 --- a/app/javascript/mastodon/locales/zh-TW.json +++ b/app/javascript/mastodon/locales/zh-TW.json @@ -409,7 +409,7 @@ "navigation_bar.favourites": "最愛", "navigation_bar.filters": "已靜音的關鍵字", "navigation_bar.follow_requests": "跟隨請求", - "navigation_bar.followed_tags": "已跟隨的主題標籤", + "navigation_bar.followed_tags": "已跟隨主題標籤", "navigation_bar.follows_and_followers": "跟隨中與跟隨者", "navigation_bar.lists": "列表", "navigation_bar.logout": "登出", diff --git a/config/locales/activerecord.fi.yml b/config/locales/activerecord.fi.yml index a06cd399a8..93f338b5d5 100644 --- a/config/locales/activerecord.fi.yml +++ b/config/locales/activerecord.fi.yml @@ -11,7 +11,7 @@ fi: locale: Alue password: Salasana user/account: - username: Käyttäjätunnus + username: Käyttäjänimi user/invite_request: text: Syy errors: diff --git a/config/locales/fi.yml b/config/locales/fi.yml index 2043d327a1..d1f345abd4 100644 --- a/config/locales/fi.yml +++ b/config/locales/fi.yml @@ -163,7 +163,7 @@ fi: unsilenced_msg: Tilin %{username} rajoituksen kumoaminen onnistui unsubscribe: Lopeta tilaus unsuspended_msg: Tilin %{username} jäädytyksen kumoaminen onnistui - username: Käyttäjätunnus + username: Käyttäjänimi view_domain: Näytä verkkotunnuksen yhteenveto warn: Varoita web: Verkko @@ -833,7 +833,7 @@ fi: database_schema_check: message_html: Tietokannan siirto on vireillä. Suorita ne varmistaaksesi, että sovellus toimii odotetulla tavalla elasticsearch_health_red: - message_html: Elasticsearch-klusteri on vikatilassa (punainen tila); hakuominaisuudet eivät ole käytettävissä + message_html: Elasticsearch-klusteri on vikatilassa (punainen tila), joten hakuominaisuudet eivät ole käytettävissä elasticsearch_health_yellow: message_html: Elasticsearch-klusteri on häiriötilassa (keltainen tila), joten suosittelemme tutkimaan syyn elasticsearch_index_mismatch: @@ -843,13 +843,13 @@ fi: message_html: Elasticsearch-klusterissa on useampi kuin yksi solmu, mutta Mastodonia ei ole määritetty käyttämään niitä. elasticsearch_preset_single_node: action: Katso käyttöohjeet - message_html: Elasticsearch-klusterissa on vain yksi solmu, ES_PRESET tulisi asettaa arvoon single_node_cluster. + message_html: Elasticsearch-klusterissa on vain yksi solmu. ES_PRESET tulisi asettaa arvoon single_node_cluster. elasticsearch_reset_chewy: message_html: Elasticsearch-järjestelmäindeksi on vanhentunut asetusmuutoksen vuoksi. Suorita tootctl search deploy --reset-chewy päivittääksesi sen. elasticsearch_running_check: - message_html: Ei saatu yhteyttä Elasticsearch. Tarkista, että se on käynnissä tai poista kokotekstihaku käytöstä + message_html: Ei saatu yhteyttä Elasticsearchiin. Tarkista, että se on käynnissä tai poista kokotekstihaku käytöstä elasticsearch_version_check: - message_html: 'Yhteensopimaton Elasticsearch versio: %{value}' + message_html: 'Yhteensopimaton Elasticsearch-versio: %{value}' version_comparison: Elasticsearch %{running_version} on käynnissä, kun %{required_version} vaaditaan rules_check: action: Hallitse palvelimen sääntöjä @@ -1089,7 +1089,7 @@ fi: new_confirmation_instructions_sent: Saat uuden vahvistuslinkin sisältävän sähköpostiviestin muutamassa minuutissa! title: Tarkista sähköpostilaatikkosi sign_in: - preamble_html: Kirjaudu %{domain}-tunnuksellasi. Jos tilisi sijaitsee eri palvelimella, et voi kirjautua täällä. + preamble_html: Kirjaudu %{domain}-tunnuksellasi. Jos tilisi sijaitsee eri palvelimella, et voi kirjautua tässä. title: Kirjaudu palvelimelle %{domain} sign_up: manual_review: Palvelimen %{domain} valvojat tarkistavat rekisteröitymiset käsin. Helpottaaksesi rekisteröitymisesi käsittelyä kerro hieman itsestäsi ja miksi haluat luoda käyttäjätilin palvelimelle %{domain}. @@ -1271,7 +1271,7 @@ fi: other: Kaikki %{count} kohdetta tällä sivulla on valittu. all_matching_items_selected_html: one: "%{count} kohde, joka vastaa hakuasi." - other: Kaikki %{count} kohdetta, jotka vastaavat hakuasi. + other: Kaikki %{count} hakuasi vastaavaa kohdetta. cancel: Peruuta changes_saved_msg: Muutosten tallennus onnistui! confirm: Vahvista @@ -1283,7 +1283,7 @@ fi: save_changes: Tallenna muutokset select_all_matching_items: one: Valitse %{count} kohde, joka vastaa hakuasi. - other: Valitse kaikki %{count} kohdetta, jotka vastaavat hakuasi. + other: Valitse kaikki %{count} hakuasi vastaavaa kohdetta. today: tänään validation_errors: one: Kaikki ei ole aivan oikein! Tarkasta alla oleva virhe @@ -1403,7 +1403,7 @@ fi: not_ready: Ei voi liittää tiedostoja, joiden käsittely on kesken. Yritä hetken kuluttua uudelleen! too_many: Tiedostoja voi liittää enintään 4 migrations: - acct: uuden tilin käyttäjätunnus@verkkotunnus + acct: Muuttanut tunnukselle cancel: Peruuta uudelleenohjaus cancel_explanation: Uudelleenohjauksen peruuttaminen aktivoi uudelleen nykyisen tilisi, mutta ei palauta seuraajia, jotka on siirretty kyseiselle tilille. cancelled_msg: Uudelleenohjaus peruttu onnistuneesti. @@ -1526,7 +1526,7 @@ fi: privacy_hint_html: Määritä, kuinka paljon muita avustavia tietoja haluat paljastaa. Käyttäjät löytävät kiinnostavia profiileja ja hienoja sovelluksia, kun he selaavat toisten seuraamia käyttäjiä ja kun he näkevät, millä sovelluksilla nämä julkaisevat. Saatat kuitenkin haluta piilottaa nämä tiedot. reach: Tavoittavuus reach_hint_html: Määritä, haluatko tulla uusien käyttäjien löytämäksi ja seuraamaksi. Haluatko julkaisujesi näkyvän Selaa-sivulla? Haluatko muiden käyttäjien näkevän sinut seuraamissuosituksissaan? Haluatko hyväksyä kaikki uudet seuraajat automaattisesti vai päättää jokaisesta erikseen? - search: Haku + search: Hae search_hint_html: Määritä, kuinka haluat tulla löydetyksi. Haluatko, että ihmiset löytävät sinut julkisten julkaisujesi perusteella? Haluatko, että ihmiset Mastodonin ulkopuolella löytävät profiilisi tehdessään hakuja verkossa? Otathan huomioon, ettei julkisten tietojen täyttä kaikista hakukoneista poisjäämistä voi taata. title: Yksityisyys ja tavoittavuus privacy_policy: diff --git a/config/locales/simple_form.fi.yml b/config/locales/simple_form.fi.yml index 1925ba77f3..189f9f8eb4 100644 --- a/config/locales/simple_form.fi.yml +++ b/config/locales/simple_form.fi.yml @@ -43,7 +43,7 @@ fi: bot: Tämä tili suorittaa enimmäkseen automaattisia toimintoja eikä sitä ehkä valvota context: Ainakin yksi konteksti, jossa suodattimen pitäisi olla voimassa current_password: Turvallisuussyistä kirjoita nykyisen tilin salasana - current_username: Vahvista kirjoittamalla nykyisen tilin käyttäjätunnus + current_username: Vahvista kirjoittamalla nykyisen tilin käyttäjänimi digest: Lähetetään vain pitkän poissaolon jälkeen ja vain, jos olet saanut suoria viestejä poissaolosi aikana email: Sinulle lähetetään vahvistussähköposti header: PNG, GIF tai JPG. Enintään %{size}. Skaalataan kokoon %{dimensions} px @@ -148,9 +148,9 @@ fi: show_collections: Näytä seuratut ja seuraajat profiilissa unlocked: Hyväksy uudet seuraajat automaattisesti account_alias: - acct: Vanhan tilin käyttäjätunnus + acct: Vanhan tilin käyttäjänimi account_migration: - acct: Uuden tilin käyttäjätunnus + acct: Uuden tilin käyttäjänimi account_warning_preset: text: Esiasetettu teksti title: Nimi @@ -227,7 +227,7 @@ fi: title: Nimi type: Tuontilaji username: Käyttäjänimi - username_or_email: Käyttäjänimi tai sähköposti + username_or_email: Käyttäjänimi tai sähköpostiosoite whole_word: Koko sana email_domain_block: with_dns_records: Sisällytä toimialueen MX tietueet ja IP-osoite @@ -253,7 +253,7 @@ fi: show_domain_blocks: Näytä domainestot show_domain_blocks_rationale: Näytä miksi verkkotunnukset on estetty site_contact_email: Ota yhteyttä sähköpostilla - site_contact_username: Kontaktin käyttäjänimi + site_contact_username: Yhteyshenkilön käyttäjänimi site_extended_description: Laajennettu kuvaus site_short_description: Palvelimen kuvaus site_terms: Tietosuojakäytäntö From d7a8f6b65823a1e52d4b4fd8a73e81b2e2ff1fa2 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Wed, 11 Oct 2023 11:06:26 -0400 Subject: [PATCH 21/58] Fix haml-lint `InstanceVariables` rule for relationships/account (#27342) --- .haml-lint_todo.yml | 7 +++---- app/views/relationships/_account.html.haml | 2 +- app/views/relationships/show.html.haml | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.haml-lint_todo.yml b/.haml-lint_todo.yml index cfa39a24e2..c6bb38eb47 100644 --- a/.haml-lint_todo.yml +++ b/.haml-lint_todo.yml @@ -1,13 +1,13 @@ # This configuration was generated by # `haml-lint --auto-gen-config` -# on 2023-10-11 10:00:39 -0400 using Haml-Lint version 0.51.0. +# on 2023-10-11 10:49:10 -0400 using Haml-Lint version 0.51.0. # The point is for the user to remove these configuration records # one by one as the lints are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of Haml-Lint, may require this file to be generated again. linters: - # Offense count: 945 + # Offense count: 946 LineLength: enabled: false @@ -26,11 +26,10 @@ linters: - 'app/views/admin/reports/show.html.haml' - 'app/views/disputes/strikes/show.html.haml' - # Offense count: 2 + # Offense count: 1 InstanceVariables: exclude: - 'app/views/auth/sessions/two_factor/_otp_authentication_form.html.haml' - - 'app/views/relationships/_account.html.haml' # Offense count: 2 IdNames: diff --git a/app/views/relationships/_account.html.haml b/app/views/relationships/_account.html.haml index 0fa3cffb55..43a3d64bc8 100644 --- a/app/views/relationships/_account.html.haml +++ b/app/views/relationships/_account.html.haml @@ -6,7 +6,7 @@ %tbody %tr %td.accounts-table__interrelationships - = interrelationships_icon(@relationships, account.id) + = interrelationships_icon(relationships, account.id) %td= account_link_to account %td.accounts-table__count.optional = friendly_number_to_human account.statuses_count diff --git a/app/views/relationships/show.html.haml b/app/views/relationships/show.html.haml index f08e9c1df8..97ba49eb52 100644 --- a/app/views/relationships/show.html.haml +++ b/app/views/relationships/show.html.haml @@ -53,6 +53,6 @@ - if @accounts.empty? = nothing_here 'nothing-here--under-tabs' - else - = render partial: 'account', collection: @accounts, locals: { f: f } + = render partial: 'account', collection: @accounts, locals: { f: f, relationships: @relationships } = paginate @accounts From 85b36fbbd3f13ea23bee2b94b6b4a0a7aeeeea44 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 12 Oct 2023 09:35:25 +0200 Subject: [PATCH 22/58] Update dependency devise to v4.9.3 (#27373) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index fa84bdc5e1..dfa1846248 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -146,7 +146,7 @@ GEM net-http-persistent (~> 4.0) nokogiri (~> 1, >= 1.10.8) base64 (0.1.1) - bcrypt (3.1.18) + bcrypt (3.1.19) better_errors (2.10.1) erubi (>= 1.0.0) rack (>= 0.9.0) @@ -210,7 +210,7 @@ GEM database_cleaner-core (2.0.1) date (3.3.3) debug_inspector (1.1.0) - devise (4.9.2) + devise (4.9.3) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 4.1.0) @@ -586,7 +586,7 @@ GEM regexp_parser (2.8.2) request_store (1.5.1) rack (>= 1.4) - responders (3.1.0) + responders (3.1.1) actionpack (>= 5.2) railties (>= 5.2) rexml (3.2.6) From d4c2dca8740236d99541420231874b258381b237 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 12 Oct 2023 03:44:20 -0400 Subject: [PATCH 23/58] =?UTF-8?q?Fix=20haml-lint=20`InstanceVariables`=20r?= =?UTF-8?q?ule=20for=20auth/sessions/two=5Ffactor/o=E2=80=A6=20(#27372)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .haml-lint_todo.yml | 7 +------ .../concerns/two_factor_authentication_concern.rb | 7 +++++++ app/views/auth/sessions/two_factor.html.haml | 2 +- .../sessions/two_factor/_otp_authentication_form.html.haml | 2 +- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/.haml-lint_todo.yml b/.haml-lint_todo.yml index c6bb38eb47..8a4dbaeff4 100644 --- a/.haml-lint_todo.yml +++ b/.haml-lint_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `haml-lint --auto-gen-config` -# on 2023-10-11 10:49:10 -0400 using Haml-Lint version 0.51.0. +# on 2023-10-11 11:31:24 -0400 using Haml-Lint version 0.51.0. # The point is for the user to remove these configuration records # one by one as the lints are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -26,11 +26,6 @@ linters: - 'app/views/admin/reports/show.html.haml' - 'app/views/disputes/strikes/show.html.haml' - # Offense count: 1 - InstanceVariables: - exclude: - - 'app/views/auth/sessions/two_factor/_otp_authentication_form.html.haml' - # Offense count: 2 IdNames: exclude: diff --git a/app/controllers/concerns/two_factor_authentication_concern.rb b/app/controllers/concerns/two_factor_authentication_concern.rb index 9eb45b90d6..bc2d194c33 100644 --- a/app/controllers/concerns/two_factor_authentication_concern.rb +++ b/app/controllers/concerns/two_factor_authentication_concern.rb @@ -5,6 +5,7 @@ module TwoFactorAuthenticationConcern included do prepend_before_action :authenticate_with_two_factor, if: :two_factor_enabled?, only: [:create] + helper_method :webauthn_enabled? end def two_factor_enabled? @@ -87,4 +88,10 @@ module TwoFactorAuthenticationConcern set_locale { render :two_factor } end + + protected + + def webauthn_enabled? + @webauthn_enabled + end end diff --git a/app/views/auth/sessions/two_factor.html.haml b/app/views/auth/sessions/two_factor.html.haml index 20232d8dc2..653f155801 100644 --- a/app/views/auth/sessions/two_factor.html.haml +++ b/app/views/auth/sessions/two_factor.html.haml @@ -3,7 +3,7 @@ = javascript_pack_tag 'two_factor_authentication', crossorigin: 'anonymous' -- if @webauthn_enabled +- if webauthn_enabled? = render partial: 'auth/sessions/two_factor/webauthn_form', locals: { hidden: @scheme_type != 'webauthn' } = render partial: 'auth/sessions/two_factor/otp_authentication_form', locals: { hidden: @scheme_type != 'totp' } diff --git a/app/views/auth/sessions/two_factor/_otp_authentication_form.html.haml b/app/views/auth/sessions/two_factor/_otp_authentication_form.html.haml index 094b502b17..8cc2c85610 100644 --- a/app/views/auth/sessions/two_factor/_otp_authentication_form.html.haml +++ b/app/views/auth/sessions/two_factor/_otp_authentication_form.html.haml @@ -13,6 +13,6 @@ - if Setting.site_contact_email.present? %p.hint.subtle-hint= t('users.otp_lost_help_html', email: mail_to(Setting.site_contact_email, nil)) - - if @webauthn_enabled + - if webauthn_enabled? .form-footer = link_to(t('auth.link_to_webauth'), '#', id: 'link-to-webauthn') From c348b904a589697dfd29bcecb911fd979736ce42 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 12 Oct 2023 10:07:40 +0200 Subject: [PATCH 24/58] New Crowdin Translations (automated) (#27376) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/si.json | 16 ++++++++++++++++ config/locales/ja.yml | 2 +- config/locales/ko.yml | 14 +++++++------- config/locales/si.yml | 2 +- 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/app/javascript/mastodon/locales/si.json b/app/javascript/mastodon/locales/si.json index 43bd5a1bb5..7b26a9b488 100644 --- a/app/javascript/mastodon/locales/si.json +++ b/app/javascript/mastodon/locales/si.json @@ -218,7 +218,10 @@ "home.hide_announcements": "නිවේදන සඟවන්න", "home.pending_critical_update.link": "යාවත්කාල බලන්න", "home.show_announcements": "නිවේදන පෙන්වන්න", + "interaction_modal.login.action": "මුලට ගෙනයන්න", "interaction_modal.on_this_server": "මෙම සේවාදායකයෙහි", + "interaction_modal.title.favourite": "{name}ගේ ලිපිය ප්‍රිය කරන්න", + "interaction_modal.title.follow": "{name} අනුගමනය", "intervals.full.days": "{number, plural, one {දවස් #} other {දවස් #}}", "intervals.full.hours": "{number, plural, one {පැය #} other {පැය #}}", "intervals.full.minutes": "{number, plural, one {විනාඩි #} other {විනාඩි #}}", @@ -319,6 +322,7 @@ "notifications.mark_as_read": "සියළු දැනුම්දීම් කියවූ බව යොදන්න", "notifications_permission_banner.enable": "වැඩතල දැනුම්දීම් සබල කරන්න", "notifications_permission_banner.title": "කිසිවක් අතපසු නොකරන්න", + "onboarding.actions.go_to_explore": "නැගී එන දෑ වෙත ගෙනයන්න", "onboarding.compose.template": "ආයුබෝ #මාස්ටඩන්!", "onboarding.share.title": "ඔබගේ පැතිකඩ බෙදාගන්න", "onboarding.steps.publish_status.title": "පළමු ලිපිය පළ කරන්න", @@ -358,6 +362,7 @@ "report.categories.other": "වෙනත්", "report.categories.spam": "ආයාචිත", "report.categories.violation": "අන්තර්ගතය නිසා සේවාදායකයේ නීතියක් හෝ කිහිපයක් කඩ වේ", + "report.category.subtitle": "හොඳම ගැලපීම තෝරන්න", "report.category.title": "මෙම {type}සමඟ සිදුවන්නේ කුමක්දැයි අපට කියන්න", "report.category.title_account": "පැතිකඩ", "report.category.title_status": "ලිපිය", @@ -394,14 +399,25 @@ "report_notification.categories.spam": "ආයාචිත", "report_notification.categories.violation": "නීතිය කඩ කිරීම", "report_notification.open": "විවෘත වාර්තාව", + "search.no_recent_searches": "මෑත සෙවීම් නැත", "search.placeholder": "සොයන්න", + "search.quick_action.account_search": "ගැළපෙන පැතිකඩ {x}", + "search.quick_action.go_to_account": "{x} පැතිකඩ වෙත යන්න", "search.quick_action.open_url": "ලිපිනය මාස්ටඩන්හි අරින්න", + "search.quick_action.status_search": "ගැළපෙන ලිපි {x}", "search.search_or_paste": "සොයන්න හෝ ඒ.ස.නි. අලවන්න", + "search_popout.options": "සෙවුම් විකල්ප", + "search_popout.quick_actions": "ඉක්මන් ක්‍රියාමාර්ග", + "search_popout.recent": "මෑත සෙවීම්", + "search_popout.specific_date": "නිශ්චිත දිනයකට", + "search_popout.user": "පරිශ්‍රීලකයා", + "search_results.accounts": "පැතිකඩ", "search_results.all": "සියල්ල", "search_results.nothing_found": "මෙම සෙවුම් පද සඳහා කිසිවක් සොයාගත නොහැකි විය", "search_results.see_all": "සියල්ල බලන්න", "search_results.statuses": "ලිපි", "search_results.title": "{q} සොයන්න", + "server_banner.active_users": "සක්‍රිය පරිශ්‍රීලකයින්", "server_banner.learn_more": "තව දැනගන්න", "sign_in_banner.create_account": "ගිණුමක් සාදන්න", "sign_in_banner.sign_in": "පිවිසෙන්න", diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 6a72c1ca14..10bc59812f 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -1653,7 +1653,7 @@ ja: private_long: フォロワーにのみ表示されます public: 公開 public_long: 誰でも見ることができ、かつ公開タイムラインに表示されます - unlisted: 未収載 + unlisted: 非収載 unlisted_long: 誰でも見ることができますが、公開タイムラインには表示されません statuses_cleanup: enabled: 古い投稿を自動的に削除する diff --git a/config/locales/ko.yml b/config/locales/ko.yml index ff337cc6ca..720d65731b 100644 --- a/config/locales/ko.yml +++ b/config/locales/ko.yml @@ -881,9 +881,9 @@ ko: only_allowed: 허용된 것만 pending_review: 심사 대기 preview_card_providers: - allowed: 이 발행처의 링크는 유행록에 실릴 수 있음 + allowed: 이 발행처의 링크는 유행 목록에 실릴 수 있음 description_html: 당신의 서버에서 많은 링크가 공유되고 있는 도메인들입니다. 링크의 도메인이 승인되기 전까지는 링크들은 공개적으로 트렌드에 게시되지 않습니다. 당신의 승인(또는 거절)은 서브도메인까지 확장됩니다. - rejected: 이 발행처의 링크는 유행록에 실리지 않음 + rejected: 이 발행처의 링크는 유행 목록에 실리지 않음 title: 발행처 rejected: 거부됨 statuses: @@ -906,14 +906,14 @@ ko: tag_servers_measure: 다른 서버들 tag_uses_measure: 총 사용 description_html: 현재 서버에서 볼 수 있는 게시물에서 많이 공유되고 있는 해시태그들입니다. 현재 사람들이 무슨 이야기를 하고 있는지 사용자들이 파악할 수 있도록 도움이 됩니다. 승인하지 않는 한 해시태그는 공개적으로 게시되지 않습니다. - listable: 추천될 수 있습니다 + listable: 추천될 수 있음 no_tag_selected: 아무 것도 선택 되지 않아 어떤 태그도 바뀌지 않았습니다 - not_listable: 추천될 수 없습니다 - not_trendable: 유행 목록에 나타나지 않습니다 - not_usable: 사용불가 + not_listable: 추천하지 않음 + not_trendable: 유행 목록에 나타내지 않음 + not_usable: 이용할 수 없음 peaked_on_and_decaying: "%{date}에 고점을 찍고, 떨어지고 있습니다" title: 유행하는 해시태그 - trendable: 유행 목록에 나타날 수 있습니다 + trendable: 유행 목록에 나타날 수 있음 trending_rank: "#%{rank}위로 유행 중" usable: 사용 가능 usage_comparison: 오늘은 %{today}회 쓰였고, 어제는 %{yesterday}회 쓰임 diff --git a/config/locales/si.yml b/config/locales/si.yml index 8f04533519..39368b3f85 100644 --- a/config/locales/si.yml +++ b/config/locales/si.yml @@ -299,7 +299,7 @@ si: updated_msg: ඉමොජි සාර්ථකව යාවත්කාලීන කරන ලදී! upload: උඩුගත කරන්න dashboard: - active_users: ක්රියාකාරී පරිශීලකයන් + active_users: සක්‍රිය පරිශ්‍රීලකයින් interactions: අන්තර්ක්රියා media_storage: මාධ්‍ය ආචයනය new_users: නව පරිශ්‍රීලකයින් From 2e7cdd0516d063adb748e242a93264548ea4e501 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Thu, 12 Oct 2023 20:06:21 +0900 Subject: [PATCH 25/58] =?UTF-8?q?Fix:=20#89=20NodeInfo=E5=90=91=E3=81=91?= =?UTF-8?q?=E3=81=AE=E6=A9=9F=E8=83=BD=E4=B8=80=E8=A6=A7=E8=A1=A8=E3=82=92?= =?UTF-8?q?=E4=BD=9C=E6=88=90=E3=81=97=E3=81=A6=E5=8C=BA=E5=88=A5=20(#103)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/helpers/kmyblue_capabilities_helper.rb | 25 +++++++++++++++++++ app/serializers/nodeinfo/serializer.rb | 2 +- spec/serializers/nodeinfo/serializer_spec.rb | 5 ++++ .../rest/instance_serializer_spec.rb | 4 +++ 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/app/helpers/kmyblue_capabilities_helper.rb b/app/helpers/kmyblue_capabilities_helper.rb index 8653a3f9da..455561a597 100644 --- a/app/helpers/kmyblue_capabilities_helper.rb +++ b/app/helpers/kmyblue_capabilities_helper.rb @@ -30,4 +30,29 @@ module KmyblueCapabilitiesHelper capabilities end + + def capabilities_for_nodeinfo + capabilities = %i( + wide_emoji + status_reference + quote + kmyblue_quote + searchability + kmyblue_searchability + visibility_mutual + visibility_limited + kmyblue_antenna + kmyblue_bookmark_category + kmyblue_searchability_limited + kmyblue_circle_history + ) + + capabilities << :full_text_search if Chewy.enabled? + if Setting.enable_emoji_reaction + capabilities << :emoji_reaction + capabilities << :enable_wide_emoji_reaction + end + + capabilities + end end diff --git a/app/serializers/nodeinfo/serializer.rb b/app/serializers/nodeinfo/serializer.rb index 3555f0bd8d..83d63bb397 100644 --- a/app/serializers/nodeinfo/serializer.rb +++ b/app/serializers/nodeinfo/serializer.rb @@ -40,7 +40,7 @@ class NodeInfo::Serializer < ActiveModel::Serializer def metadata { - features: fedibird_capabilities, + features: capabilities_for_nodeinfo, } end diff --git a/spec/serializers/nodeinfo/serializer_spec.rb b/spec/serializers/nodeinfo/serializer_spec.rb index c43b0b569f..8352a44143 100644 --- a/spec/serializers/nodeinfo/serializer_spec.rb +++ b/spec/serializers/nodeinfo/serializer_spec.rb @@ -28,5 +28,10 @@ describe NodeInfo::Serializer do # rubocop:disable RSpec/FilePath it 'returns features' do expect(serialization['metadata']['features']).to include 'emoji_reaction' end + + it 'returns nodeinfo own features' do + expect(serialization['metadata']['features']).to include 'quote' + expect(serialization['metadata']['features']).to_not include 'kmyblue_markdown' + end end end diff --git a/spec/serializers/rest/instance_serializer_spec.rb b/spec/serializers/rest/instance_serializer_spec.rb index a9a3259aa8..4b33d15daa 100644 --- a/spec/serializers/rest/instance_serializer_spec.rb +++ b/spec/serializers/rest/instance_serializer_spec.rb @@ -22,5 +22,9 @@ describe REST::InstanceSerializer do it 'returns fedibird_capabilities' do expect(serialization['fedibird_capabilities']).to include 'emoji_reaction' end + + it 'returns api own fedibird_capabilities' do + expect(serialization['fedibird_capabilities']).to include 'kmyblue_markdown' + end end end From 12d068d38d2752fcd3c5d519d74b7db5c3c22fba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Thu, 12 Oct 2023 20:06:33 +0900 Subject: [PATCH 26/58] =?UTF-8?q?Fix:=20#83=20=E3=83=95=E3=83=AC=E3=83=B3?= =?UTF-8?q?=E3=83=89=E3=82=B5=E3=83=BC=E3=83=90=E3=83=BC=E3=81=A7=E3=81=AE?= =?UTF-8?q?=E5=85=A8=E6=8A=95=E7=A8=BF=E9=85=8D=E9=80=81=E3=81=A7=E3=80=81?= =?UTF-8?q?=E3=82=A2=E3=82=AB=E3=82=A6=E3=83=B3=E3=83=88=E3=83=89=E3=83=A1?= =?UTF-8?q?=E3=82=A4=E3=83=B3=E3=83=96=E3=83=AD=E3=83=83=E3=82=AF=E3=81=8C?= =?UTF-8?q?=E7=84=A1=E8=A6=96=E3=81=95=E3=82=8C=E3=82=8B=E5=95=8F=E9=A1=8C?= =?UTF-8?q?=20(#102)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/lib/status_reach_finder.rb | 4 ++-- spec/lib/status_reach_finder_spec.rb | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/app/lib/status_reach_finder.rb b/app/lib/status_reach_finder.rb index 5a33418fab..22b0d94ff6 100644 --- a/app/lib/status_reach_finder.rb +++ b/app/lib/status_reach_finder.rb @@ -147,7 +147,7 @@ class StatusReachFinder def friend_inboxes if @status.public_visibility? || @status.public_unlisted_visibility? || (@status.unlisted_visibility? && (@status.public_searchability? || @status.public_unlisted_searchability?)) - DeliveryFailureTracker.without_unavailable(FriendDomain.distributables.where(delivery_local: true).pluck(:inbox_url)) + DeliveryFailureTracker.without_unavailable(FriendDomain.distributables.where(delivery_local: true).where.not(domain: AccountDomainBlock.where(account: @status.account).select(:domain)).pluck(:inbox_url)) else [] end @@ -155,7 +155,7 @@ class StatusReachFinder def nolocal_friend_inboxes if @status.public_visibility? - DeliveryFailureTracker.without_unavailable(FriendDomain.distributables.where(delivery_local: false).pluck(:inbox_url)) + DeliveryFailureTracker.without_unavailable(FriendDomain.distributables.where(delivery_local: false).where.not(domain: AccountDomainBlock.where(account: @status.account).select(:domain)).pluck(:inbox_url)) else [] end diff --git a/spec/lib/status_reach_finder_spec.rb b/spec/lib/status_reach_finder_spec.rb index 2d8e075d5b..8b333de0c4 100644 --- a/spec/lib/status_reach_finder_spec.rb +++ b/spec/lib/status_reach_finder_spec.rb @@ -239,6 +239,18 @@ describe StatusReachFinder do expect(subject.inboxes_for_friend).to_not include 'https://foo.bar/inbox' end end + + context 'when distributable but domain blocked by account' do + before do + Fabricate(:account_domain_block, account: alice, domain: 'foo.bar') + Fabricate(:friend_domain, domain: 'foo.bar', inbox_url: 'https://foo.bar/inbox', passive_state: :accepted, pseudo_relay: true) + end + + it 'send status' do + expect(subject.inboxes).to_not include 'https://foo.bar/inbox' + expect(subject.inboxes_for_friend).to_not include 'https://foo.bar/inbox' + end + end end context 'when it contains distributable friend server' do From c86ad4566003f15f2f4f2499efd36f20b62737ab Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 12 Oct 2023 16:47:18 +0200 Subject: [PATCH 27/58] Change PWA start URL from `/home` to `/` (#27377) --- app/serializers/manifest_serializer.rb | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/app/serializers/manifest_serializer.rb b/app/serializers/manifest_serializer.rb index aa7f7ce5d8..501bb788e7 100644 --- a/app/serializers/manifest_serializer.rb +++ b/app/serializers/manifest_serializer.rb @@ -16,11 +16,18 @@ class ManifestSerializer < ActiveModel::Serializer 512 ).freeze - attributes :name, :short_name, + attributes :id, :name, :short_name, :icons, :theme_color, :background_color, :display, :start_url, :scope, :share_target, :shortcuts + def id + # This is set to `/home` because that was the old value of `start_url` and + # thus the fallback ID computed by Chrome: + # https://developer.chrome.com/blog/pwa-manifest-id/ + '/home' + end + def name object.title end @@ -53,7 +60,7 @@ class ManifestSerializer < ActiveModel::Serializer end def start_url - '/home' + '/' end def scope From 133f218a4da3d895ae99879acb3afaa25c12f80a Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 13 Oct 2023 04:42:59 -0400 Subject: [PATCH 28/58] Add system specs for admin area `batch` actions (#25027) --- spec/features/admin/accounts_spec.rb | 81 +++++++++++++++++++ spec/features/admin/custom_emojis_spec.rb | 33 ++++++++ .../admin/email_domain_blocks_spec.rb | 33 ++++++++ spec/features/admin/ip_blocks_spec.rb | 33 ++++++++ spec/features/admin/statuses_spec.rb | 34 ++++++++ .../links/preview_card_providers_spec.rb | 33 ++++++++ spec/features/admin/trends/links_spec.rb | 33 ++++++++ spec/features/admin/trends/statuses_spec.rb | 33 ++++++++ spec/features/admin/trends/tags_spec.rb | 33 ++++++++ 9 files changed, 346 insertions(+) create mode 100644 spec/features/admin/accounts_spec.rb create mode 100644 spec/features/admin/custom_emojis_spec.rb create mode 100644 spec/features/admin/email_domain_blocks_spec.rb create mode 100644 spec/features/admin/ip_blocks_spec.rb create mode 100644 spec/features/admin/statuses_spec.rb create mode 100644 spec/features/admin/trends/links/preview_card_providers_spec.rb create mode 100644 spec/features/admin/trends/links_spec.rb create mode 100644 spec/features/admin/trends/statuses_spec.rb create mode 100644 spec/features/admin/trends/tags_spec.rb diff --git a/spec/features/admin/accounts_spec.rb b/spec/features/admin/accounts_spec.rb new file mode 100644 index 0000000000..6d7bab1844 --- /dev/null +++ b/spec/features/admin/accounts_spec.rb @@ -0,0 +1,81 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe 'Admin::Accounts' do + let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } + + before do + sign_in current_user + end + + describe 'Performing batch updates' do + let(:unapproved_user_account) { Fabricate(:account) } + let(:approved_user_account) { Fabricate(:account) } + + before do + unapproved_user_account.user.update(approved: false) + approved_user_account.user.update(approved: true) + + visit admin_accounts_path + end + + context 'without selecting any accounts' do + it 'displays a notice about account selection' do + click_on button_for_suspend + + expect(page).to have_content(selection_error_text) + end + end + + context 'with action of `suspend`' do + it 'suspends the account' do + batch_checkbox_for(approved_user_account).check + + click_on button_for_suspend + + expect(approved_user_account.reload).to be_suspended + end + end + + context 'with action of `approve`' do + it 'approves the account user' do + batch_checkbox_for(unapproved_user_account).check + + click_on button_for_approve + + expect(unapproved_user_account.reload.user).to be_approved + end + end + + context 'with action of `reject`' do + it 'rejects and removes the account' do + batch_checkbox_for(unapproved_user_account).check + + click_on button_for_reject + + expect { unapproved_user_account.reload }.to raise_error(ActiveRecord::RecordNotFound) + end + end + + def button_for_suspend + I18n.t('admin.accounts.perform_full_suspension') + end + + def button_for_approve + I18n.t('admin.accounts.approve') + end + + def button_for_reject + I18n.t('admin.accounts.reject') + end + + def selection_error_text + I18n.t('admin.accounts.no_account_selected') + end + + def batch_checkbox_for(account) + find("#form_account_batch_account_ids_#{account.id}") + end + end +end diff --git a/spec/features/admin/custom_emojis_spec.rb b/spec/features/admin/custom_emojis_spec.rb new file mode 100644 index 0000000000..8a8b6efcd1 --- /dev/null +++ b/spec/features/admin/custom_emojis_spec.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe 'Admin::CustomEmojis' do + let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } + + before do + sign_in current_user + end + + describe 'Performing batch updates' do + before do + visit admin_custom_emojis_path + end + + context 'without selecting any records' do + it 'displays a notice about selection' do + click_on button_for_enable + + expect(page).to have_content(selection_error_text) + end + end + + def button_for_enable + I18n.t('admin.custom_emojis.enable') + end + + def selection_error_text + I18n.t('admin.custom_emojis.no_emoji_selected') + end + end +end diff --git a/spec/features/admin/email_domain_blocks_spec.rb b/spec/features/admin/email_domain_blocks_spec.rb new file mode 100644 index 0000000000..14959cbe74 --- /dev/null +++ b/spec/features/admin/email_domain_blocks_spec.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe 'Admin::EmailDomainBlocks' do + let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } + + before do + sign_in current_user + end + + describe 'Performing batch updates' do + before do + visit admin_email_domain_blocks_path + end + + context 'without selecting any records' do + it 'displays a notice about selection' do + click_on button_for_delete + + expect(page).to have_content(selection_error_text) + end + end + + def button_for_delete + I18n.t('admin.email_domain_blocks.delete') + end + + def selection_error_text + I18n.t('admin.email_domain_blocks.no_email_domain_block_selected') + end + end +end diff --git a/spec/features/admin/ip_blocks_spec.rb b/spec/features/admin/ip_blocks_spec.rb new file mode 100644 index 0000000000..c9b16f6f78 --- /dev/null +++ b/spec/features/admin/ip_blocks_spec.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe 'Admin::IpBlocks' do + let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } + + before do + sign_in current_user + end + + describe 'Performing batch updates' do + before do + visit admin_ip_blocks_path + end + + context 'without selecting any records' do + it 'displays a notice about selection' do + click_on button_for_delete + + expect(page).to have_content(selection_error_text) + end + end + + def button_for_delete + I18n.t('admin.ip_blocks.delete') + end + + def selection_error_text + I18n.t('admin.ip_blocks.no_ip_block_selected') + end + end +end diff --git a/spec/features/admin/statuses_spec.rb b/spec/features/admin/statuses_spec.rb new file mode 100644 index 0000000000..531d0de953 --- /dev/null +++ b/spec/features/admin/statuses_spec.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe 'Admin::Statuses' do + let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } + + before do + sign_in current_user + end + + describe 'Performing batch updates' do + before do + _status = Fabricate(:status, account: current_user.account) + visit admin_account_statuses_path(account_id: current_user.account_id) + end + + context 'without selecting any records' do + it 'displays a notice about selection' do + click_on button_for_report + + expect(page).to have_content(selection_error_text) + end + end + + def button_for_report + I18n.t('admin.statuses.batch.report') + end + + def selection_error_text + I18n.t('admin.statuses.no_status_selected') + end + end +end diff --git a/spec/features/admin/trends/links/preview_card_providers_spec.rb b/spec/features/admin/trends/links/preview_card_providers_spec.rb new file mode 100644 index 0000000000..dca89117b1 --- /dev/null +++ b/spec/features/admin/trends/links/preview_card_providers_spec.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe 'Admin::Trends::Links::PreviewCardProviders' do + let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } + + before do + sign_in current_user + end + + describe 'Performing batch updates' do + before do + visit admin_trends_links_preview_card_providers_path + end + + context 'without selecting any records' do + it 'displays a notice about selection' do + click_on button_for_allow + + expect(page).to have_content(selection_error_text) + end + end + + def button_for_allow + I18n.t('admin.trends.allow') + end + + def selection_error_text + I18n.t('admin.trends.links.publishers.no_publisher_selected') + end + end +end diff --git a/spec/features/admin/trends/links_spec.rb b/spec/features/admin/trends/links_spec.rb new file mode 100644 index 0000000000..99638bc069 --- /dev/null +++ b/spec/features/admin/trends/links_spec.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe 'Admin::Trends::Links' do + let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } + + before do + sign_in current_user + end + + describe 'Performing batch updates' do + before do + visit admin_trends_links_path + end + + context 'without selecting any records' do + it 'displays a notice about selection' do + click_on button_for_allow + + expect(page).to have_content(selection_error_text) + end + end + + def button_for_allow + I18n.t('admin.trends.links.allow') + end + + def selection_error_text + I18n.t('admin.trends.links.no_link_selected') + end + end +end diff --git a/spec/features/admin/trends/statuses_spec.rb b/spec/features/admin/trends/statuses_spec.rb new file mode 100644 index 0000000000..779a15d38f --- /dev/null +++ b/spec/features/admin/trends/statuses_spec.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe 'Admin::Trends::Statuses' do + let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } + + before do + sign_in current_user + end + + describe 'Performing batch updates' do + before do + visit admin_trends_statuses_path + end + + context 'without selecting any records' do + it 'displays a notice about selection' do + click_on button_for_allow + + expect(page).to have_content(selection_error_text) + end + end + + def button_for_allow + I18n.t('admin.trends.statuses.allow') + end + + def selection_error_text + I18n.t('admin.trends.statuses.no_status_selected') + end + end +end diff --git a/spec/features/admin/trends/tags_spec.rb b/spec/features/admin/trends/tags_spec.rb new file mode 100644 index 0000000000..52e49c3a5d --- /dev/null +++ b/spec/features/admin/trends/tags_spec.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe 'Admin::Trends::Tags' do + let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } + + before do + sign_in current_user + end + + describe 'Performing batch updates' do + before do + visit admin_trends_tags_path + end + + context 'without selecting any records' do + it 'displays a notice about selection' do + click_on button_for_allow + + expect(page).to have_content(selection_error_text) + end + end + + def button_for_allow + I18n.t('admin.trends.allow') + end + + def selection_error_text + I18n.t('admin.trends.tags.no_tag_selected') + end + end +end From 6a9aab38d7294cd3c0f62fb8acf703ea58e8f48f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 13 Oct 2023 10:52:55 +0200 Subject: [PATCH 29/58] Update dependency devise-two-factor to v4.1.1 (#27382) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index dfa1846248..a47a9d0468 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -216,11 +216,11 @@ GEM railties (>= 4.1.0) responders warden (~> 1.2.3) - devise-two-factor (4.1.0) - activesupport (< 7.1) + devise-two-factor (4.1.1) + activesupport (~> 7.0) attr_encrypted (>= 1.3, < 5, != 2) devise (~> 4.0) - railties (< 7.1) + railties (~> 7.0) rotp (~> 6.0) devise_pam_authenticatable2 (9.2.0) devise (>= 4.0.0) From 773d25e8df5f32973df343a4dffdb730ef490d3d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 13 Oct 2023 11:01:40 +0200 Subject: [PATCH 30/58] New Crowdin Translations (automated) (#27388) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/fi.json | 24 ++--- config/locales/doorkeeper.fi.yml | 6 +- config/locales/fi.yml | 120 ++++++++++++------------ config/locales/simple_form.fi.yml | 18 ++-- 4 files changed, 84 insertions(+), 84 deletions(-) diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json index cef2250339..91be7bfc0e 100644 --- a/app/javascript/mastodon/locales/fi.json +++ b/app/javascript/mastodon/locales/fi.json @@ -26,10 +26,10 @@ "account.domain_blocked": "Verkkotunnus estetty", "account.edit_profile": "Muokkaa profiilia", "account.enable_notifications": "Ilmoita minulle, kun @{name} julkaisee", - "account.endorse": "Suosittele profiilissasi", + "account.endorse": "Pidä esillä profiilissa", "account.featured_tags.last_status_at": "Viimeisin julkaisu {date}", "account.featured_tags.last_status_never": "Ei julkaisuja", - "account.featured_tags.title": "Käyttäjän {name} esille nostetut aihetunnisteet", + "account.featured_tags.title": "Käyttäjän {name} esillä pidettävät aihetunnisteet", "account.follow": "Seuraa", "account.followers": "Seuraajat", "account.followers.empty": "Kukaan ei seuraa tätä käyttäjää vielä.", @@ -62,10 +62,10 @@ "account.share": "Jaa käyttäjän @{name} profiili", "account.show_reblogs": "Näytä käyttäjän @{name} tehostukset", "account.statuses_counter": "{count, plural, one {{counter} julkaisu} other {{counter} julkaisua}}", - "account.unblock": "Poista esto: @{name}", - "account.unblock_domain": "Salli palvelu {domain}", + "account.unblock": "Poista käyttäjän @{name} esto", + "account.unblock_domain": "Poista verkkotunnuksen {domain} esto", "account.unblock_short": "Poista esto", - "account.unendorse": "Poista suosittelu profiilistasi", + "account.unendorse": "Älä pidä esillä profiilissa", "account.unfollow": "Lopeta seuraaminen", "account.unmute": "Poista käyttäjän @{name} mykistys", "account.unmute_notifications_short": "Poista ilmoitusten mykistys", @@ -225,12 +225,12 @@ "empty_column.account_suspended": "Tili jäädytetty", "empty_column.account_timeline": "Ei viestejä täällä.", "empty_column.account_unavailable": "Profiilia ei löydy", - "empty_column.blocks": "Et ole estänyt käyttäjiä.", + "empty_column.blocks": "Et ole vielä estänyt käyttäjiä.", "empty_column.bookmarked_statuses": "Et ole vielä lisännyt julkaisuja kirjanmerkkeihisi. Kun lisäät yhden, se näkyy tässä.", "empty_column.community": "Paikallinen aikajana on tyhjä. Kirjoita jotain julkista, niin homma lähtee käyntiin!", "empty_column.direct": "Yksityisiä mainintoja ei vielä ole. Jos lähetät tai sinulle lähetetään sellaisia, näet ne täällä.", - "empty_column.domain_blocks": "Palveluita ei ole vielä estetty.", - "empty_column.explore_statuses": "Mikään ei trendaa nyt. Tarkista myöhemmin uudelleen!", + "empty_column.domain_blocks": "Verkkotunnuksia ei ole vielä estetty.", + "empty_column.explore_statuses": "Mikään ei ole nyt suosittua. Tarkista myöhemmin uudelleen!", "empty_column.favourited_statuses": "Sinulla ei ole vielä yhtään suosikkijulkaisua. Kun lisäät sellaisen, näkyy se tässä.", "empty_column.favourites": "Kukaan ei ole vielä lisännyt tätä julkaisua suosikkeihinsa. Kun joku tekee niin, tulee hän tähän näkyviin.", "empty_column.follow_requests": "Et ole vielä vastaanottanut seuraamispyyntöjä. Saamasi pyynnöt näkyvät täällä.", @@ -414,7 +414,7 @@ "navigation_bar.lists": "Listat", "navigation_bar.logout": "Kirjaudu ulos", "navigation_bar.mutes": "Mykistetyt käyttäjät", - "navigation_bar.opened_in_classic_interface": "Julkaisut, profiilit ja tietyt muut sivut avautuvat oletuksena perinteiseen web-käyttöliittymään.", + "navigation_bar.opened_in_classic_interface": "Julkaisut, profiilit ja tietyt muut sivut avautuvat oletuksena perinteiseen selainkäyttöliittymään.", "navigation_bar.personal": "Henkilökohtainen", "navigation_bar.pins": "Kiinnitetyt julkaisut", "navigation_bar.preferences": "Asetukset", @@ -472,7 +472,7 @@ "notifications_permission_banner.title": "Älä anna minkään mennä ohi", "onboarding.action.back": "Palaa takaisin", "onboarding.actions.back": "Palaa takaisin", - "onboarding.actions.go_to_explore": "Siirry suosituimpien aiheiden syötteeseen", + "onboarding.actions.go_to_explore": "Siirry suosittujen aiheiden syötteeseen", "onboarding.actions.go_to_home": "Siirry kotisyötteeseeni", "onboarding.compose.template": "Tervehdys #Mastodon!", "onboarding.follows.empty": "Valitettavasti tuloksia ei voida näyttää juuri nyt. Voit kokeilla hakua tai selata tutustumissivua löytääksesi seurattavaa tai yrittää myöhemmin uudelleen.", @@ -537,7 +537,7 @@ "relative_time.today": "tänään", "reply_indicator.cancel": "Peruuta", "report.block": "Estä", - "report.block_explanation": "Et näe hänen viestejään, eikä hän voi nähdä viestejäsi tai seurata sinua. Hän näkevät, että olet estänyt hänet.", + "report.block_explanation": "Et näe hänen viestejään, eikä hän voi nähdä viestejäsi tai seurata sinua. Hän näkee, että olet estänyt hänet.", "report.categories.legal": "Lakiasiat", "report.categories.other": "Muu", "report.categories.spam": "Roskaposti", @@ -694,7 +694,7 @@ "units.short.thousand": "{count} t.", "upload_area.title": "Lataa raahaamalla ja pudottamalla tähän", "upload_button.label": "Lisää kuvia, video tai äänitiedosto", - "upload_error.limit": "Tiedostolatauksien raja ylitetty.", + "upload_error.limit": "Tiedostolatauksien rajoitus ylitetty.", "upload_error.poll": "Tiedoston lataaminen ei ole sallittua äänestyksissä.", "upload_form.audio_description": "Kuvaile sisältöä kuuroille ja kuulorajoitteisille", "upload_form.description": "Kuvaile sisältöä sokeille ja näkörajoitteisille", diff --git a/config/locales/doorkeeper.fi.yml b/config/locales/doorkeeper.fi.yml index 0f263b00d5..fea01d1076 100644 --- a/config/locales/doorkeeper.fi.yml +++ b/config/locales/doorkeeper.fi.yml @@ -119,11 +119,11 @@ fi: write: Vain kirjoitusoikeus title: accounts: Tilit - admin/accounts: Tilien hallinta + admin/accounts: Tilien hallinnointi admin/all: Kaikki hallinnolliset toiminnot - admin/reports: Raporttien hallinta + admin/reports: Raporttien hallinnointi all: Täysi pääsy Mastodon-tiliisi - blocks: Torjutut + blocks: Estot bookmarks: Kirjanmerkit conversations: Keskustelut crypto: Päästä päähän -salaus diff --git a/config/locales/fi.yml b/config/locales/fi.yml index d1f345abd4..0c36b795c9 100644 --- a/config/locales/fi.yml +++ b/config/locales/fi.yml @@ -28,10 +28,10 @@ fi: title: Suorita valvontatoimi käyttäjälle %{acct} account_moderation_notes: create: Jätä muistiinpano - created_msg: Valvontamerkinnän luonti onnistui! - destroyed_msg: Valvontamerkinnän poisto onnistui! + created_msg: Valvontamuistiinpanon luonti onnistui! + destroyed_msg: Valvontamuistiinpanon poisto onnistui! accounts: - add_email_domain_block: Estä sähköpostidomain + add_email_domain_block: Estä sähköpostiverkkotunnus approve: Hyväksy approved_msg: Käyttäjän %{username} liittymishakemus hyväksyttiin are_you_sure: Oletko varma? @@ -96,10 +96,10 @@ fi: silenced: Rajoitettu suspended: Jäädytetty title: Valvonta - moderation_notes: Valvontamerkinnät + moderation_notes: Valvontamuistiinpanot most_recent_activity: Viimeisin toiminta most_recent_ip: Viimeisin IP - no_account_selected: Yhtään tiliä ei muutettu, koska mitään ei valittu + no_account_selected: Tilejä ei muutettu, koska yhtään ei ollut valittuna no_limits_imposed: Rajoituksia ei ole asetettu no_role_assigned: Roolia ei ole määritetty not_subscribed: Ei tilaaja @@ -118,7 +118,7 @@ fi: reject: Hylkää rejected_msg: Käyttäjän %{username} rekisteröitymishakemus hylättiin remote_suspension_irreversible: Tämän tilin tiedot on poistettu peruuttamattomasti. - remote_suspension_reversible_hint_html: Tili on jäädytetty heidän palvelimellaan, ja kaikki tiedot poistetaan %{date}. Sitä ennen etäpalvelin voi palauttaa tilin ongelmitta. Jos haluat poistaa kaikki tilin tiedot heti, onnistuu se alta. + remote_suspension_reversible_hint_html: Tili on jäädytetty omalla palvelimellaan, ja kaikki tiedot poistetaan %{date}. Sitä ennen etäpalvelin voi palauttaa tilin ongelmitta. Jos haluat poistaa kaikki tilin tiedot heti, onnistuu se alta. remove_avatar: Poista profiilikuva remove_header: Poista otsakekuva removed_avatar_msg: Käyttäjän %{username} avatar-kuva poistettu onnistuneesti @@ -182,7 +182,7 @@ fi: create_custom_emoji: Luo mukautettu emoji create_domain_allow: Luo verkkotunnuksen salliminen create_domain_block: Luo verkkotunnuksen esto - create_email_domain_block: Luo sähköpostin verkkotunnuksen esto + create_email_domain_block: Luo sähköpostiverkkotunnuksen esto create_ip_block: Luo IP-sääntö create_unavailable_domain: Luo ei-saatavilla oleva verkkotunnus create_user_role: Luo rooli @@ -192,7 +192,7 @@ fi: destroy_custom_emoji: Poista mukautettu emoji destroy_domain_allow: Poista verkkotunnuksen salliminen destroy_domain_block: Poista verkkotunnuksen esto - destroy_email_domain_block: Poista sähköpostin verkkotunnuksen esto + destroy_email_domain_block: Poista sähköpostiverkkotunnuksen esto destroy_instance: Tyhjennä verkkotunnus destroy_ip_block: Poista IP-sääntö destroy_status: Poista julkaisu @@ -237,21 +237,21 @@ fi: confirm_user_html: "%{name} vahvisti käyttäjän %{target} sähköpostiosoitteen" create_account_warning_html: "%{name} lähetti varoituksen käyttäjälle %{target}" create_announcement_html: "%{name} loi uuden tiedotteen %{target}" - create_canonical_email_block_html: "%{name} esti sähköpostin hashilla %{target}" + create_canonical_email_block_html: "%{name} esti sähköpostin tiivisteellä %{target}" create_custom_emoji_html: "%{name} lähetti uuden emojin %{target}" create_domain_allow_html: "%{name} salli federoinnin verkkotunnuksen %{target} kanssa" create_domain_block_html: "%{name} esti verkkotunnuksen %{target}" - create_email_domain_block_html: "%{name} esti sähköpostin %{target}" + create_email_domain_block_html: "%{name} esti sähköpostiverkkotunnuksen %{target}" create_ip_block_html: "%{name} loi IP-säännön %{target}" create_unavailable_domain_html: "%{name} pysäytti toimituksen verkkotunnukseen %{target}" create_user_role_html: "%{name} loi roolin %{target}" demote_user_html: "%{name} alensi käyttäjän %{target}" destroy_announcement_html: "%{name} poisti tiedotteen %{target}" - destroy_canonical_email_block_html: "%{name} poisti sähköpostieston hashilla %{target}" + destroy_canonical_email_block_html: "%{name} poisti sähköpostin eston tiivisteellä %{target}" destroy_custom_emoji_html: "%{name} poisti emojin %{target}" destroy_domain_allow_html: "%{name} kielsi federoinnin verkkotunnuksen %{target} kanssa" destroy_domain_block_html: "%{name} poisti verkkotunnuksen %{target} eston" - destroy_email_domain_block_html: "%{name} poisti sähköpostin verkkotunnuksen %{target} eston" + destroy_email_domain_block_html: "%{name} poisti sähköpostiverkkotunnuksen %{target} eston" destroy_instance_html: "%{name} tyhjensi verkkotunnuksen %{target}" destroy_ip_block_html: "%{name} poisti IP-säännön %{target}" destroy_status_html: "%{name} poisti käyttäjän %{target} julkaisun" @@ -332,7 +332,7 @@ fi: listed: Listalla new: title: Lisää uusi mukautettu emoji - no_emoji_selected: Emojeita ei muutettu, koska yhtään ei valittu + no_emoji_selected: Emojeita ei muutettu, koska yhtään ei ollut valittuna not_permitted: Sinulla ei ole oikeutta suorittaa tätä toimintoa overwrite: Korvaa shortcode: Lyhennekoodi @@ -382,7 +382,7 @@ fi: import: Tuo undo: Estä liitto verkkotunnukselle domain_blocks: - add_new: Lisää uusi + add_new: Lisää uusi verkkotunnuksen esto confirm_suspension: cancel: Peruuta confirm: Jäädytä @@ -409,7 +409,7 @@ fi: silence: Rajoita suspend: Jäädytä title: Uusi verkkotunnuksen esto - no_domain_block_selected: Verkkoalue-estoihin ei tehty muutoksia, koska valintoja ei tehty + no_domain_block_selected: Verkkotunnusten estoja ei muutettu, koska yhtään ei ollut valittuna not_permitted: Nykyiset käyttöoikeutesi eivät kata tätä toimintoa obfuscate: Peitä verkkotunnuksen nimi obfuscate_hint: Peitä verkkotunnus osittain luettelossa, jos julkinen verkkotunnusten rajoitusluettelo on käytössä @@ -421,14 +421,14 @@ fi: reject_media_hint: Poistaa paikallisesti tallennetut mediatiedostot eikä lataa niitä enää jatkossa. Ei merkitystä jäähyn kohdalla reject_reports: Hylkää raportit reject_reports_hint: Ohita kaikki tästä verkkotunnuksesta tulevat raportit. Erottamisen kannalta ei merkitystä - undo: Peru + undo: Peru verkkotunnuksen esto view: Näytä verkkotunnuksen esto email_domain_blocks: add_new: Lisää uusi attempts_over_week: one: "%{count} yritystä viimeisen viikon aikana" other: "%{count} rekisteröitymisyritystä viimeisen viikon aikana" - created_msg: Sähköpostiverkkotunnuksen lisäys estolistalle onnistui + created_msg: Sähköpostiverkkotunnus estetty onnistuneesti delete: Poista dns: types: @@ -437,26 +437,26 @@ fi: new: create: Lisää verkkotunnus resolve: Ratkaise verkkotunnus - title: Uusi sähköpostiestolistan merkintä - no_email_domain_block_selected: Sähköpostin verkkotunnuksia ei muutettu, koska yhtään ei valittu + title: Estä uusi sähköpostiverkkotunnus + no_email_domain_block_selected: Sähköpostin verkkotunnuksia ei muutettu, koska yhtään ei ollut valittuna not_permitted: Ei sallittu resolved_dns_records_hint_html: Verkkotunnuksen nimi määräytyy seuraaviin MX-verkkotunnuksiin, jotka ovat viime kädessä vastuussa sähköpostin vastaanottamisesta. MX-verkkotunnuksen estäminen estää kirjautumisen mistä tahansa sähköpostiosoitteesta, joka käyttää samaa MX-verkkotunnusta, vaikka näkyvä verkkotunnuksen nimi olisikin erilainen. Varo estämästä suuria sähköpostin palveluntarjoajia. resolved_through_html: Ratkaistu %{domain} kautta - title: Sähköpostiestolista + title: Estetyt sähköpostiverkkotunnukset export_domain_allows: new: - title: Tuo sallitut verkkoalueet + title: Tuo sallittuja verkkotunnuksia no_file: Yhtäkään tiedostoa ei ole valittu export_domain_blocks: import: description_html: Olet tuomassa verkkotunnusten estoluetteloa. Tarkista luettelo huolella – etenkin, jos et ole laatinut sitä itse. existing_relationships_warning: Olemassa olevat seuraussuhteet - private_comment_description_html: 'Tuodun estolistan alkuperän selvillä pitämiseksi, lisätään tietojen yhteyteen seuraava yksityinen kommentti: %{comment}' - private_comment_template: Tuotu lähteestä %{source}, pvm %{date} - title: Tuo luettelo verkkoalue-estoista - invalid_domain_block: 'Yksi tai useampi verkkotunnuksen lohko ohitettiin seuraavien virheiden vuoksi: %{error}' + private_comment_description_html: 'Seurataksesi tuotujen estojen alkuperää lisätään estojen yhteyteen seuraava yksityinen kommentti: %{comment}' + private_comment_template: Tuotu lähteestä %{source} %{date} + title: Tuo verkkotunnusten estoja + invalid_domain_block: 'Yksi tai useampi verkkotunnuksen esto ohitettiin seuraavien virheiden vuoksi: %{error}' new: - title: Tuo luettelo verkkoalue-estoista + title: Tuo verkkotunnusten estoja no_file: Yhtäkään tiedostoa ei ole valittu follow_recommendations: description_html: "Seuraamissuositukset auttavat uusia käyttäjiä löytämään nopeasti kiinnostavaa sisältöä. Kun käyttäjä ei ole ollut tarpeeksi vuorovaikutuksessa muiden kanssa, jotta hänelle olisi muodostunut henkilökohtaisia seuraamissuosituksia, suositellaan niiden sijaan näitä tilejä. Ne lasketaan päivittäin uudelleen yhdistelmästä tilejä, jotka ovat viime aikoina olleet aktiivisimmin sitoutuneita ja joilla on suurimmat paikalliset seuraajamäärät tietyllä kielellä." @@ -482,9 +482,9 @@ fi: back_to_limited: Rajoitettu back_to_warning: Varoitus by_domain: Verkkotunnus - confirm_purge: Oletko varma, että haluat pysyvästi poistaa tiedot tältä verkkotunnukselta? + confirm_purge: Haluatko varmasti poistaa pysyvästi tämän verkkotunnuksen tiedot? content_policies: - comment: Sisäinen huomautus + comment: Sisäinen muistiinpano description_html: Voit määrittää sisältökäytännöt, joita sovelletaan kaikkiin tämän verkkotunnuksen ja sen aliverkkotunnuksien tileihin. limited_federation_mode_description_html: Voit valita sallitaanko federointi tällä verkkotunnuksella. policies: @@ -528,7 +528,7 @@ fi: purge: Tyhjennä purge_description_html: Jos uskot, että tämä verkkotunnus on offline-tilassa tarkoituksella, voit poistaa kaikki verkkotunnuksen tilitietueet ja niihin liittyvät tiedot tallennustilastasi. Tämä voi kestää jonkin aikaa. title: Federointi - total_blocked_by_us: Estetty meidän toimesta + total_blocked_by_us: Estämämme total_followed_by_them: Heidän seuraama total_followed_by_us: Meidän seuraama total_reported: Niitä koskevat raportit @@ -555,7 +555,7 @@ fi: '94670856': 3 vuotta new: title: Luo uusi IP-sääntö - no_ip_block_selected: IP-sääntöjä ei muutettu, koska yhtään ei ole valittuna + no_ip_block_selected: IP-sääntöjä ei muutettu, koska yhtään ei ollut valittuna title: IP-säännöt relationships: title: "%{acct}n suhteet" @@ -576,13 +576,13 @@ fi: status: Tila title: Välittäjät report_notes: - created_msg: Muistiinpano onnistuneesti lisätty raporttiin! - destroyed_msg: Muistiinpano onnistuneesti poistettu raportista! + created_msg: Muistiinpano lisätty raporttiin onnistuneesti! + destroyed_msg: Muistiinpano poistettu raportista onnistuneesti! reports: account: notes: - one: "%{count} ilmoitus" - other: "%{count} ilmoitusta" + one: "%{count} muistiinpano" + other: "%{count} muistiinpanoa" action_log: Tarkastusloki action_taken_by: Toimen tehnyt actions: @@ -621,8 +621,8 @@ fi: create_and_unresolve: Avaa uudelleen ja lisää muistiinpano delete: Poista placeholder: Kuvaile mitä toimia on tehty tai muita päivityksiä tähän raporttiin… - title: Merkinnät - notes_description_html: Tarkastele ja jätä merkintöjä muille valvojille ja itsellesi tulevaisuuteen + title: Muistiinpanot + notes_description_html: Tarkastele ja jätä muistiinpanoja muille valvojille ja itsellesi tulevaisuuteen processed_msg: 'Raportti #%{id} käsitelty' quick_actions_description_html: 'Suorita nopea toiminto tai vieritä alas nähdäksesi raportoitu sisältö:' remote_user_placeholder: etäkäyttäjä instanssista %{instance} @@ -708,7 +708,7 @@ fi: manage_settings: Hallitse asetuksia manage_settings_description: Sallii käyttäjien muuttaa sivuston asetuksia manage_taxonomies: Hallitse luokittelua - manage_taxonomies_description: Sallii käyttäjien tarkistaa nousussa olevan sisällön ja päivittää aihetunnisteiden asetuksia + manage_taxonomies_description: Sallii käyttäjien tarkistaa suositun sisällön ja päivittää aihetunnisteiden asetuksia manage_user_access: Hallitse käyttäjäoikeuksia manage_user_access_description: Sallii käyttäjien poistaa muiden käyttäjien kaksivaiheinen todennus käytöstä, vaihtaa heidän sähköpostiosoitteensa ja nollata heidän salasanansa manage_users: Hallitse käyttäjiä @@ -736,10 +736,10 @@ fi: rules_hint: On olemassa erityinen alue sääntöjä, joita käyttäjien odotetaan noudattavan. title: Tietoja appearance: - preamble: Mukauta Mastodonin verkkokäyttöliittymää. + preamble: Mukauta Mastodonin selainkäyttöliittymää. title: Ulkoasu branding: - preamble: Palvelimesi brändäys erottaa sen muista verkon palvelimista. Nämä tiedot voivat näkyä monissa eri ympäristöissä, kuten Mastodonin verkkokäyttöliittymässä, natiivisovelluksissa, linkkien esikatseluissa muilla sivustoilla, viestintäsovelluksissa ja niin edelleen. Siksi nämä tiedot kannattaa pitää selkeinä, lyhyinä ja ytimekkäinä. + preamble: Palvelimesi brändäys erottaa sen muista verkon palvelimista. Nämä tiedot voivat näkyä monissa eri ympäristöissä, kuten Mastodonin selainkäyttöliittymässä, natiivisovelluksissa, linkkien esikatseluissa muilla sivustoilla, viestintäsovelluksissa ja niin edelleen. Siksi nämä tiedot kannattaa pitää selkeinä, lyhyinä ja ytimekkäinä. title: Brändäys captcha_enabled: desc_html: Tämä perustuu ulkoisiin skripteihin hCaptchasta, mikä voi olla turvallisuus- ja yksityisyysongelma. Lisäksi tämä voi tehdä rekisteröinnin ihmisille huomattavasti (erityisesti vammaisten) helpommaksi. Harkitse vaihtoehtoisia toimenpiteitä, kuten hyväksymisperusteista tai kutsupohjaista rekisteröintiä. @@ -808,13 +808,13 @@ fi: media: title: Media metadata: Metadata - no_status_selected: Julkaisuja ei muutettu, koska yhtään ei ole valittuna + no_status_selected: Julkaisuja ei muutettu, koska yhtään ei ollut valittuna open: Avaa julkaisu original_status: Alkuperäinen julkaisu reblogs: Edelleen jako status_changed: Julkaisua muutettu title: Tilin tilat - trending: Nousussa + trending: Suosituttua visibility: Näkyvyys with_media: Sisältää mediaa strikes: @@ -882,9 +882,9 @@ fi: description_html: Nämä ovat linkkejä, joita jaetaan tällä hetkellä paljon tileillä, joilta palvelimesi näkee viestejä. Se voi auttaa käyttäjiäsi saamaan selville, mitä maailmassa tapahtuu. Linkkejä ei näytetä julkisesti, ennen kuin hyväksyt julkaisijan. Voit myös sallia tai hylätä yksittäiset linkit. disallow: Hylkää linkki disallow_provider: Estä julkaisija - no_link_selected: Yhtään linkkiä ei muutettu, koska yhtään ei valittu + no_link_selected: Linkkejä ei muutettu, koska yhtään ei ollut valittuna publishers: - no_publisher_selected: Julkaisijoita ei muutettu, koska yhtään ei valittu + no_publisher_selected: Julkaisijoita ei muutettu, koska yhtään ei ollut valittuna shared_by_over_week: one: Yksi henkilö jakanut viimeisen viikon aikana other: Jakanut %{count} henkilöä viimeisen viikon aikana @@ -905,7 +905,7 @@ fi: description_html: Nämä ovat julkaisuja, joita palvelimesi tietää jaettavan ja lisättävän suosikkeihin paljon tällä hetkellä. Listaus voi auttaa uusia ja palaavia käyttäjiäsi löytämään lisää seurattavia. Julkaisut eivät näy julkisesti ennen kuin hyväksyt niiden julkaisijan ja julkaisija sallii tilinsä ehdottamisen. Voit myös sallia tai hylätä yksittäisiä julkaisuja. disallow: Kiellä julkaisu disallow_account: Estä tekijä - no_status_selected: Suosittuja julkaisuja ei muutettu, koska yhtään ei ole valittuna + no_status_selected: Suosittuja julkaisuja ei muutettu, koska yhtään ei ollut valittuna not_discoverable: Tekijä ei ole ilmoittanut olevansa löydettävissä shared_by: one: Jaettu tai lisätty suosikkeihin kerran @@ -921,21 +921,21 @@ fi: tag_uses_measure: käyttökerrat description_html: Nämä ovat aihetunnisteita, jotka näkyvät tällä hetkellä monissa julkaisuissa, jotka palvelimesi näkee. Tämä voi auttaa käyttäjiäsi selvittämään, mistä ihmiset puhuvat eniten tällä hetkellä. Mitään aihetunnisteita ei näytetä julkisesti, ennen kuin hyväksyt ne. listable: Voidaan ehdottaa - no_tag_selected: Yhtään tagia ei muutettu, koska yhtään ei valittu + no_tag_selected: Tunnisteita ei muutettu, koska yhtään ei ollut valittuna not_listable: Ei tulla ehdottamaan not_trendable: Ei näy trendien alla not_usable: Ei voida käyttää peaked_on_and_decaying: Saavutti huipun %{date}, nyt hiipuu title: Suositut aihetunnisteet trendable: Voi näkyä trendien alla - trending_rank: 'Nousussa #%{rank}' + trending_rank: 'Suosittua #%{rank}' usable: Voidaan käyttää usage_comparison: Käytetty %{today} kertaa tänään, verrattuna %{yesterday} eiliseen used_by_over_week: one: Yhden henkilön käyttämä viime viikon aikana other: Käyttänyt %{count} henkilöä viimeisen viikon aikana title: Trendit - trending: Nousussa + trending: Suosittua warning_presets: add_new: Lisää uusi delete: Poista @@ -995,8 +995,8 @@ fi: new_trending_statuses: title: Suositut julkaisut new_trending_tags: - no_approved_tags: Tällä hetkellä ei ole hyväksyttyjä trendikkäitä aihetunnisteita. - requirements: 'Mikä tahansa näistä ehdokkaista voisi ylittää #%{rank} hyväksytyn trendikkään aihetunnisteen, joka on tällä hetkellä #%{lowest_tag_name} arvosanalla %{lowest_tag_score}.' + no_approved_tags: Tällä hetkellä ei ole hyväksyttyjä suosittuja aihetunnisteita. + requirements: 'Mikä tahansa näistä ehdokkaista voisi ylittää #%{rank} hyväksytyn suositun aihetunnisteen, joka on tällä hetkellä #%{lowest_tag_name} %{lowest_tag_score} pisteellä.' title: Suositut aihetunnisteet subject: Uusia trendejä tarkistettavaksi instanssissa %{instance} aliases: @@ -1008,7 +1008,7 @@ fi: remove: Poista aliaksen linkitys appearance: advanced_web_interface: Edistynyt selainkäyttöliittymä - advanced_web_interface_hint: 'Jos haluat hyödyntää näytön koko leveyttä, edistyneen webkäyttöliittymän avulla voit määrittää useita erilaisia sarakkeita, niin näet kerralla niin paljon tietoa kuin haluat: kotisyöte, ilmoitukset, yleinen aikajana, mikä tahansa määrä listoja ja aihetunnisteita.' + advanced_web_interface_hint: 'Jos haluat hyödyntää näytön koko leveyttä, edistyneen selainkäyttöliittymän avulla voit määrittää useita erilaisia sarakkeita, niin näet kerralla niin paljon tietoa kuin haluat: kotisyöte, ilmoitukset, yleinen aikajana, mikä tahansa määrä listoja ja aihetunnisteita.' animations_and_accessibility: Animaatiot ja saavutettavuus confirmation_dialogs: Vahvistusvalinnat discovery: Löytäminen @@ -1220,8 +1220,8 @@ fi: featured_tags: add_new: Lisää uusi errors: - limit: Olet jo nostanut esille enimmäismäärän aihetunnisteita - hint_html: "Mitä ovat näkyvillä olevat hashtagit eli aihetunnisteet? Ne ovat näkyvissä julkisessa profiilissasi ja niiden avulla ihmiset voivat selata julkisia viestejäsi nimenomaan näiden aihetunnisteiden alla. Ne auttavat esimerkiksi luovan työn tai pitkäaikaisten projektien seurannassa." + limit: Pidät jo esillä aihetunnisteiden enimmäismäärää + hint_html: "Pidä tärkeimpiä aihetunnisteitasi esillä profiilissasi. Erinomainen työkalu, jolla pidät kirjaa luovista teoksistasi ja pitkäaikaisista projekteistasi. Esillä pitämäsi aihetunnisteet ovat näyttävällä paikalla profiilissasi ja mahdollistavat nopean pääsyn omiin julkaisuihisi." filters: contexts: account: Profiilit @@ -1236,7 +1236,7 @@ fi: statuses_hint_html: Tämä suodatin koskee yksittäisten julkaisujen valintaa riippumatta siitä, vastaavatko ne alla olevia avainsanoja. Tarkista tai poista julkaisut suodattimesta. title: Muokkaa suodatinta errors: - deprecated_api_multiple_keywords: Näitä parametreja ei voi muuttaa tästä sovelluksesta, koska ne koskevat useampaa kuin yhtä suodattimen avainsanaa. Käytä uudempaa sovellusta tai verkkokäyttöliittymää. + deprecated_api_multiple_keywords: Näitä parametreja ei voi muuttaa tästä sovelluksesta, koska ne koskevat useampaa kuin yhtä suodattimen avainsanaa. Käytä uudempaa sovellusta tai selainkäyttöliittymää. invalid_context: Ei sisältöä tai se on virheellinen index: contexts: Suodattimet %{contexts} @@ -1262,7 +1262,7 @@ fi: batch: remove: Poista suodattimista index: - hint: Tämä suodatin koskee yksittäisten julkaisujen valintaa muista kriteereistä riippumatta. Voit lisätä lisää julkaisuja tähän suodattimeen verkkokäyttöliittymästä. + hint: Tämä suodatin koskee yksittäisten julkaisujen valintaa muista kriteereistä riippumatta. Voit lisätä lisää julkaisuja tähän suodattimeen selainkäyttöliittymästä. title: Suodatetut julkaisut generic: all: Kaikki @@ -1291,7 +1291,7 @@ fi: imports: errors: empty: Tyhjä CSV-tiedosto - incompatible_type: Yhteensopimaton valitun tuontilajin kanssa + incompatible_type: Yhteensopimaton valitun tuontityypin kanssa invalid_csv_file: 'Epäkelpo CSV-tiedosto. Virhe: %{error}' over_rows_processing_limit: sisältää yli %{count} riviä too_large: Tiedosto on liian suuri @@ -1332,8 +1332,8 @@ fi: bookmarks: Tuodaan kirjanmerkkejä domain_blocking: Tuodaan estettyjä verkkotunnuksia following: Tuodaan seurattuja tilejä - lists: Listojen tuonti - muting: Tuodaan hiljennettyjä tilejä + lists: Tuodaan listoja + muting: Tuodaan mykistettyjä tilejä type: Tuonnin tyyppi type_groups: constructive: Seuratut ja kirjanmerkit @@ -1341,7 +1341,7 @@ fi: types: blocking: Estoluettelo bookmarks: Kirjanmerkit - domain_blocking: Verkkotunnuksen estoluettelo + domain_blocking: Verkkotunnusten estoluettelo following: Seurattujen luettelo lists: Listat muting: Mykistettyjen luettelo @@ -1437,7 +1437,7 @@ fi: title: Valvonta move_handler: carry_blocks_over_text: Tämä käyttäjä siirtyi paikasta %{acct}, jonka olit estänyt. - carry_mutes_over_text: Tämä käyttäjä siirtyi paikasta %{acct}, jonka mykistit. + carry_mutes_over_text: Tämä käyttäjä siirtyi tililtä %{acct}, jonka olet mykistänyt. copy_account_note_text: 'Tämä käyttäjä siirtyi paikasta %{acct}, tässä olivat aiemmat muistiinpanosi niistä:' navigation: toggle_menu: Avaa/sulje valikko @@ -1626,7 +1626,7 @@ fi: development: Kehitys edit_profile: Muokkaa profiilia export: Vie tietoja - featured_tags: Esiteltävät aihetunnisteet + featured_tags: Esillä pidettävät aihetunnisteet import: Tuo import_and_export: Tuonti ja vienti migrate: Tilin muutto muualle diff --git a/config/locales/simple_form.fi.yml b/config/locales/simple_form.fi.yml index 189f9f8eb4..f73667f5cc 100644 --- a/config/locales/simple_form.fi.yml +++ b/config/locales/simple_form.fi.yml @@ -78,11 +78,11 @@ fi: form_admin_settings: activity_api_enabled: Paikallisesti julkaistujen julkaisujen, aktiivisten käyttäjien ja rekisteröitymisten viikoittainen määrä backups_retention_period: Säilytä luodut arkistot määritetyn määrän päiviä. - bootstrap_timeline_accounts: Nämä tilit kiinnitetään uusien käyttäjien suositusten yläpuolelle. + bootstrap_timeline_accounts: Nämä tilit kiinnitetään uusien käyttäjien seuraamissuositusten yläpuolelle. closed_registrations_message: Näkyy, kun ilmoittautuminen on suljettu content_cache_retention_period: Viestit muilta palvelimilta poistetaan määritetyn määrän päiviä jälkeen, kun arvo on asetettu positiiviseksi. Tämä voi olla peruuttamatonta. custom_css: Voit käyttää mukautettuja tyylejä Mastodonin verkkoversiossa. - mascot: Ohittaa kuvituksen edistyneessä käyttöliittymässä. + mascot: Ohittaa kuvituksen edistyneessä selainkäyttöliittymässä. media_cache_retention_period: Ladatut mediatiedostot poistetaan määritetyn määrän päiviä jälkeen, kun arvo on positiivinen ja ladataan uudelleen pyynnöstä. peers_api_enabled: Luettelo verkkotunnuksista, jotka tämä palvelin on kohdannut fediversumissa. Se ei kerro, oletko liitossa tietyn palvelimen kanssa, vaan että palvelimesi on ylipäätään tietoinen siitä. Tätä tietoa käytetään palveluissa, jotka keräävät tilastoja liittoutumisesta yleisellä tasolla. profile_directory: Profiilihakemisto lueteloi kaikki käyttäjät, jotka ovat ilmoittaneet olevansa löydettävissä. @@ -109,7 +109,7 @@ fi: ip_block: comment: Valinnainen. Muista miksi lisäsit tämän säännön. expires_in: IP-osoitteet ovat rajallinen resurssi, joskus niitä jaetaan ja vaihtavat usein omistajaa. Tästä syystä epämääräisiä IP-lohkoja ei suositella. - ip: Kirjoita IPv4- tai IPv6-osoite. Voit estää kokonaisia alueita käyttämällä CIDR-syntaksia. Varo, että et lukitse itseäsi! + ip: Kirjoita IPv4- tai IPv6-osoite. Voit estää kokonaisia alueita käyttämällä CIDR-syntaksia. Varo, että et lukitse itseäsi ulos! severities: no_access: Estä pääsy kaikkiin resursseihin sign_up_block: Uudet kirjautumiset eivät ole mahdollisia @@ -140,7 +140,7 @@ fi: url: Mihin tapahtumat lähetetään labels: account: - discoverable: Nosta profiili ja julkaisut esille löytämisalgoritmeissa + discoverable: Pidä profiiliasi ja julkaisujasi esillä löytämisalgoritmeissa fields: name: Nimike value: Sisältö @@ -163,8 +163,8 @@ fi: disable: Poista kirjautuminen käytöstä none: Älä tee mitään sensitive: Arkaluonteinen - silence: Hiljennä - suspend: Poista käytöstä ja tuhoa käyttäjätunnuksen tiedot peruuttamattomasti + silence: Rajoita + suspend: Jäädytä warning_preset_id: Käytä varoitusmallia announcement: all_day: Koko päivän kestävä tapahtuma @@ -225,7 +225,7 @@ fi: severity: Vakavuus sign_in_token_attempt: Turvakoodi title: Nimi - type: Tuontilaji + type: Tuontityyppi username: Käyttäjänimi username_or_email: Käyttäjänimi tai sähköpostiosoite whole_word: Koko sana @@ -250,7 +250,7 @@ fi: profile_directory: Ota profiilihakemisto käyttöön registrations_mode: Kuka voi rekisteröityä require_invite_text: Vaadi syy liittyä - show_domain_blocks: Näytä domainestot + show_domain_blocks: Näytä verkkotunnusten estot show_domain_blocks_rationale: Näytä miksi verkkotunnukset on estetty site_contact_email: Ota yhteyttä sähköpostilla site_contact_username: Yhteyshenkilön käyttäjänimi @@ -278,7 +278,7 @@ fi: ip: IP-osoite severities: no_access: Estä pääsy - sign_up_block: Estä kirjautumiset + sign_up_block: Estä rekisteröitymiset sign_up_requires_approval: Rajoita rekisteröitymisiä severity: Sääntö notification_emails: From 45bdd60f3c268363c28da6e20144eed6c450a29b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Fri, 13 Oct 2023 18:15:47 +0900 Subject: [PATCH 31/58] Fix when unfollow a tag, my post also disappears from the home timeline (#27391) --- app/lib/feed_manager.rb | 1 + spec/lib/feed_manager_spec.rb | 38 +++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb index 26e5b78e8f..8b7f208115 100644 --- a/app/lib/feed_manager.rb +++ b/app/lib/feed_manager.rb @@ -192,6 +192,7 @@ class FeedManager # also tagged with another followed hashtag or from a followed user scope = from_tag.statuses .where(id: timeline_status_ids) + .where.not(account: into_account) .where.not(account: into_account.following) .tagged_with_none(TagFollow.where(account: into_account).pluck(:tag_id)) diff --git a/spec/lib/feed_manager_spec.rb b/spec/lib/feed_manager_spec.rb index 25edaada64..f4dd42f845 100644 --- a/spec/lib/feed_manager_spec.rb +++ b/spec/lib/feed_manager_spec.rb @@ -525,6 +525,44 @@ RSpec.describe FeedManager do end end + describe '#unmerge_tag_from_home' do + let(:receiver) { Fabricate(:account) } + let(:tag) { Fabricate(:tag) } + + it 'leaves a tagged status' do + status = Fabricate(:status) + status.tags << tag + described_class.instance.push_to_home(receiver, status) + + described_class.instance.unmerge_tag_from_home(tag, receiver) + + expect(redis.zrange("feed:home:#{receiver.id}", 0, -1)).to_not include(status.id.to_s) + end + + it 'remains a tagged status written by receiver\'s followee' do + followee = Fabricate(:account) + receiver.follow!(followee) + + status = Fabricate(:status, account: followee) + status.tags << tag + described_class.instance.push_to_home(receiver, status) + + described_class.instance.unmerge_tag_from_home(tag, receiver) + + expect(redis.zrange("feed:home:#{receiver.id}", 0, -1)).to include(status.id.to_s) + end + + it 'remains a tagged status written by receiver' do + status = Fabricate(:status, account: receiver) + status.tags << tag + described_class.instance.push_to_home(receiver, status) + + described_class.instance.unmerge_tag_from_home(tag, receiver) + + expect(redis.zrange("feed:home:#{receiver.id}", 0, -1)).to include(status.id.to_s) + end + end + describe '#clear_from_home' do let(:account) { Fabricate(:account) } let(:followed_account) { Fabricate(:account) } From 6451b853e76cf2059e8605e8db553efce9c86927 Mon Sep 17 00:00:00 2001 From: KMY Date: Fri, 13 Oct 2023 18:37:43 +0900 Subject: [PATCH 32/58] =?UTF-8?q?Change:=20#82=20=E3=83=95=E3=83=AC?= =?UTF-8?q?=E3=83=B3=E3=83=89=E7=94=B3=E8=AB=8B=E6=99=82=E3=80=81=E8=87=AA?= =?UTF-8?q?=E5=88=86=E3=81=AE=E3=82=B5=E3=83=BC=E3=83=90=E3=83=BC=E3=81=AE?= =?UTF-8?q?Inbox=20URL=E3=82=92=E4=BC=9D=E3=81=88=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/lib/activitypub/activity/follow.rb | 2 +- app/models/friend_domain.rb | 11 +++++------ spec/lib/activitypub/activity/follow_spec.rb | 20 ++++++++++++++++++++ spec/models/friend_domain_spec.rb | 1 + 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/app/lib/activitypub/activity/follow.rb b/app/lib/activitypub/activity/follow.rb index f5a0250163..fdded98440 100644 --- a/app/lib/activitypub/activity/follow.rb +++ b/app/lib/activitypub/activity/follow.rb @@ -53,7 +53,7 @@ class ActivityPub::Activity::Follow < ActivityPub::Activity friend.update!(passive_state: :pending, active_state: :idle, passive_follow_activity_id: @json['id']) else @friend = FriendDomain.new(domain: @account.domain, passive_state: :pending, passive_follow_activity_id: @json['id']) - @friend.initialize_inbox_url! + @friend.inbox_url = @json['inboxUrl'].presence || @friend.default_inbox_url @friend.save! end diff --git a/app/models/friend_domain.rb b/app/models/friend_domain.rb index 28cc59b334..0842500033 100644 --- a/app/models/friend_domain.rb +++ b/app/models/friend_domain.rb @@ -93,16 +93,12 @@ class FriendDomain < ApplicationRecord destroy! end - def initialize_inbox_url! - self.inbox_url = default_inbox_url - end - - private - def default_inbox_url "https://#{domain}/inbox" end + private + def delete_for_friend! activity_id = ActivityPub::TagManager.instance.generate_uri_for(nil) payload = Oj.dump(delete_follow_activity(activity_id)) @@ -118,6 +114,9 @@ class FriendDomain < ApplicationRecord type: 'Follow', actor: ActivityPub::TagManager.instance.uri_for(some_local_account), object: ActivityPub::TagManager::COLLECTIONS[:public], + + # Cannot use inbox_url method because this model also has inbox_url column + inboxUrl: "https://#{Rails.configuration.x.web_domain}/inbox", } end diff --git a/spec/lib/activitypub/activity/follow_spec.rb b/spec/lib/activitypub/activity/follow_spec.rb index c27696ebaf..53ce9a29a6 100644 --- a/spec/lib/activitypub/activity/follow_spec.rb +++ b/spec/lib/activitypub/activity/follow_spec.rb @@ -310,6 +310,7 @@ RSpec.describe ActivityPub::Activity::Follow do let!(:friend) { Fabricate(:friend_domain, domain: 'abc.com', passive_state: :idle) } let!(:owner_user) { Fabricate(:user, role: UserRole.find_by(name: 'Owner')) } let!(:patch_user) { Fabricate(:user, role: Fabricate(:user_role, name: 'OhagiOps', permissions: UserRole::FLAGS[:manage_federation])) } + let(:inbox_url) { nil } let(:json) do { @@ -318,6 +319,7 @@ RSpec.describe ActivityPub::Activity::Follow do type: 'Follow', actor: ActivityPub::TagManager.instance.uri_for(sender), object: 'https://www.w3.org/ns/activitystreams#Public', + inboxUrl: inbox_url, }.with_indifferent_access end @@ -343,6 +345,24 @@ RSpec.describe ActivityPub::Activity::Follow do end end + context 'when no record and inbox_url is specified' do + let(:inbox_url) { 'https://ohagi.com/inbox' } + + before do + friend.update(domain: 'def.com') + end + + it 'marks the friend as pending' do + subject.perform + + friend = FriendDomain.find_by(domain: 'abc.com') + expect(friend).to_not be_nil + expect(friend.they_are_pending?).to be true + expect(friend.passive_follow_activity_id).to eq 'foo' + expect(friend.inbox_url).to eq 'https://ohagi.com/inbox' + end + end + context 'when my server is pending' do before do friend.update(active_state: :pending) diff --git a/spec/models/friend_domain_spec.rb b/spec/models/friend_domain_spec.rb index 647c39e5a8..65d090f9a7 100644 --- a/spec/models/friend_domain_spec.rb +++ b/spec/models/friend_domain_spec.rb @@ -21,6 +21,7 @@ describe FriendDomain do type: 'Follow', actor: 'https://cb6e6126.ngrok.io/actor', object: 'https://www.w3.org/ns/activitystreams#Public', + inboxUrl: 'https://cb6e6126.ngrok.io/inbox', }))).to have_been_made.once end end From 5c287c4958a2bf87db79064aa0e8a70d71e58b99 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 13 Oct 2023 11:46:25 +0200 Subject: [PATCH 33/58] Update dependency rubocop to v1.57.1 (#27389) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index a47a9d0468..0068df461b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -620,7 +620,7 @@ GEM sidekiq (>= 5, < 8) rspec-support (3.12.1) rspec_chunked (0.6) - rubocop (1.57.0) + rubocop (1.57.1) base64 (~> 0.1.1) json (~> 2.3) language_server-protocol (>= 3.17.0) From 77098c6f1c25958960df98a1510b28352a39704f Mon Sep 17 00:00:00 2001 From: Renaud Chaput Date: Fri, 13 Oct 2023 12:01:33 +0200 Subject: [PATCH 34/58] Delete .github/FUNDING.yml (#27390) --- .github/FUNDING.yml | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index be750a5e41..0000000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,3 +0,0 @@ -patreon: mastodon -open_collective: mastodon -custom: https://sponsor.joinmastodon.org From 61b8693022e1f03f87b1a50eda2b448c1844633d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Fri, 13 Oct 2023 19:13:44 +0900 Subject: [PATCH 35/58] =?UTF-8?q?Change:=20#100=20=E3=83=AA=E3=83=A2?= =?UTF-8?q?=E3=83=BC=E3=83=88=E3=81=AE=E3=82=B9=E3=82=BF=E3=83=B3=E3=83=97?= =?UTF-8?q?=E3=81=AB=E7=9B=B8=E4=B9=97=E3=82=8A=E3=81=97=E3=81=9F=E6=99=82?= =?UTF-8?q?=E3=80=81=E3=81=9D=E3=82=8C=E3=82=92=E3=83=95=E3=82=A9=E3=83=AD?= =?UTF-8?q?=E3=83=AF=E3=83=BC=E3=81=AE=E3=81=84=E3=82=8B=E3=82=B5=E3=83=BC?= =?UTF-8?q?=E3=83=90=E3=83=BC=E3=81=AB=E9=85=8D=E9=80=81=20(#111)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/emoji_reaction.rb | 4 ---- app/services/emoji_react_service.rb | 1 - 2 files changed, 5 deletions(-) diff --git a/app/models/emoji_reaction.rb b/app/models/emoji_reaction.rb index 5d6d58513c..a562865f3a 100644 --- a/app/models/emoji_reaction.rb +++ b/app/models/emoji_reaction.rb @@ -39,10 +39,6 @@ class EmojiReaction < ApplicationRecord custom_emoji.present? end - def remote_custom_emoji? - custom_emoji? && !custom_emoji.local? - end - def sign? status&.distributable_friend? end diff --git a/app/services/emoji_react_service.rb b/app/services/emoji_react_service.rb index 250868b3bc..c3135bdff2 100644 --- a/app/services/emoji_react_service.rb +++ b/app/services/emoji_react_service.rb @@ -62,7 +62,6 @@ class EmojiReactService < BaseService status = emoji_reaction.status return unless status.account.local? - return if emoji_reaction.remote_custom_emoji? ActivityPub::RawDistributionWorker.perform_async(build_json(emoji_reaction), status.account_id) end From 4230d1ee0a0752e0259e96e1590f7eb9fb1ebb9b Mon Sep 17 00:00:00 2001 From: Daniel M Brasil Date: Fri, 13 Oct 2023 09:04:37 -0300 Subject: [PATCH 36/58] Migrate to request specs in `/api/v1/timelines/tag/:hashtag` (#25797) --- .../api/v1/timelines/tag_controller_spec.rb | 71 ----------- spec/requests/api/v1/timelines/tag_spec.rb | 112 ++++++++++++++++++ 2 files changed, 112 insertions(+), 71 deletions(-) delete mode 100644 spec/controllers/api/v1/timelines/tag_controller_spec.rb create mode 100644 spec/requests/api/v1/timelines/tag_spec.rb diff --git a/spec/controllers/api/v1/timelines/tag_controller_spec.rb b/spec/controllers/api/v1/timelines/tag_controller_spec.rb deleted file mode 100644 index 1c60798fcf..0000000000 --- a/spec/controllers/api/v1/timelines/tag_controller_spec.rb +++ /dev/null @@ -1,71 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -describe Api::V1::Timelines::TagController do - render_views - - let(:user) { Fabricate(:user) } - let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:statuses') } - - before do - allow(controller).to receive(:doorkeeper_token) { token } - end - - describe 'GET #show' do - subject do - get :show, params: { id: 'test' } - end - - before do - PostStatusService.new.call(user.account, text: 'It is a #test') - end - - context 'when the instance allows public preview' do - context 'when the user is not authenticated' do - let(:token) { nil } - - it 'returns http success', :aggregate_failures do - subject - - expect(response).to have_http_status(200) - expect(response.headers['Link'].links.size).to eq(2) - end - end - - context 'when the user is authenticated' do - it 'returns http success', :aggregate_failures do - subject - - expect(response).to have_http_status(200) - expect(response.headers['Link'].links.size).to eq(2) - end - end - end - - context 'when the instance does not allow public preview' do - before do - Form::AdminSettings.new(timeline_preview: false).save - end - - context 'when the user is not authenticated' do - let(:token) { nil } - - it 'returns http unauthorized' do - subject - - expect(response).to have_http_status(401) - end - end - - context 'when the user is authenticated' do - it 'returns http success', :aggregate_failures do - subject - - expect(response).to have_http_status(200) - expect(response.headers['Link'].links.size).to eq(2) - end - end - end - end -end diff --git a/spec/requests/api/v1/timelines/tag_spec.rb b/spec/requests/api/v1/timelines/tag_spec.rb new file mode 100644 index 0000000000..a118af13e2 --- /dev/null +++ b/spec/requests/api/v1/timelines/tag_spec.rb @@ -0,0 +1,112 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Tag' do + let(:user) { Fabricate(:user) } + let(:scopes) { 'read:statuses' } + let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) } + let(:headers) { { 'Authorization' => "Bearer #{token.token}" } } + + shared_examples 'a successful request to the tag timeline' do + it 'returns the expected statuses', :aggregate_failures do + subject + + expect(response).to have_http_status(200) + expect(body_as_json.pluck(:id)).to match_array(expected_statuses.map { |status| status.id.to_s }) + end + end + + describe 'GET /api/v1/timelines/tag/:hashtag' do + subject do + get "/api/v1/timelines/tag/#{hashtag}", headers: headers, params: params + end + + let(:account) { Fabricate(:account) } + let!(:private_status) { PostStatusService.new.call(account, visibility: :private, text: '#life could be a dream') } # rubocop:disable RSpec/LetSetup + let!(:life_status) { PostStatusService.new.call(account, text: 'tell me what is my #life without your #love') } + let!(:war_status) { PostStatusService.new.call(user.account, text: '#war, war never changes') } + let!(:love_status) { PostStatusService.new.call(account, text: 'what is #love?') } + let(:params) { {} } + let(:hashtag) { 'life' } + + context 'when given only one hashtag' do + let(:expected_statuses) { [life_status] } + + it_behaves_like 'a successful request to the tag timeline' + end + + context 'with any param' do + let(:expected_statuses) { [life_status, love_status] } + let(:params) { { any: %(love) } } + + it_behaves_like 'a successful request to the tag timeline' + end + + context 'with all param' do + let(:expected_statuses) { [life_status] } + let(:params) { { all: %w(love) } } + + it_behaves_like 'a successful request to the tag timeline' + end + + context 'with none param' do + let(:expected_statuses) { [war_status] } + let(:hashtag) { 'war' } + let(:params) { { none: %w(life love) } } + + it_behaves_like 'a successful request to the tag timeline' + end + + context 'with limit param' do + let(:hashtag) { 'love' } + let(:params) { { limit: 1 } } + + it 'returns only the requested number of statuses' do + subject + + expect(body_as_json.size).to eq(params[:limit]) + end + + it 'sets the correct pagination headers', :aggregate_failures do + subject + + headers = response.headers['Link'] + + expect(headers.find_link(%w(rel prev)).href).to eq(api_v1_timelines_tag_url(limit: 1, min_id: love_status.id.to_s)) + expect(headers.find_link(%w(rel next)).href).to eq(api_v1_timelines_tag_url(limit: 1, max_id: love_status.id.to_s)) + end + end + + context 'when the instance allows public preview' do + context 'when the user is not authenticated' do + let(:headers) { {} } + let(:expected_statuses) { [life_status] } + + it_behaves_like 'a successful request to the tag timeline' + end + end + + context 'when the instance does not allow public preview' do + before do + Form::AdminSettings.new(timeline_preview: false).save + end + + context 'when the user is not authenticated' do + let(:headers) { {} } + + it 'returns http unauthorized' do + subject + + expect(response).to have_http_status(401) + end + end + + context 'when the user is authenticated' do + let(:expected_statuses) { [life_status] } + + it_behaves_like 'a successful request to the tag timeline' + end + end + end +end From 7664e3b69207a221b036e3afb84b897ab9078e6a Mon Sep 17 00:00:00 2001 From: Daniel M Brasil Date: Fri, 13 Oct 2023 09:08:21 -0300 Subject: [PATCH 37/58] Migrate to request specs in `/api/v1/statuses/:status_id/source` (#25634) --- .../v1/statuses/sources_controller_spec.rb | 29 -------- spec/requests/api/v1/statuses/sources_spec.rb | 72 +++++++++++++++++++ 2 files changed, 72 insertions(+), 29 deletions(-) delete mode 100644 spec/controllers/api/v1/statuses/sources_controller_spec.rb create mode 100644 spec/requests/api/v1/statuses/sources_spec.rb diff --git a/spec/controllers/api/v1/statuses/sources_controller_spec.rb b/spec/controllers/api/v1/statuses/sources_controller_spec.rb deleted file mode 100644 index fbe6fa0be6..0000000000 --- a/spec/controllers/api/v1/statuses/sources_controller_spec.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -describe Api::V1::Statuses::SourcesController do - render_views - - let(:user) { Fabricate(:user) } - let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') } - let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:statuses', application: app) } - - context 'with an oauth token' do - before do - allow(controller).to receive(:doorkeeper_token) { token } - end - - describe 'GET #show' do - let(:status) { Fabricate(:status, account: user.account) } - - before do - get :show, params: { status_id: status.id } - end - - it 'returns http success' do - expect(response).to have_http_status(200) - end - end - end -end diff --git a/spec/requests/api/v1/statuses/sources_spec.rb b/spec/requests/api/v1/statuses/sources_spec.rb new file mode 100644 index 0000000000..723b81905e --- /dev/null +++ b/spec/requests/api/v1/statuses/sources_spec.rb @@ -0,0 +1,72 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Sources' do + let(:user) { Fabricate(:user) } + let(:scopes) { 'read:statuses' } + let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) } + let(:headers) { { 'Authorization' => "Bearer #{token.token}" } } + + describe 'GET /api/v1/statuses/:status_id/source' do + subject do + get "/api/v1/statuses/#{status.id}/source", headers: headers + end + + let(:status) { Fabricate(:status) } + + it_behaves_like 'forbidden for wrong scope', 'write write:statuses' + + context 'with public status' do + it 'returns the source properties of the status', :aggregate_failures do + subject + + expect(response).to have_http_status(200) + expect(body_as_json).to eq({ + id: status.id.to_s, + text: status.text, + spoiler_text: status.spoiler_text, + }) + end + end + + context 'with private status of non-followed account' do + let(:status) { Fabricate(:status, visibility: :private) } + + it 'returns http not found' do + subject + + expect(response).to have_http_status(404) + end + end + + context 'with private status of followed account' do + let(:status) { Fabricate(:status, visibility: :private) } + + before do + user.account.follow!(status.account) + end + + it 'returns the source properties of the status', :aggregate_failures do + subject + + expect(response).to have_http_status(200) + expect(body_as_json).to eq({ + id: status.id.to_s, + text: status.text, + spoiler_text: status.spoiler_text, + }) + end + end + + context 'without an authorization header' do + let(:headers) { {} } + + it 'returns http unauthorized' do + subject + + expect(response).to have_http_status(401) + end + end + end +end From ecdb31d4799422245f73d74b280bc8733081a6d7 Mon Sep 17 00:00:00 2001 From: Daniel M Brasil Date: Fri, 13 Oct 2023 09:19:12 -0300 Subject: [PATCH 38/58] Migrate to request specs in `/api/v1/favourites` (#25518) --- .../api/v1/favourites_controller_spec.rb | 80 ------------------- spec/requests/api/v1/favourites_spec.rb | 71 ++++++++++++++++ 2 files changed, 71 insertions(+), 80 deletions(-) delete mode 100644 spec/controllers/api/v1/favourites_controller_spec.rb create mode 100644 spec/requests/api/v1/favourites_spec.rb diff --git a/spec/controllers/api/v1/favourites_controller_spec.rb b/spec/controllers/api/v1/favourites_controller_spec.rb deleted file mode 100644 index c9ca046be0..0000000000 --- a/spec/controllers/api/v1/favourites_controller_spec.rb +++ /dev/null @@ -1,80 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe Api::V1::FavouritesController do - render_views - - let(:user) { Fabricate(:user) } - let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read') } - - describe 'GET #index' do - context 'without token' do - it 'returns http unauthorized' do - get :index - expect(response).to have_http_status 401 - end - end - - context 'with token' do - context 'without read scope' do - before do - allow(controller).to receive(:doorkeeper_token) do - Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: '') - end - end - - it 'returns http forbidden' do - get :index - expect(response).to have_http_status 403 - end - end - - context 'without valid resource owner' do - before do - token = Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read') - user.destroy! - - allow(controller).to receive(:doorkeeper_token) { token } - end - - it 'returns http unprocessable entity' do - get :index - expect(response).to have_http_status 422 - end - end - - context 'with read scope and valid resource owner' do - before do - allow(controller).to receive(:doorkeeper_token) do - Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:favourites') - end - end - - it 'shows favourites owned by the user' do - favourite_by_user = Fabricate(:favourite, account: user.account) - favourite_by_others = Fabricate(:favourite) - - get :index - - expect(assigns(:statuses)).to contain_exactly(favourite_by_user.status) - end - - it 'adds pagination headers if necessary' do - favourite = Fabricate(:favourite, account: user.account) - - get :index, params: { limit: 1 } - - expect(response.headers['Link'].find_link(%w(rel next)).href).to eq "http://test.host/api/v1/favourites?limit=1&max_id=#{favourite.id}" - expect(response.headers['Link'].find_link(%w(rel prev)).href).to eq "http://test.host/api/v1/favourites?limit=1&min_id=#{favourite.id}" - end - - it 'does not add pagination headers if not necessary' do - get :index - - expect(response.headers['Link']).to be_nil - end - end - end - end -end diff --git a/spec/requests/api/v1/favourites_spec.rb b/spec/requests/api/v1/favourites_spec.rb new file mode 100644 index 0000000000..713990592c --- /dev/null +++ b/spec/requests/api/v1/favourites_spec.rb @@ -0,0 +1,71 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Favourites' do + let(:user) { Fabricate(:user) } + let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) } + let(:scopes) { 'read:favourites' } + let(:headers) { { Authorization: "Bearer #{token.token}" } } + + describe 'GET /api/v1/favourites' do + subject do + get '/api/v1/favourites', headers: headers, params: params + end + + let(:params) { {} } + let!(:favourites) { Fabricate.times(3, :favourite, account: user.account) } + + let(:expected_response) do + favourites.map do |favourite| + a_hash_including(id: favourite.status.id.to_s, account: a_hash_including(id: favourite.status.account.id.to_s)) + end + end + + it_behaves_like 'forbidden for wrong scope', 'write' + + it 'returns http success' do + subject + + expect(response).to have_http_status(200) + end + + it 'returns the favourites' do + subject + + expect(body_as_json).to match_array(expected_response) + end + + context 'with limit param' do + let(:params) { { limit: 2 } } + + it 'returns only the requested number of favourites' do + subject + + expect(body_as_json.size).to eq(params[:limit]) + end + + it 'sets the correct pagination header for the prev path' do + subject + + expect(response.headers['Link'].find_link(%w(rel prev)).href).to eq(api_v1_favourites_url(limit: params[:limit], min_id: favourites.last.id)) + end + + it 'sets the correct pagination header for the next path' do + subject + + expect(response.headers['Link'].find_link(%w(rel next)).href).to eq(api_v1_favourites_url(limit: params[:limit], max_id: favourites[1].id)) + end + end + + context 'without an authorization header' do + let(:headers) { {} } + + it 'returns http unauthorized' do + subject + + expect(response).to have_http_status(401) + end + end + end +end From fd9dea21d0da9d5c4184efca8f66cc2ffc5435f6 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 13 Oct 2023 08:42:09 -0400 Subject: [PATCH 39/58] DB speedup in `API::` controller/request specs (#25516) --- .../controllers/api/oembed_controller_spec.rb | 5 +- .../accounts/credentials_controller_spec.rb | 6 +- .../follower_accounts_controller_spec.rb | 10 +-- .../following_accounts_controller_spec.rb | 10 +-- .../api/v1/accounts/notes_controller_spec.rb | 18 ++--- .../api/v1/accounts/pins_controller_spec.rb | 14 +--- .../accounts/relationships_controller_spec.rb | 16 ++-- .../v1/accounts/statuses_controller_spec.rb | 14 +--- .../api/v1/accounts_controller_spec.rb | 80 +++---------------- .../api/v1/admin/accounts_controller_spec.rb | 38 ++------- .../reactions_controller_spec.rb | 10 +-- .../api/v1/announcements_controller_spec.rb | 5 +- .../api/v1/blocks_controller_spec.rb | 21 ++--- .../api/v1/conversations_controller_spec.rb | 11 +-- .../api/v1/filters_controller_spec.rb | 26 ++---- .../translation_languages_controller_spec.rb | 4 +- .../api/v1/lists/accounts_controller_spec.rb | 20 +---- .../api/v1/markers_controller_spec.rb | 17 +--- .../api/v1/media_controller_spec.rb | 31 +------ .../api/v1/polls/votes_controller_spec.rb | 7 +- .../api/v1/reports_controller_spec.rb | 16 +--- .../api/v1/statuses/mutes_controller_spec.rb | 10 +-- .../reblogged_by_accounts_controller_spec.rb | 6 +- .../v1/statuses/reblogs_controller_spec.rb | 24 +----- .../api/v1/statuses_controller_spec.rb | 57 ++++--------- .../api/v2/admin/accounts_controller_spec.rb | 10 +-- .../v2/filters/keywords_controller_spec.rb | 18 +---- .../v2/filters/statuses_controller_spec.rb | 14 +--- .../api/v1/admin/account_actions_spec.rb | 28 +------ .../v1/admin/canonical_email_blocks_spec.rb | 49 ++---------- .../api/v1/admin/domain_allows_spec.rb | 26 +----- .../api/v1/admin/domain_blocks_spec.rb | 41 ++-------- .../api/v1/admin/email_domain_blocks_spec.rb | 26 +----- spec/requests/api/v1/admin/ip_blocks_spec.rb | 33 +------- spec/requests/api/v1/admin/reports_spec.rb | 55 +++---------- spec/requests/api/v1/apps/credentials_spec.rb | 6 +- spec/requests/api/v1/apps_spec.rb | 18 +---- spec/requests/api/v1/domain_blocks_spec.rb | 21 +---- spec/requests/api/v1/follow_requests_spec.rb | 33 +------- spec/requests/api/v1/lists_spec.rb | 40 ++-------- spec/requests/api/v1/tags_spec.rb | 33 +------- 41 files changed, 181 insertions(+), 746 deletions(-) diff --git a/spec/controllers/api/oembed_controller_spec.rb b/spec/controllers/api/oembed_controller_spec.rb index 70248c3982..5f0ca560d2 100644 --- a/spec/controllers/api/oembed_controller_spec.rb +++ b/spec/controllers/api/oembed_controller_spec.rb @@ -14,11 +14,8 @@ RSpec.describe Api::OEmbedController do get :show, params: { url: short_account_status_url(alice, status) }, format: :json end - it 'returns http success' do + it 'returns private cache control headers', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'returns private cache control headers' do expect(response.headers['Cache-Control']).to include('private, no-store') end end diff --git a/spec/controllers/api/v1/accounts/credentials_controller_spec.rb b/spec/controllers/api/v1/accounts/credentials_controller_spec.rb index b5d5c37a9c..a62fa54e60 100644 --- a/spec/controllers/api/v1/accounts/credentials_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/credentials_controller_spec.rb @@ -41,11 +41,9 @@ describe Api::V1::Accounts::CredentialsController do } end - it 'returns http success' do + it 'updates account info', :aggregate_failures do expect(response).to have_http_status(200) - end - it 'updates account info' do user.reload user.account.reload @@ -55,9 +53,7 @@ describe Api::V1::Accounts::CredentialsController do expect(user.account.header).to exist expect(user.setting_default_privacy).to eq('unlisted') expect(user.setting_default_sensitive).to be(true) - end - it 'queues up an account update distribution' do expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_async).with(user.account_id) end end diff --git a/spec/controllers/api/v1/accounts/follower_accounts_controller_spec.rb b/spec/controllers/api/v1/accounts/follower_accounts_controller_spec.rb index 7a387f326f..510a47566b 100644 --- a/spec/controllers/api/v1/accounts/follower_accounts_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/follower_accounts_controller_spec.rb @@ -18,23 +18,19 @@ describe Api::V1::Accounts::FollowerAccountsController do end describe 'GET #index' do - it 'returns http success' do + it 'returns accounts following the given account', :aggregate_failures do get :index, params: { account_id: account.id, limit: 2 } expect(response).to have_http_status(200) - end - - it 'returns accounts following the given account' do - get :index, params: { account_id: account.id, limit: 2 } - expect(body_as_json.size).to eq 2 expect([body_as_json[0][:id], body_as_json[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s) end - it 'does not return blocked users' do + it 'does not return blocked users', :aggregate_failures do user.account.block!(bob) get :index, params: { account_id: account.id, limit: 2 } + expect(response).to have_http_status(200) expect(body_as_json.size).to eq 1 expect(body_as_json[0][:id]).to eq alice.id.to_s end diff --git a/spec/controllers/api/v1/accounts/following_accounts_controller_spec.rb b/spec/controllers/api/v1/accounts/following_accounts_controller_spec.rb index b69b0bd395..a7d07a6bec 100644 --- a/spec/controllers/api/v1/accounts/following_accounts_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/following_accounts_controller_spec.rb @@ -18,23 +18,19 @@ describe Api::V1::Accounts::FollowingAccountsController do end describe 'GET #index' do - it 'returns http success' do + it 'returns accounts followed by the given account', :aggregate_failures do get :index, params: { account_id: account.id, limit: 2 } expect(response).to have_http_status(200) - end - - it 'returns accounts followed by the given account' do - get :index, params: { account_id: account.id, limit: 2 } - expect(body_as_json.size).to eq 2 expect([body_as_json[0][:id], body_as_json[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s) end - it 'does not return blocked users' do + it 'does not return blocked users', :aggregate_failures do user.account.block!(bob) get :index, params: { account_id: account.id, limit: 2 } + expect(response).to have_http_status(200) expect(body_as_json.size).to eq 1 expect(body_as_json[0][:id]).to eq alice.id.to_s end diff --git a/spec/controllers/api/v1/accounts/notes_controller_spec.rb b/spec/controllers/api/v1/accounts/notes_controller_spec.rb index 4107105afd..75599b32b2 100644 --- a/spec/controllers/api/v1/accounts/notes_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/notes_controller_spec.rb @@ -19,30 +19,24 @@ describe Api::V1::Accounts::NotesController do post :create, params: { account_id: account.id, comment: comment } end - context 'when account note has reasonable length' do + context 'when account note has reasonable length', :aggregate_failures do let(:comment) { 'foo' } - it 'returns http success' do - subject - expect(response).to have_http_status(200) - end - it 'updates account note' do subject + + expect(response).to have_http_status(200) expect(AccountNote.find_by(account_id: user.account.id, target_account_id: account.id).comment).to eq comment end end - context 'when account note exceeds allowed length' do + context 'when account note exceeds allowed length', :aggregate_failures do let(:comment) { 'a' * 2_001 } - it 'returns 422' do - subject - expect(response).to have_http_status(422) - end - it 'does not create account note' do subject + + expect(response).to have_http_status(422) expect(AccountNote.where(account_id: user.account.id, target_account_id: account.id)).to_not exist end end diff --git a/spec/controllers/api/v1/accounts/pins_controller_spec.rb b/spec/controllers/api/v1/accounts/pins_controller_spec.rb index b4aa9b7116..36f525e756 100644 --- a/spec/controllers/api/v1/accounts/pins_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/pins_controller_spec.rb @@ -15,14 +15,11 @@ RSpec.describe Api::V1::Accounts::PinsController do describe 'POST #create' do subject { post :create, params: { account_id: kevin.account.id } } - it 'returns 200' do - expect(response).to have_http_status(200) - end - - it 'creates account_pin' do + it 'creates account_pin', :aggregate_failures do expect do subject end.to change { AccountPin.where(account: john.account, target_account: kevin.account).count }.by(1) + expect(response).to have_http_status(200) end end @@ -33,14 +30,11 @@ RSpec.describe Api::V1::Accounts::PinsController do Fabricate(:account_pin, account: john.account, target_account: kevin.account) end - it 'returns 200' do - expect(response).to have_http_status(200) - end - - it 'destroys account_pin' do + it 'destroys account_pin', :aggregate_failures do expect do subject end.to change { AccountPin.where(account: john.account, target_account: kevin.account).count }.by(-1) + expect(response).to have_http_status(200) end end end diff --git a/spec/controllers/api/v1/accounts/relationships_controller_spec.rb b/spec/controllers/api/v1/accounts/relationships_controller_spec.rb index 993ead636a..5ba6f2a1f8 100644 --- a/spec/controllers/api/v1/accounts/relationships_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/relationships_controller_spec.rb @@ -26,13 +26,10 @@ describe Api::V1::Accounts::RelationshipsController do get :index, params: { id: simon.id } end - it 'returns http success' do - expect(response).to have_http_status(200) - end - - it 'returns JSON with correct data' do + it 'returns JSON with correct data', :aggregate_failures do json = body_as_json + expect(response).to have_http_status(200) expect(json).to be_a Enumerable expect(json.first[:following]).to be true expect(json.first[:followed_by]).to be false @@ -51,11 +48,14 @@ describe Api::V1::Accounts::RelationshipsController do context 'when there is returned JSON data' do let(:json) { body_as_json } - it 'returns an enumerable json' do + it 'returns an enumerable json with correct elements', :aggregate_failures do expect(json).to be_a Enumerable + + expect_simon_item_one + expect_lewis_item_two end - it 'returns a correct first element' do + def expect_simon_item_one expect(json.first[:id]).to eq simon.id.to_s expect(json.first[:following]).to be true expect(json.first[:showing_reblogs]).to be true @@ -65,7 +65,7 @@ describe Api::V1::Accounts::RelationshipsController do expect(json.first[:domain_blocking]).to be false end - it 'returns a correct second element' do + def expect_lewis_item_two expect(json.second[:id]).to eq lewis.id.to_s expect(json.second[:following]).to be false expect(json.second[:showing_reblogs]).to be false diff --git a/spec/controllers/api/v1/accounts/statuses_controller_spec.rb b/spec/controllers/api/v1/accounts/statuses_controller_spec.rb index cb62afcf93..0e4fa93017 100644 --- a/spec/controllers/api/v1/accounts/statuses_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/statuses_controller_spec.rb @@ -14,15 +14,10 @@ describe Api::V1::Accounts::StatusesController do end describe 'GET #index' do - it 'returns http success' do + it 'returns expected headers', :aggregate_failures do get :index, params: { account_id: user.account.id, limit: 1 } expect(response).to have_http_status(200) - end - - it 'returns expected headers' do - get :index, params: { account_id: user.account.id, limit: 1 } - expect(response.headers['Link'].links.size).to eq(2) end @@ -44,14 +39,11 @@ describe Api::V1::Accounts::StatusesController do get :index, params: { account_id: user.account.id, exclude_replies: true } end - it 'returns http success' do - expect(response).to have_http_status(200) - end - - it 'returns posts along with self replies' do + it 'returns posts along with self replies', :aggregate_failures do json = body_as_json post_ids = json.map { |item| item[:id].to_i }.sort + expect(response).to have_http_status(200) expect(post_ids).to eq [status.id, status_self_reply.id] end end diff --git a/spec/controllers/api/v1/accounts_controller_spec.rb b/spec/controllers/api/v1/accounts_controller_spec.rb index 0daec691a5..9d0bb73c7c 100644 --- a/spec/controllers/api/v1/accounts_controller_spec.rb +++ b/spec/controllers/api/v1/accounts_controller_spec.rb @@ -25,15 +25,10 @@ RSpec.describe Api::V1::AccountsController do context 'when given truthy agreement' do let(:agreement) { 'true' } - it 'returns http success' do + it 'creates a user', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'returns a new access token as JSON' do expect(body_as_json[:access_token]).to_not be_blank - end - it 'creates a user' do user = User.find_by(email: 'hello@world.tld') expect(user).to_not be_nil expect(user.created_by_application_id).to eq app.id @@ -59,18 +54,14 @@ RSpec.describe Api::V1::AccountsController do context 'with unlocked account' do let(:locked) { false } - it 'returns http success' do + it 'creates a following relation between user and target user', :aggregate_failures do expect(response).to have_http_status(200) - end - it 'returns JSON with following=true and requested=false' do json = body_as_json expect(json[:following]).to be true expect(json[:requested]).to be false - end - it 'creates a following relation between user and target user' do expect(user.account.following?(other_account)).to be true end @@ -80,18 +71,14 @@ RSpec.describe Api::V1::AccountsController do context 'with locked account' do let(:locked) { true } - it 'returns http success' do + it 'creates a follow request relation between user and target user', :aggregate_failures do expect(response).to have_http_status(200) - end - it 'returns JSON with following=false and requested=true' do json = body_as_json expect(json[:following]).to be false expect(json[:requested]).to be true - end - it 'creates a follow request relation between user and target user' do expect(user.account.requested?(other_account)).to be true end @@ -148,11 +135,8 @@ RSpec.describe Api::V1::AccountsController do post :unfollow, params: { id: other_account.id } end - it 'returns http success' do + it 'removes the following relation between user and target user', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'removes the following relation between user and target user' do expect(user.account.following?(other_account)).to be false end @@ -168,11 +152,8 @@ RSpec.describe Api::V1::AccountsController do post :remove_from_followers, params: { id: other_account.id } end - it 'returns http success' do + it 'removes the followed relation between user and target user', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'removes the followed relation between user and target user' do expect(user.account.followed_by?(other_account)).to be false end @@ -188,15 +169,9 @@ RSpec.describe Api::V1::AccountsController do post :block, params: { id: other_account.id } end - it 'returns http success' do + it 'creates a blocking relation', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'removes the following relation between user and target user' do expect(user.account.following?(other_account)).to be false - end - - it 'creates a blocking relation' do expect(user.account.blocking?(other_account)).to be true end @@ -212,11 +187,8 @@ RSpec.describe Api::V1::AccountsController do post :unblock, params: { id: other_account.id } end - it 'returns http success' do + it 'removes the blocking relation between user and target user', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'removes the blocking relation between user and target user' do expect(user.account.blocking?(other_account)).to be false end @@ -232,19 +204,10 @@ RSpec.describe Api::V1::AccountsController do post :mute, params: { id: other_account.id } end - it 'returns http success' do + it 'mutes notifications', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'does not remove the following relation between user and target user' do expect(user.account.following?(other_account)).to be true - end - - it 'creates a muting relation' do expect(user.account.muting?(other_account)).to be true - end - - it 'mutes notifications' do expect(user.account.muting_notifications?(other_account)).to be true end @@ -260,19 +223,10 @@ RSpec.describe Api::V1::AccountsController do post :mute, params: { id: other_account.id, notifications: false } end - it 'returns http success' do + it 'does not mute notifications', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'does not remove the following relation between user and target user' do expect(user.account.following?(other_account)).to be true - end - - it 'creates a muting relation' do expect(user.account.muting?(other_account)).to be true - end - - it 'does not mute notifications' do expect(user.account.muting_notifications?(other_account)).to be false end @@ -288,19 +242,10 @@ RSpec.describe Api::V1::AccountsController do post :mute, params: { id: other_account.id, duration: 300 } end - it 'returns http success' do + it 'mutes notifications', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'does not remove the following relation between user and target user' do expect(user.account.following?(other_account)).to be true - end - - it 'creates a muting relation' do expect(user.account.muting?(other_account)).to be true - end - - it 'mutes notifications' do expect(user.account.muting_notifications?(other_account)).to be true end @@ -316,11 +261,8 @@ RSpec.describe Api::V1::AccountsController do post :unmute, params: { id: other_account.id } end - it 'returns http success' do + it 'removes the muting relation between user and target user', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'removes the muting relation between user and target user' do expect(user.account.muting?(other_account)).to be false end diff --git a/spec/controllers/api/v1/admin/accounts_controller_spec.rb b/spec/controllers/api/v1/admin/accounts_controller_spec.rb index 36f6e398cb..4b56b25479 100644 --- a/spec/controllers/api/v1/admin/accounts_controller_spec.rb +++ b/spec/controllers/api/v1/admin/accounts_controller_spec.rb @@ -44,11 +44,9 @@ RSpec.describe Api::V1::Admin::AccountsController do context "when called with #{params.inspect}" do let(:params) { params } - it 'returns http success' do + it "returns the correct accounts (#{expected_results.inspect})", :aggregate_failures do expect(response).to have_http_status(200) - end - it "returns the correct accounts (#{expected_results.inspect})" do json = body_as_json expect(json.map { |a| a[:id].to_i }).to eq(expected_results.map { |symbol| send(symbol).id }) @@ -79,15 +77,10 @@ RSpec.describe Api::V1::Admin::AccountsController do it_behaves_like 'forbidden for wrong scope', 'write:statuses' it_behaves_like 'forbidden for wrong role', '' - it 'returns http success' do + it 'approves user', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'approves user' do expect(account.reload.user_approved?).to be true - end - it 'logs action' do log_item = Admin::ActionLog.last expect(log_item).to_not be_nil @@ -106,15 +99,10 @@ RSpec.describe Api::V1::Admin::AccountsController do it_behaves_like 'forbidden for wrong scope', 'write:statuses' it_behaves_like 'forbidden for wrong role', '' - it 'returns http success' do + it 'removes user', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'removes user' do expect(User.where(id: account.user.id).count).to eq 0 - end - it 'logs action' do log_item = Admin::ActionLog.last expect(log_item).to_not be_nil @@ -133,11 +121,8 @@ RSpec.describe Api::V1::Admin::AccountsController do it_behaves_like 'forbidden for wrong scope', 'write:statuses' it_behaves_like 'forbidden for wrong role', '' - it 'returns http success' do + it 'enables user', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'enables user' do expect(account.reload.user_disabled?).to be false end end @@ -151,11 +136,8 @@ RSpec.describe Api::V1::Admin::AccountsController do it_behaves_like 'forbidden for wrong scope', 'write:statuses' it_behaves_like 'forbidden for wrong role', '' - it 'returns http success' do + it 'unsuspends account', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'unsuspends account' do expect(account.reload.suspended?).to be false end end @@ -169,11 +151,8 @@ RSpec.describe Api::V1::Admin::AccountsController do it_behaves_like 'forbidden for wrong scope', 'write:statuses' it_behaves_like 'forbidden for wrong role', '' - it 'returns http success' do + it 'unsensitizes account', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'unsensitizes account' do expect(account.reload.sensitized?).to be false end end @@ -187,11 +166,8 @@ RSpec.describe Api::V1::Admin::AccountsController do it_behaves_like 'forbidden for wrong scope', 'write:statuses' it_behaves_like 'forbidden for wrong role', '' - it 'returns http success' do + it 'unsilences account', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'unsilences account' do expect(account.reload.silenced?).to be false end end diff --git a/spec/controllers/api/v1/announcements/reactions_controller_spec.rb b/spec/controllers/api/v1/announcements/reactions_controller_spec.rb index 10aaa553f5..c1debc33fe 100644 --- a/spec/controllers/api/v1/announcements/reactions_controller_spec.rb +++ b/spec/controllers/api/v1/announcements/reactions_controller_spec.rb @@ -25,11 +25,8 @@ RSpec.describe Api::V1::Announcements::ReactionsController do put :update, params: { announcement_id: announcement.id, id: '😂' } end - it 'returns http success' do + it 'creates reaction', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'creates reaction' do expect(announcement.announcement_reactions.find_by(name: '😂', account: user.account)).to_not be_nil end end @@ -53,11 +50,8 @@ RSpec.describe Api::V1::Announcements::ReactionsController do delete :destroy, params: { announcement_id: announcement.id, id: '😂' } end - it 'returns http success' do + it 'creates reaction', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'creates reaction' do expect(announcement.announcement_reactions.find_by(name: '😂', account: user.account)).to be_nil end end diff --git a/spec/controllers/api/v1/announcements_controller_spec.rb b/spec/controllers/api/v1/announcements_controller_spec.rb index 15d94b4512..95ce8fd9fc 100644 --- a/spec/controllers/api/v1/announcements_controller_spec.rb +++ b/spec/controllers/api/v1/announcements_controller_spec.rb @@ -47,11 +47,8 @@ RSpec.describe Api::V1::AnnouncementsController do post :dismiss, params: { id: announcement.id } end - it 'returns http success' do + it 'dismisses announcement', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'dismisses announcement' do expect(announcement.announcement_mutes.find_by(account: user.account)).to_not be_nil end end diff --git a/spec/controllers/api/v1/blocks_controller_spec.rb b/spec/controllers/api/v1/blocks_controller_spec.rb index eaafc1b4fa..ba63560a96 100644 --- a/spec/controllers/api/v1/blocks_controller_spec.rb +++ b/spec/controllers/api/v1/blocks_controller_spec.rb @@ -12,45 +12,48 @@ RSpec.describe Api::V1::BlocksController do before { allow(controller).to receive(:doorkeeper_token) { token } } describe 'GET #index' do - it 'limits according to limit parameter' do + it 'limits according to limit parameter', :aggregate_failures do Array.new(2) { Fabricate(:block, account: user.account) } get :index, params: { limit: 1 } + + expect(response).to have_http_status(200) expect(body_as_json.size).to eq 1 end - it 'queries blocks in range according to max_id' do + it 'queries blocks in range according to max_id', :aggregate_failures do blocks = Array.new(2) { Fabricate(:block, account: user.account) } get :index, params: { max_id: blocks[1] } + expect(response).to have_http_status(200) expect(body_as_json.size).to eq 1 expect(body_as_json[0][:id]).to eq blocks[0].target_account_id.to_s end - it 'queries blocks in range according to since_id' do + it 'queries blocks in range according to since_id', :aggregate_failures do blocks = Array.new(2) { Fabricate(:block, account: user.account) } get :index, params: { since_id: blocks[0] } + expect(response).to have_http_status(200) expect(body_as_json.size).to eq 1 expect(body_as_json[0][:id]).to eq blocks[1].target_account_id.to_s end - it 'sets pagination header for next path' do + it 'sets pagination header for next path', :aggregate_failures do blocks = Array.new(2) { Fabricate(:block, account: user.account) } get :index, params: { limit: 1, since_id: blocks[0] } + + expect(response).to have_http_status(200) expect(response.headers['Link'].find_link(%w(rel next)).href).to eq api_v1_blocks_url(limit: 1, max_id: blocks[1]) end - it 'sets pagination header for previous path' do + it 'sets pagination header for previous path', :aggregate_failures do block = Fabricate(:block, account: user.account) get :index - expect(response.headers['Link'].find_link(%w(rel prev)).href).to eq api_v1_blocks_url(since_id: block) - end - it 'returns http success' do - get :index expect(response).to have_http_status(200) + expect(response.headers['Link'].find_link(%w(rel prev)).href).to eq api_v1_blocks_url(since_id: block) end context 'with wrong scopes' do diff --git a/spec/controllers/api/v1/conversations_controller_spec.rb b/spec/controllers/api/v1/conversations_controller_spec.rb index 28d7c7f3ae..50e2a62efd 100644 --- a/spec/controllers/api/v1/conversations_controller_spec.rb +++ b/spec/controllers/api/v1/conversations_controller_spec.rb @@ -21,17 +21,14 @@ RSpec.describe Api::V1::ConversationsController do PostStatusService.new.call(user.account, text: 'Hey, nobody here', visibility: 'direct') end - it 'returns http success' do - get :index - expect(response).to have_http_status(200) - end - - it 'returns pagination headers' do + it 'returns pagination headers', :aggregate_failures do get :index, params: { limit: 1 } + + expect(response).to have_http_status(200) expect(response.headers['Link'].links.size).to eq(2) end - it 'returns conversations' do + it 'returns conversations', :aggregate_failures do get :index json = body_as_json expect(json.size).to eq 2 diff --git a/spec/controllers/api/v1/filters_controller_spec.rb b/spec/controllers/api/v1/filters_controller_spec.rb index 8ccd2f4d66..8d5408cf54 100644 --- a/spec/controllers/api/v1/filters_controller_spec.rb +++ b/spec/controllers/api/v1/filters_controller_spec.rb @@ -31,12 +31,10 @@ RSpec.describe Api::V1::FiltersController do post :create, params: { phrase: 'magic', context: %w(home), irreversible: irreversible, whole_word: whole_word } end - it 'returns http success' do - expect(response).to have_http_status(200) - end - - it 'creates a filter' do + it 'creates a filter', :aggregate_failures do filter = user.account.custom_filters.first + + expect(response).to have_http_status(200) expect(filter).to_not be_nil expect(filter.keywords.pluck(:keyword, :whole_word)).to eq [['magic', whole_word]] expect(filter.context).to eq %w(home) @@ -48,12 +46,10 @@ RSpec.describe Api::V1::FiltersController do let(:irreversible) { false } let(:whole_word) { true } - it 'returns http success' do - expect(response).to have_http_status(200) - end - - it 'creates a filter' do + it 'creates a filter', :aggregate_failures do filter = user.account.custom_filters.first + + expect(response).to have_http_status(200) expect(filter).to_not be_nil expect(filter.keywords.pluck(:keyword, :whole_word)).to eq [['magic', whole_word]] expect(filter.context).to eq %w(home) @@ -83,11 +79,8 @@ RSpec.describe Api::V1::FiltersController do put :update, params: { id: keyword.id, phrase: 'updated' } end - it 'returns http success' do + it 'updates the filter', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'updates the filter' do expect(keyword.reload.phrase).to eq 'updated' end end @@ -101,11 +94,8 @@ RSpec.describe Api::V1::FiltersController do delete :destroy, params: { id: keyword.id } end - it 'returns http success' do + it 'removes the filter', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'removes the filter' do expect { keyword.reload }.to raise_error ActiveRecord::RecordNotFound end end diff --git a/spec/controllers/api/v1/instances/translation_languages_controller_spec.rb b/spec/controllers/api/v1/instances/translation_languages_controller_spec.rb index 88bcc40341..f79687df66 100644 --- a/spec/controllers/api/v1/instances/translation_languages_controller_spec.rb +++ b/spec/controllers/api/v1/instances/translation_languages_controller_spec.rb @@ -5,7 +5,7 @@ require 'rails_helper' describe Api::V1::Instances::TranslationLanguagesController do describe 'GET #show' do context 'when no translation service is configured' do - it 'returns empty language matrix' do + it 'returns empty language matrix', :aggregate_failures do get :show expect(response).to have_http_status(200) @@ -19,7 +19,7 @@ describe Api::V1::Instances::TranslationLanguagesController do allow(TranslationService).to receive_messages(configured?: true, configured: service) end - it 'returns language matrix' do + it 'returns language matrix', :aggregate_failures do get :show expect(response).to have_http_status(200) diff --git a/spec/controllers/api/v1/lists/accounts_controller_spec.rb b/spec/controllers/api/v1/lists/accounts_controller_spec.rb index d4550dd769..21e155a508 100644 --- a/spec/controllers/api/v1/lists/accounts_controller_spec.rb +++ b/spec/controllers/api/v1/lists/accounts_controller_spec.rb @@ -35,11 +35,8 @@ describe Api::V1::Lists::AccountsController do post :create, params: { list_id: list.id, account_ids: [bob.id] } end - it 'returns http success' do + it 'adds account to the list', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'adds account to the list' do expect(list.accounts.include?(bob)).to be true end end @@ -50,11 +47,8 @@ describe Api::V1::Lists::AccountsController do post :create, params: { list_id: list.id, account_ids: [bob.id] } end - it 'returns http success' do + it 'adds account to the list', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'adds account to the list' do expect(list.accounts.include?(bob)).to be true end end @@ -64,11 +58,8 @@ describe Api::V1::Lists::AccountsController do post :create, params: { list_id: list.id, account_ids: [bob.id] } end - it 'returns http not found' do + it 'does not add the account to the list', :aggregate_failures do expect(response).to have_http_status(404) - end - - it 'does not add the account to the list' do expect(list.accounts.include?(bob)).to be false end end @@ -81,11 +72,8 @@ describe Api::V1::Lists::AccountsController do delete :destroy, params: { list_id: list.id, account_ids: [list.accounts.first.id] } end - it 'returns http success' do + it 'removes account from the list', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'removes account from the list' do expect(list.accounts.count).to eq 0 end end diff --git a/spec/controllers/api/v1/markers_controller_spec.rb b/spec/controllers/api/v1/markers_controller_spec.rb index 64e9dcafb6..e954bbd1b6 100644 --- a/spec/controllers/api/v1/markers_controller_spec.rb +++ b/spec/controllers/api/v1/markers_controller_spec.rb @@ -18,13 +18,10 @@ RSpec.describe Api::V1::MarkersController do get :index, params: { timeline: %w(home notifications) } end - it 'returns http success' do - expect(response).to have_http_status(200) - end - - it 'returns markers' do + it 'returns markers', :aggregate_failures do json = body_as_json + expect(response).to have_http_status(200) expect(json.key?(:home)).to be true expect(json[:home][:last_read_id]).to eq '123' expect(json.key?(:notifications)).to be true @@ -38,11 +35,8 @@ RSpec.describe Api::V1::MarkersController do post :create, params: { home: { last_read_id: '69420' } } end - it 'returns http success' do + it 'creates a marker', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'creates a marker' do expect(user.markers.first.timeline).to eq 'home' expect(user.markers.first.last_read_id).to eq 69_420 end @@ -54,11 +48,8 @@ RSpec.describe Api::V1::MarkersController do post :create, params: { home: { last_read_id: '70120' } } end - it 'returns http success' do + it 'updates a marker', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'updates a marker' do expect(user.markers.first.timeline).to eq 'home' expect(user.markers.first.last_read_id).to eq 70_120 end diff --git a/spec/controllers/api/v1/media_controller_spec.rb b/spec/controllers/api/v1/media_controller_spec.rb index 94b2a0a98f..b574381f90 100644 --- a/spec/controllers/api/v1/media_controller_spec.rb +++ b/spec/controllers/api/v1/media_controller_spec.rb @@ -38,19 +38,10 @@ RSpec.describe Api::V1::MediaController do post :create, params: { file: fixture_file_upload('attachment.jpg', 'image/jpeg') } end - it 'returns http success' do + it 'creates a media attachment', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'creates a media attachment' do expect(MediaAttachment.first).to_not be_nil - end - - it 'uploads a file' do expect(MediaAttachment.first).to have_attached_file(:file) - end - - it 'returns media ID in JSON' do expect(body_as_json[:id]).to eq MediaAttachment.first.id.to_s end end @@ -60,19 +51,10 @@ RSpec.describe Api::V1::MediaController do post :create, params: { file: fixture_file_upload('attachment.gif', 'image/gif') } end - it 'returns http success' do + it 'creates a media attachment', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'creates a media attachment' do expect(MediaAttachment.first).to_not be_nil - end - - it 'uploads a file' do expect(MediaAttachment.first).to have_attached_file(:file) - end - - it 'returns media ID in JSON' do expect(body_as_json[:id]).to eq MediaAttachment.first.id.to_s end end @@ -82,17 +64,10 @@ RSpec.describe Api::V1::MediaController do post :create, params: { file: fixture_file_upload('attachment.webm', 'video/webm') } end - it do - # returns http success + it 'creates a media attachment', :aggregate_failures do expect(response).to have_http_status(200) - - # creates a media attachment expect(MediaAttachment.first).to_not be_nil - - # uploads a file expect(MediaAttachment.first).to have_attached_file(:file) - - # returns media ID in JSON expect(body_as_json[:id]).to eq MediaAttachment.first.id.to_s end end diff --git a/spec/controllers/api/v1/polls/votes_controller_spec.rb b/spec/controllers/api/v1/polls/votes_controller_spec.rb index 7abd2a1b17..5de225a487 100644 --- a/spec/controllers/api/v1/polls/votes_controller_spec.rb +++ b/spec/controllers/api/v1/polls/votes_controller_spec.rb @@ -18,18 +18,13 @@ RSpec.describe Api::V1::Polls::VotesController do post :create, params: { poll_id: poll.id, choices: %w(1) } end - it 'returns http success' do + it 'creates a vote', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'creates a vote' do vote = poll.votes.where(account: user.account).first expect(vote).to_not be_nil expect(vote.choice).to eq 1 - end - it 'updates poll tallies' do expect(poll.reload.cached_tallies).to eq [0, 1] end end diff --git a/spec/controllers/api/v1/reports_controller_spec.rb b/spec/controllers/api/v1/reports_controller_spec.rb index f923ff0794..624ceb213e 100644 --- a/spec/controllers/api/v1/reports_controller_spec.rb +++ b/spec/controllers/api/v1/reports_controller_spec.rb @@ -26,19 +26,10 @@ RSpec.describe Api::V1::ReportsController do post :create, params: { status_ids: [status.id], account_id: target_account.id, comment: 'reasons', category: category, rule_ids: rule_ids, forward: forward } end - it 'returns http success' do + it 'creates a report', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'creates a report' do expect(target_account.targeted_reports).to_not be_empty - end - - it 'saves comment' do expect(target_account.targeted_reports.first.comment).to eq 'reasons' - end - - it 'sends e-mails to admins' do expect(ActionMailer::Base.deliveries.first.to).to eq([admin.email]) end @@ -63,11 +54,8 @@ RSpec.describe Api::V1::ReportsController do let(:category) { 'violation' } let(:rule_ids) { [rule.id] } - it 'saves category' do + it 'saves category and rule_ids' do expect(target_account.targeted_reports.first.violation?).to be true - end - - it 'saves rule_ids' do expect(target_account.targeted_reports.first.rule_ids).to contain_exactly(rule.id) end end diff --git a/spec/controllers/api/v1/statuses/mutes_controller_spec.rb b/spec/controllers/api/v1/statuses/mutes_controller_spec.rb index bffa9fe0d9..03274fe1cd 100644 --- a/spec/controllers/api/v1/statuses/mutes_controller_spec.rb +++ b/spec/controllers/api/v1/statuses/mutes_controller_spec.rb @@ -21,11 +21,8 @@ describe Api::V1::Statuses::MutesController do post :create, params: { status_id: status.id } end - it 'returns http success' do + it 'creates a conversation mute', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'creates a conversation mute' do expect(ConversationMute.find_by(account: user.account, conversation_id: status.conversation_id)).to_not be_nil end end @@ -38,11 +35,8 @@ describe Api::V1::Statuses::MutesController do post :destroy, params: { status_id: status.id } end - it 'returns http success' do + it 'destroys the conversation mute', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'destroys the conversation mute' do expect(ConversationMute.find_by(account: user.account, conversation_id: status.conversation_id)).to be_nil end end diff --git a/spec/controllers/api/v1/statuses/reblogged_by_accounts_controller_spec.rb b/spec/controllers/api/v1/statuses/reblogged_by_accounts_controller_spec.rb index 756010af87..0d15cca75c 100644 --- a/spec/controllers/api/v1/statuses/reblogged_by_accounts_controller_spec.rb +++ b/spec/controllers/api/v1/statuses/reblogged_by_accounts_controller_spec.rb @@ -24,14 +24,12 @@ RSpec.describe Api::V1::Statuses::RebloggedByAccountsController do Fabricate(:status, account: bob, reblog_of_id: status.id) end - it 'returns http success' do + it 'returns accounts who reblogged the status', :aggregate_failures do get :index, params: { status_id: status.id, limit: 2 } + expect(response).to have_http_status(200) expect(response.headers['Link'].links.size).to eq(2) - end - it 'returns accounts who reblogged the status' do - get :index, params: { status_id: status.id, limit: 2 } expect(body_as_json.size).to eq 2 expect([body_as_json[0][:id], body_as_json[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s) end diff --git a/spec/controllers/api/v1/statuses/reblogs_controller_spec.rb b/spec/controllers/api/v1/statuses/reblogs_controller_spec.rb index 16ce95dc22..2f2b30b07d 100644 --- a/spec/controllers/api/v1/statuses/reblogs_controller_spec.rb +++ b/spec/controllers/api/v1/statuses/reblogs_controller_spec.rb @@ -28,19 +28,13 @@ describe Api::V1::Statuses::ReblogsController do end context 'with public status' do - it 'returns http success' do + it 'reblogs the status', :aggregate_failures do expect(response).to have_http_status(200) - end - it 'updates the reblogs count' do expect(status.reblogs.count).to eq 1 - end - it 'updates the reblogged attribute' do expect(user.account.reblogged?(status)).to be true - end - it 'returns json with updated attributes' do hash_body = body_as_json expect(hash_body[:reblog][:id]).to eq status.id.to_s @@ -67,19 +61,13 @@ describe Api::V1::Statuses::ReblogsController do post :destroy, params: { status_id: status.id } end - it 'returns http success' do + it 'destroys the reblog', :aggregate_failures do expect(response).to have_http_status(200) - end - it 'updates the reblogs count' do expect(status.reblogs.count).to eq 0 - end - it 'updates the reblogged attribute' do expect(user.account.reblogged?(status)).to be false - end - it 'returns json with updated attributes' do hash_body = body_as_json expect(hash_body[:id]).to eq status.id.to_s @@ -97,19 +85,13 @@ describe Api::V1::Statuses::ReblogsController do post :destroy, params: { status_id: status.id } end - it 'returns http success' do + it 'destroys the reblog', :aggregate_failures do expect(response).to have_http_status(200) - end - it 'updates the reblogs count' do expect(status.reblogs.count).to eq 0 - end - it 'updates the reblogged attribute' do expect(user.account.reblogged?(status)).to be false - end - it 'returns json with updated attributes' do hash_body = body_as_json expect(hash_body[:id]).to eq status.id.to_s diff --git a/spec/controllers/api/v1/statuses_controller_spec.rb b/spec/controllers/api/v1/statuses_controller_spec.rb index c2bdba9ace..30bafe19ac 100644 --- a/spec/controllers/api/v1/statuses_controller_spec.rb +++ b/spec/controllers/api/v1/statuses_controller_spec.rb @@ -30,14 +30,11 @@ RSpec.describe Api::V1::StatusesController do user.account.custom_filters.create!(phrase: 'filter1', context: %w(home), action: :hide, keywords_attributes: [{ keyword: 'banned' }, { keyword: 'irrelevant' }]) end - it 'returns http success' do - get :show, params: { id: status.id } - expect(response).to have_http_status(200) - end - - it 'returns filter information' do + it 'returns filter information', :aggregate_failures do get :show, params: { id: status.id } json = body_as_json + + expect(response).to have_http_status(200) expect(json[:filtered][0]).to include({ filter: a_hash_including({ id: user.account.custom_filters.first.id.to_s, @@ -57,14 +54,11 @@ RSpec.describe Api::V1::StatusesController do filter.statuses.create!(status_id: status.id) end - it 'returns http success' do - get :show, params: { id: status.id } - expect(response).to have_http_status(200) - end - - it 'returns filter information' do + it 'returns filter information', :aggregate_failures do get :show, params: { id: status.id } json = body_as_json + + expect(response).to have_http_status(200) expect(json[:filtered][0]).to include({ filter: a_hash_including({ id: user.account.custom_filters.first.id.to_s, @@ -83,14 +77,11 @@ RSpec.describe Api::V1::StatusesController do user.account.custom_filters.create!(phrase: 'filter1', context: %w(home), action: :hide, keywords_attributes: [{ keyword: 'banned' }, { keyword: 'irrelevant' }]) end - it 'returns http success' do - get :show, params: { id: status.id } - expect(response).to have_http_status(200) - end - - it 'returns filter information' do + it 'returns filter information', :aggregate_failures do get :show, params: { id: status.id } json = body_as_json + + expect(response).to have_http_status(200) expect(json[:reblog][:filtered][0]).to include({ filter: a_hash_including({ id: user.account.custom_filters.first.id.to_s, @@ -125,11 +116,8 @@ RSpec.describe Api::V1::StatusesController do post :create, params: { status: 'Hello world' } end - it 'returns http success' do + it 'returns rate limit headers', :aggregate_failures 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 @@ -143,11 +131,8 @@ RSpec.describe Api::V1::StatusesController do post :create, params: { status: '@alice hm, @bob is really annoying lately', allowed_mentions: [alice.id] } end - it 'returns http unprocessable entity' do + it 'returns serialized extra accounts in body', :aggregate_failures do expect(response).to have_http_status(422) - end - - it 'returns serialized extra accounts in body' do expect(body_as_json[:unexpected_accounts].map { |a| a.slice(:id, :acct) }).to eq [{ id: bob.id.to_s, acct: bob.acct }] end end @@ -157,11 +142,8 @@ RSpec.describe Api::V1::StatusesController do post :create, params: {} end - it 'returns http unprocessable entity' do + it 'returns rate limit headers', :aggregate_failures 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 @@ -173,11 +155,8 @@ RSpec.describe Api::V1::StatusesController do post :create, params: { status: 'Hello world' } end - it 'returns http too many requests' do + it 'returns rate limit headers', :aggregate_failures 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 @@ -192,11 +171,8 @@ RSpec.describe Api::V1::StatusesController do post :destroy, params: { id: status.id } end - it 'returns http success' do + it 'removes the status', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'removes the status' do expect(Status.find_by(id: status.id)).to be_nil end end @@ -209,11 +185,8 @@ RSpec.describe Api::V1::StatusesController do put :update, params: { id: status.id, status: 'I am updated' } end - it 'returns http success' do + it 'updates the status', :aggregate_failures do expect(response).to have_http_status(200) - end - - it 'updates the status' do expect(status.reload.text).to eq 'I am updated' end end diff --git a/spec/controllers/api/v2/admin/accounts_controller_spec.rb b/spec/controllers/api/v2/admin/accounts_controller_spec.rb index 635f645915..18b3950140 100644 --- a/spec/controllers/api/v2/admin/accounts_controller_spec.rb +++ b/spec/controllers/api/v2/admin/accounts_controller_spec.rb @@ -44,14 +44,14 @@ RSpec.describe Api::V2::Admin::AccountsController do context "when called with #{params.inspect}" do let(:params) { params } - it 'returns http success' do + it "returns the correct accounts (#{expected_results.inspect})" do expect(response).to have_http_status(200) + + expect(body_json_ids).to eq(expected_results.map { |symbol| send(symbol).id }) end - it "returns the correct accounts (#{expected_results.inspect})" do - json = body_as_json - - expect(json.map { |a| a[:id].to_i }).to eq(expected_results.map { |symbol| send(symbol).id }) + def body_json_ids + body_as_json.map { |a| a[:id].to_i } end end end diff --git a/spec/controllers/api/v2/filters/keywords_controller_spec.rb b/spec/controllers/api/v2/filters/keywords_controller_spec.rb index 057a9c3d00..5321f787a1 100644 --- a/spec/controllers/api/v2/filters/keywords_controller_spec.rb +++ b/spec/controllers/api/v2/filters/keywords_controller_spec.rb @@ -40,17 +40,13 @@ RSpec.describe Api::V2::Filters::KeywordsController do post :create, params: { filter_id: filter_id, keyword: 'magic', whole_word: false } end - it 'returns http success' do + it 'creates a filter', :aggregate_failures do expect(response).to have_http_status(200) - end - it 'returns a keyword' do json = body_as_json expect(json[:keyword]).to eq 'magic' expect(json[:whole_word]).to be false - end - it 'creates a keyword' do filter = user.account.custom_filters.first expect(filter).to_not be_nil expect(filter.keywords.pluck(:keyword)).to eq ['magic'] @@ -73,11 +69,9 @@ RSpec.describe Api::V2::Filters::KeywordsController do get :show, params: { id: keyword.id } end - it 'returns http success' do + it 'responds with the keyword', :aggregate_failures do expect(response).to have_http_status(200) - end - it 'returns expected data' do json = body_as_json expect(json[:keyword]).to eq 'foo' expect(json[:whole_word]).to be false @@ -100,11 +94,9 @@ RSpec.describe Api::V2::Filters::KeywordsController do get :update, params: { id: keyword.id, keyword: 'updated' } end - it 'returns http success' do + it 'updates the keyword', :aggregate_failures do expect(response).to have_http_status(200) - end - it 'updates the keyword' do expect(keyword.reload.keyword).to eq 'updated' end @@ -125,11 +117,9 @@ RSpec.describe Api::V2::Filters::KeywordsController do delete :destroy, params: { id: keyword.id } end - it 'returns http success' do + it 'destroys the keyword', :aggregate_failures do expect(response).to have_http_status(200) - end - it 'removes the filter' do expect { keyword.reload }.to raise_error ActiveRecord::RecordNotFound end diff --git a/spec/controllers/api/v2/filters/statuses_controller_spec.rb b/spec/controllers/api/v2/filters/statuses_controller_spec.rb index 588532ffd2..5c2a623954 100644 --- a/spec/controllers/api/v2/filters/statuses_controller_spec.rb +++ b/spec/controllers/api/v2/filters/statuses_controller_spec.rb @@ -41,16 +41,12 @@ RSpec.describe Api::V2::Filters::StatusesController do post :create, params: { filter_id: filter_id, status_id: status.id } end - it 'returns http success' do + it 'creates a filter', :aggregate_failures do expect(response).to have_http_status(200) - end - it 'returns a status filter' do json = body_as_json expect(json[:status_id]).to eq status.id.to_s - end - it 'creates a status filter' do filter = user.account.custom_filters.first expect(filter).to_not be_nil expect(filter.statuses.pluck(:status_id)).to eq [status.id] @@ -73,11 +69,9 @@ RSpec.describe Api::V2::Filters::StatusesController do get :show, params: { id: status_filter.id } end - it 'returns http success' do + it 'responds with the filter', :aggregate_failures do expect(response).to have_http_status(200) - end - it 'returns expected data' do json = body_as_json expect(json[:status_id]).to eq status_filter.status_id.to_s end @@ -99,11 +93,9 @@ RSpec.describe Api::V2::Filters::StatusesController do delete :destroy, params: { id: status_filter.id } end - it 'returns http success' do + it 'destroys the filter', :aggregate_failures do expect(response).to have_http_status(200) - end - it 'removes the filter' do expect { status_filter.reload }.to raise_error ActiveRecord::RecordNotFound end diff --git a/spec/requests/api/v1/admin/account_actions_spec.rb b/spec/requests/api/v1/admin/account_actions_spec.rb index 9295d262d6..bdf1f08e43 100644 --- a/spec/requests/api/v1/admin/account_actions_spec.rb +++ b/spec/requests/api/v1/admin/account_actions_spec.rb @@ -51,14 +51,9 @@ RSpec.describe 'Account actions' do it_behaves_like 'a successful notification delivery' it_behaves_like 'a successful logged action', :disable, :user - it 'returns http success' do - subject - - expect(response).to have_http_status(200) - end - it 'disables the target account' do expect { subject }.to change { target_account.reload.user_disabled? }.from(false).to(true) + expect(response).to have_http_status(200) end end @@ -70,14 +65,9 @@ RSpec.describe 'Account actions' do it_behaves_like 'a successful notification delivery' it_behaves_like 'a successful logged action', :sensitive, :account - it 'returns http success' do - subject - - expect(response).to have_http_status(200) - end - it 'marks the target account as sensitive' do expect { subject }.to change { target_account.reload.sensitized? }.from(false).to(true) + expect(response).to have_http_status(200) end end @@ -89,14 +79,9 @@ RSpec.describe 'Account actions' do it_behaves_like 'a successful notification delivery' it_behaves_like 'a successful logged action', :silence, :account - it 'returns http success' do - subject - - expect(response).to have_http_status(200) - end - it 'marks the target account as silenced' do expect { subject }.to change { target_account.reload.silenced? }.from(false).to(true) + expect(response).to have_http_status(200) end end @@ -108,14 +93,9 @@ RSpec.describe 'Account actions' do it_behaves_like 'a successful notification delivery' it_behaves_like 'a successful logged action', :suspend, :account - it 'returns http success' do - subject - - expect(response).to have_http_status(200) - end - it 'marks the target account as suspended' do expect { subject }.to change { target_account.reload.suspended? }.from(false).to(true) + expect(response).to have_http_status(200) end end diff --git a/spec/requests/api/v1/admin/canonical_email_blocks_spec.rb b/spec/requests/api/v1/admin/canonical_email_blocks_spec.rb index 4382cb84e5..3f33b50f39 100644 --- a/spec/requests/api/v1/admin/canonical_email_blocks_spec.rb +++ b/spec/requests/api/v1/admin/canonical_email_blocks_spec.rb @@ -92,15 +92,10 @@ RSpec.describe 'Canonical Email Blocks' do it_behaves_like 'forbidden for wrong role', 'Moderator' context 'when the requested canonical email block exists' do - it 'returns http success' do + it 'returns the requested canonical email block data correctly', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'returns the requested canonical email block data correctly' do - subject - json = body_as_json expect(json[:id]).to eq(canonical_email_block.id.to_s) @@ -142,29 +137,19 @@ RSpec.describe 'Canonical Email Blocks' do context 'when there is a matching canonical email block' do let!(:canonical_email_block) { CanonicalEmailBlock.create(params) } - it 'returns http success' do + it 'returns the expected canonical email hash', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'returns the expected canonical email hash' do - subject - expect(body_as_json[0][:canonical_email_hash]).to eq(canonical_email_block.canonical_email_hash) end end context 'when there is no matching canonical email block' do - it 'returns http success' do + it 'returns an empty list', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'returns an empty list' do - subject - expect(body_as_json).to be_empty end end @@ -183,15 +168,10 @@ RSpec.describe 'Canonical Email Blocks' do it_behaves_like 'forbidden for wrong role', '' it_behaves_like 'forbidden for wrong role', 'Moderator' - it 'returns http success' do + it 'returns the canonical_email_hash correctly', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'returns the canonical_email_hash correctly' do - subject - expect(body_as_json[:canonical_email_hash]).to eq(canonical_email_block.canonical_email_hash) end @@ -208,15 +188,10 @@ RSpec.describe 'Canonical Email Blocks' do context 'when the canonical_email_hash param is provided instead of email' do let(:params) { { canonical_email_hash: 'dd501ce4e6b08698f19df96f2f15737e48a75660b1fa79b6ff58ea25ee4851a4' } } - it 'returns http success' do + it 'returns the correct canonical_email_hash', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'returns the correct canonical_email_hash' do - subject - expect(body_as_json[:canonical_email_hash]).to eq(params[:canonical_email_hash]) end end @@ -224,15 +199,10 @@ RSpec.describe 'Canonical Email Blocks' do context 'when both email and canonical_email_hash params are provided' do let(:params) { { email: 'example@email.com', canonical_email_hash: 'dd501ce4e6b08698f19df96f2f15737e48a75660b1fa79b6ff58ea25ee4851a4' } } - it 'returns http success' do + it 'ignores the canonical_email_hash param', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'ignores the canonical_email_hash param' do - subject - expect(body_as_json[:canonical_email_hash]).to eq(canonical_email_block.canonical_email_hash) end end @@ -262,15 +232,10 @@ RSpec.describe 'Canonical Email Blocks' do it_behaves_like 'forbidden for wrong role', '' it_behaves_like 'forbidden for wrong role', 'Moderator' - it 'returns http success' do + it 'deletes the canonical email block', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'deletes the canonical email block' do - subject - expect(CanonicalEmailBlock.find_by(id: canonical_email_block.id)).to be_nil end diff --git a/spec/requests/api/v1/admin/domain_allows_spec.rb b/spec/requests/api/v1/admin/domain_allows_spec.rb index 96000e3ef4..6db1ab6e30 100644 --- a/spec/requests/api/v1/admin/domain_allows_spec.rb +++ b/spec/requests/api/v1/admin/domain_allows_spec.rb @@ -75,15 +75,10 @@ RSpec.describe 'Domain Allows' do it_behaves_like 'forbidden for wrong role', '' it_behaves_like 'forbidden for wrong role', 'Moderator' - it 'returns http success' do + it 'returns the expected allowed domain name', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'returns the expected allowed domain name' do - subject - expect(body_as_json[:domain]).to eq domain_allow.domain end @@ -108,21 +103,11 @@ RSpec.describe 'Domain Allows' do it_behaves_like 'forbidden for wrong role', 'Moderator' context 'with a valid domain name' do - it 'returns http success' do + it 'returns the expected domain name', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'returns the expected domain name' do - subject - expect(body_as_json[:domain]).to eq 'foo.bar.com' - end - - it 'creates a domain allow' do - subject - expect(DomainAllow.find_by(domain: 'foo.bar.com')).to be_present end end @@ -171,15 +156,10 @@ RSpec.describe 'Domain Allows' do it_behaves_like 'forbidden for wrong role', '' it_behaves_like 'forbidden for wrong role', 'Moderator' - it 'returns http success' do + it 'deletes the allowed domain', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'deletes the allowed domain' do - subject - expect(DomainAllow.find_by(id: domain_allow.id)).to be_nil end diff --git a/spec/requests/api/v1/admin/domain_blocks_spec.rb b/spec/requests/api/v1/admin/domain_blocks_spec.rb index 7a5ac28c56..1fb6fc8228 100644 --- a/spec/requests/api/v1/admin/domain_blocks_spec.rb +++ b/spec/requests/api/v1/admin/domain_blocks_spec.rb @@ -89,15 +89,10 @@ RSpec.describe 'Domain Blocks' do it_behaves_like 'forbidden for wrong role', '' it_behaves_like 'forbidden for wrong role', 'Moderator' - it 'returns http success' do + it 'returns the expected domain block content', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'returns the expected domain block content' do - subject - expect(body_as_json).to eq( { id: domain_block.id.to_s, @@ -133,27 +128,18 @@ RSpec.describe 'Domain Blocks' do it_behaves_like 'forbidden for wrong role', '' it_behaves_like 'forbidden for wrong role', 'Moderator' - it 'returns http success' do - subject - - expect(response).to have_http_status(200) - end - - it 'returns expected domain name and severity' do + it 'returns expected domain name and severity', :aggregate_failures do subject body = body_as_json + expect(response).to have_http_status(200) expect(body).to match a_hash_including( { domain: 'foo.bar.com', severity: 'silence', } ) - end - - it 'creates a domain block' do - subject expect(DomainBlock.find_by(domain: 'foo.bar.com')).to be_present end @@ -163,15 +149,10 @@ RSpec.describe 'Domain Blocks' do Fabricate(:domain_block, domain: 'bar.com', severity: :suspend) end - it 'returns http unprocessable entity' do + it 'returns existing domain block in error', :aggregate_failures do subject expect(response).to have_http_status(422) - end - - it 'returns existing domain block in error' do - subject - expect(body_as_json[:existing_domain_block][:domain]).to eq('bar.com') end end @@ -199,15 +180,10 @@ RSpec.describe 'Domain Blocks' do it_behaves_like 'forbidden for wrong role', '' it_behaves_like 'forbidden for wrong role', 'Moderator' - it 'returns http success' do + it 'returns the updated domain block', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'returns the updated domain block' do - subject - expect(body_as_json).to match a_hash_including( { id: domain_block.id.to_s, @@ -241,15 +217,10 @@ RSpec.describe 'Domain Blocks' do it_behaves_like 'forbidden for wrong role', '' it_behaves_like 'forbidden for wrong role', 'Moderator' - it 'returns http success' do + it 'deletes the domain block', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'deletes the domain block' do - subject - expect(DomainBlock.find_by(id: domain_block.id)).to be_nil end diff --git a/spec/requests/api/v1/admin/email_domain_blocks_spec.rb b/spec/requests/api/v1/admin/email_domain_blocks_spec.rb index d512def866..16656e0202 100644 --- a/spec/requests/api/v1/admin/email_domain_blocks_spec.rb +++ b/spec/requests/api/v1/admin/email_domain_blocks_spec.rb @@ -93,15 +93,10 @@ RSpec.describe 'Email Domain Blocks' do it_behaves_like 'forbidden for wrong role', 'Moderator' context 'when email domain block exists' do - it 'returns http success' do + it 'returns the correct blocked domain', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'returns the correct blocked domain' do - subject - expect(body_as_json[:domain]).to eq(email_domain_block.domain) end end @@ -126,15 +121,10 @@ RSpec.describe 'Email Domain Blocks' do it_behaves_like 'forbidden for wrong role', '' it_behaves_like 'forbidden for wrong role', 'Moderator' - it 'returns http success' do + it 'returns the correct blocked email domain', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'returns the correct blocked email domain' do - subject - expect(body_as_json[:domain]).to eq(params[:domain]) end @@ -182,21 +172,11 @@ RSpec.describe 'Email Domain Blocks' do it_behaves_like 'forbidden for wrong role', '' it_behaves_like 'forbidden for wrong role', 'Moderator' - it 'returns http success' do + it 'deletes email domain block', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'returns an empty body' do - subject - expect(body_as_json).to be_empty - end - - it 'deletes email domain block' do - subject - expect(EmailDomainBlock.find_by(id: email_domain_block.id)).to be_nil end diff --git a/spec/requests/api/v1/admin/ip_blocks_spec.rb b/spec/requests/api/v1/admin/ip_blocks_spec.rb index d03886c51b..fbcb39e3be 100644 --- a/spec/requests/api/v1/admin/ip_blocks_spec.rb +++ b/spec/requests/api/v1/admin/ip_blocks_spec.rb @@ -84,15 +84,10 @@ RSpec.describe 'IP Blocks' do it_behaves_like 'forbidden for wrong role', '' it_behaves_like 'forbidden for wrong role', 'Moderator' - it 'returns http success' do + it 'returns the correct ip block', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'returns the correct ip block' do - subject - json = body_as_json expect(json[:ip]).to eq("#{ip_block.ip}/#{ip_block.ip.prefix}") @@ -119,15 +114,10 @@ RSpec.describe 'IP Blocks' do it_behaves_like 'forbidden for wrong role', '' it_behaves_like 'forbidden for wrong role', 'Moderator' - it 'returns http success' do + it 'returns the correct ip block', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'returns the correct ip block' do - subject - json = body_as_json expect(json[:ip]).to eq("#{params[:ip]}/32") @@ -186,15 +176,10 @@ RSpec.describe 'IP Blocks' do let!(:ip_block) { IpBlock.create(ip: '185.200.13.3', severity: 'no_access', comment: 'Spam', expires_in: 48.hours) } let(:params) { { severity: 'sign_up_requires_approval', comment: 'Decreasing severity' } } - it 'returns http success' do + it 'returns the correct ip block', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'returns the correct ip block' do - subject - expect(body_as_json).to match(hash_including({ ip: "#{ip_block.ip}/#{ip_block.ip.prefix}", severity: 'sign_up_requires_approval', @@ -226,21 +211,11 @@ RSpec.describe 'IP Blocks' do let!(:ip_block) { IpBlock.create(ip: '185.200.13.3', severity: 'no_access') } - it 'returns http success' do + it 'deletes the ip block', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'returns an empty body' do - subject - expect(body_as_json).to be_empty - end - - it 'deletes the ip block' do - subject - expect(IpBlock.find_by(id: ip_block.id)).to be_nil end diff --git a/spec/requests/api/v1/admin/reports_spec.rb b/spec/requests/api/v1/admin/reports_spec.rb index 91c3c11f5d..5403457db0 100644 --- a/spec/requests/api/v1/admin/reports_spec.rb +++ b/spec/requests/api/v1/admin/reports_spec.rb @@ -122,15 +122,10 @@ RSpec.describe 'Reports' do it_behaves_like 'forbidden for wrong scope', 'write:statuses' it_behaves_like 'forbidden for wrong role', '' - it 'returns http success' do + it 'returns the requested report content', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'returns the requested report content' do - subject - expect(body_as_json).to include( { id: report.id.to_s, @@ -155,18 +150,10 @@ RSpec.describe 'Reports' do let!(:report) { Fabricate(:report, category: :other) } let(:params) { { category: 'spam' } } - it 'returns http success' do - subject + it 'updates the report category', :aggregate_failures do + expect { subject }.to change { report.reload.category }.from('other').to('spam') expect(response).to have_http_status(200) - end - - it 'updates the report category' do - expect { subject }.to change { report.reload.category }.from('other').to('spam') - end - - it 'returns the updated report content' do - subject report.reload @@ -196,14 +183,9 @@ RSpec.describe 'Reports' do it_behaves_like 'forbidden for wrong scope', 'write:statuses' it_behaves_like 'forbidden for wrong role', '' - it 'returns http success' do - subject - - expect(response).to have_http_status(200) - end - - it 'marks report as resolved' do + it 'marks report as resolved', :aggregate_failures do expect { subject }.to change { report.reload.unresolved? }.from(true).to(false) + expect(response).to have_http_status(200) end end @@ -217,14 +199,9 @@ RSpec.describe 'Reports' do it_behaves_like 'forbidden for wrong scope', 'write:statuses' it_behaves_like 'forbidden for wrong role', '' - it 'returns http success' do - subject - - expect(response).to have_http_status(200) - end - - it 'marks report as unresolved' do + it 'marks report as unresolved', :aggregate_failures do expect { subject }.to change { report.reload.unresolved? }.from(false).to(true) + expect(response).to have_http_status(200) end end @@ -238,14 +215,9 @@ RSpec.describe 'Reports' do it_behaves_like 'forbidden for wrong scope', 'write:statuses' it_behaves_like 'forbidden for wrong role', '' - it 'returns http success' do - subject - - expect(response).to have_http_status(200) - end - - it 'assigns report to the requesting user' do + it 'assigns report to the requesting user', :aggregate_failures do expect { subject }.to change { report.reload.assigned_account_id }.from(nil).to(user.account.id) + expect(response).to have_http_status(200) end end @@ -259,14 +231,9 @@ RSpec.describe 'Reports' do it_behaves_like 'forbidden for wrong scope', 'write:statuses' it_behaves_like 'forbidden for wrong role', '' - it 'returns http success' do - subject - - expect(response).to have_http_status(200) - end - - it 'unassigns report from assignee' do + it 'unassigns report from assignee', :aggregate_failures do expect { subject }.to change { report.reload.assigned_account_id }.from(user.account.id).to(nil) + expect(response).to have_http_status(200) end end end diff --git a/spec/requests/api/v1/apps/credentials_spec.rb b/spec/requests/api/v1/apps/credentials_spec.rb index dafe168c56..1268b36f8a 100644 --- a/spec/requests/api/v1/apps/credentials_spec.rb +++ b/spec/requests/api/v1/apps/credentials_spec.rb @@ -12,14 +12,10 @@ describe 'Credentials' do let(:token) { Fabricate(:accessible_access_token, scopes: 'read', application: Fabricate(:application)) } let(:headers) { { 'Authorization' => "Bearer #{token.token}" } } - it 'returns http success' do + it 'returns the app information correctly', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'returns the app information correctly' do - subject expect(body_as_json).to match( a_hash_including( diff --git a/spec/requests/api/v1/apps_spec.rb b/spec/requests/api/v1/apps_spec.rb index 88f9eee360..acabbc93f0 100644 --- a/spec/requests/api/v1/apps_spec.rb +++ b/spec/requests/api/v1/apps_spec.rb @@ -23,20 +23,11 @@ RSpec.describe 'Apps' do end context 'with valid params' do - it 'returns http success' do + it 'creates an OAuth app', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'creates an OAuth app' do - subject - expect(Doorkeeper::Application.find_by(name: client_name)).to be_present - end - - it 'returns client ID and client secret' do - subject body = body_as_json @@ -58,15 +49,10 @@ RSpec.describe 'Apps' do context 'with many duplicate scopes' do let(:scopes) { (%w(read) * 40).join(' ') } - it 'returns http success' do + it 'only saves the scope once', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'only saves the scope once' do - subject - expect(Doorkeeper::Application.find_by(name: client_name).scopes.to_s).to eq 'read' end end diff --git a/spec/requests/api/v1/domain_blocks_spec.rb b/spec/requests/api/v1/domain_blocks_spec.rb index 0f4fd4e90e..954497ebe1 100644 --- a/spec/requests/api/v1/domain_blocks_spec.rb +++ b/spec/requests/api/v1/domain_blocks_spec.rb @@ -22,15 +22,10 @@ RSpec.describe 'Domain blocks' do it_behaves_like 'forbidden for wrong scope', 'write:blocks' - it 'returns http success' do + it 'returns the domains blocked by the requesting user', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'returns the domains blocked by the requesting user' do - subject - expect(body_as_json).to match_array(blocked_domains) end @@ -54,15 +49,10 @@ RSpec.describe 'Domain blocks' do it_behaves_like 'forbidden for wrong scope', 'read read:blocks' - it 'returns http success' do + it 'creates a domain block', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'creates a domain block' do - subject - expect(user.account.domain_blocking?(params[:domain])).to be(true) end @@ -100,15 +90,10 @@ RSpec.describe 'Domain blocks' do it_behaves_like 'forbidden for wrong scope', 'read read:blocks' - it 'returns http success' do + it 'deletes the specified domain block', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'deletes the specified domain block' do - subject - expect(user.account.domain_blocking?('example.com')).to be(false) end diff --git a/spec/requests/api/v1/follow_requests_spec.rb b/spec/requests/api/v1/follow_requests_spec.rb index 9d4ef8cd55..1d78c9be19 100644 --- a/spec/requests/api/v1/follow_requests_spec.rb +++ b/spec/requests/api/v1/follow_requests_spec.rb @@ -32,15 +32,10 @@ RSpec.describe 'Follow requests' do it_behaves_like 'forbidden for wrong scope', 'write write:follows' - it 'returns http success' do + it 'returns the expected content from accounts requesting to follow', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'returns the expected content from accounts requesting to follow' do - subject - expect(body_as_json).to match_array(expected_response) end @@ -68,19 +63,9 @@ RSpec.describe 'Follow requests' do it_behaves_like 'forbidden for wrong scope', 'read read:follows' - it 'returns http success' do - subject - - expect(response).to have_http_status(200) - end - - it 'allows the requesting follower to follow' do + it 'allows the requesting follower to follow', :aggregate_failures do expect { subject }.to change { follower.following?(user.account) }.from(false).to(true) - end - - it 'returns JSON with followed_by set to true' do - subject - + expect(response).to have_http_status(200) expect(body_as_json[:followed_by]).to be true end end @@ -98,21 +83,11 @@ RSpec.describe 'Follow requests' do it_behaves_like 'forbidden for wrong scope', 'read read:follows' - it 'returns http success' do + it 'removes the follow request', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'removes the follow request' do - subject - expect(FollowRequest.where(target_account: user.account, account: follower)).to_not exist - end - - it 'returns JSON with followed_by set to false' do - subject - expect(body_as_json[:followed_by]).to be false end end diff --git a/spec/requests/api/v1/lists_spec.rb b/spec/requests/api/v1/lists_spec.rb index 383e09d0c3..22dde43a19 100644 --- a/spec/requests/api/v1/lists_spec.rb +++ b/spec/requests/api/v1/lists_spec.rb @@ -39,15 +39,10 @@ RSpec.describe 'Lists' do it_behaves_like 'forbidden for wrong scope', 'write write:lists' - it 'returns http success' do + it 'returns the expected lists', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'returns the expected lists' do - subject - expect(body_as_json).to match_array(expected_response) end end @@ -61,15 +56,10 @@ RSpec.describe 'Lists' do it_behaves_like 'forbidden for wrong scope', 'write write:lists' - it 'returns http success' do + it 'returns the requested list correctly', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'returns the requested list correctly' do - subject - expect(body_as_json).to eq({ id: list.id.to_s, title: list.title, @@ -106,21 +96,11 @@ RSpec.describe 'Lists' do it_behaves_like 'forbidden for wrong scope', 'read read:lists' - it 'returns http success' do + it 'returns the new list', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'returns the new list' do - subject - expect(body_as_json).to match(a_hash_including(title: 'my list', replies_policy: 'none', exclusive: true)) - end - - it 'creates a list' do - subject - expect(List.where(account: user.account).count).to eq(1) end @@ -155,15 +135,10 @@ RSpec.describe 'Lists' do it_behaves_like 'forbidden for wrong scope', 'read read:lists' - it 'returns http success' do + it 'returns the updated list', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'returns the updated list' do - subject - list.reload expect(body_as_json).to eq({ @@ -214,15 +189,10 @@ RSpec.describe 'Lists' do it_behaves_like 'forbidden for wrong scope', 'read read:lists' - it 'returns http success' do + it 'deletes the list', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'deletes the list' do - subject - expect(List.where(id: list.id)).to_not exist end diff --git a/spec/requests/api/v1/tags_spec.rb b/spec/requests/api/v1/tags_spec.rb index 300ddf805c..db74a6f037 100644 --- a/spec/requests/api/v1/tags_spec.rb +++ b/spec/requests/api/v1/tags_spec.rb @@ -17,15 +17,10 @@ RSpec.describe 'Tags' do let!(:tag) { Fabricate(:tag) } let(:name) { tag.name } - it 'returns http success' do + it 'returns the tag', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'returns the tag' do - subject - expect(body_as_json[:name]).to eq(name) end end @@ -62,15 +57,10 @@ RSpec.describe 'Tags' do it_behaves_like 'forbidden for wrong scope', 'read read:follows' context 'when the tag exists' do - it 'returns http success' do + it 'creates follow', :aggregate_failures do subject expect(response).to have_http_status(:success) - end - - it 'creates follow' do - subject - expect(TagFollow.where(tag: tag, account: user.account)).to exist end end @@ -78,21 +68,11 @@ RSpec.describe 'Tags' do context 'when the tag does not exist' do let(:name) { 'hoge' } - it 'returns http success' do + it 'creates a new tag with the specified name', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'creates a new tag with the specified name' do - subject - expect(Tag.where(name: name)).to exist - end - - it 'creates follow' do - subject - expect(TagFollow.where(tag: Tag.find_by(name: name), account: user.account)).to exist end end @@ -133,15 +113,10 @@ RSpec.describe 'Tags' do it_behaves_like 'forbidden for wrong scope', 'read read:follows' - it 'returns http success' do + it 'removes the follow', :aggregate_failures do subject expect(response).to have_http_status(200) - end - - it 'removes the follow' do - subject - expect(TagFollow.where(tag: tag, account: user.account)).to_not exist end From bc6cd27d9edc473da3403c9af7970db8114b2135 Mon Sep 17 00:00:00 2001 From: Daniel M Brasil Date: Fri, 13 Oct 2023 09:43:50 -0300 Subject: [PATCH 40/58] Migrate to request specs in `/api/v1/followed_tags` (#25472) --- .rubocop_todo.yml | 1 - .../api/v1/followed_tags_controller_spec.rb | 25 ------- spec/requests/api/v1/followed_tags_spec.rb | 65 +++++++++++++++++++ 3 files changed, 65 insertions(+), 26 deletions(-) delete mode 100644 spec/controllers/api/v1/followed_tags_controller_spec.rb create mode 100644 spec/requests/api/v1/followed_tags_spec.rb diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 19cfcff7f7..d58bee4ba8 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -180,7 +180,6 @@ RSpec/LetSetup: - 'spec/controllers/api/v1/accounts/statuses_controller_spec.rb' - 'spec/controllers/api/v1/admin/accounts_controller_spec.rb' - 'spec/controllers/api/v1/filters_controller_spec.rb' - - 'spec/controllers/api/v1/followed_tags_controller_spec.rb' - 'spec/controllers/api/v2/admin/accounts_controller_spec.rb' - 'spec/controllers/api/v2/filters/keywords_controller_spec.rb' - 'spec/controllers/api/v2/filters/statuses_controller_spec.rb' diff --git a/spec/controllers/api/v1/followed_tags_controller_spec.rb b/spec/controllers/api/v1/followed_tags_controller_spec.rb deleted file mode 100644 index c1a366d4e3..0000000000 --- a/spec/controllers/api/v1/followed_tags_controller_spec.rb +++ /dev/null @@ -1,25 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe Api::V1::FollowedTagsController do - render_views - - let(:user) { Fabricate(:user) } - let(:scopes) { 'read:follows' } - let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) } - - before { allow(controller).to receive(:doorkeeper_token) { token } } - - describe 'GET #index' do - let!(:tag_follows) { Fabricate.times(5, :tag_follow, account: user.account) } - - before do - get :index, params: { limit: 1 } - end - - it 'returns http success' do - expect(response).to have_http_status(:success) - end - end -end diff --git a/spec/requests/api/v1/followed_tags_spec.rb b/spec/requests/api/v1/followed_tags_spec.rb new file mode 100644 index 0000000000..9391c7bdc8 --- /dev/null +++ b/spec/requests/api/v1/followed_tags_spec.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Followed tags' do + let(:user) { Fabricate(:user) } + let(:scopes) { 'read:follows' } + let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) } + let(:headers) { { 'Authorization' => "Bearer #{token.token}" } } + + describe 'GET /api/v1/followed_tags' do + subject do + get '/api/v1/followed_tags', headers: headers, params: params + end + + let!(:tag_follows) { Fabricate.times(5, :tag_follow, account: user.account) } + let(:params) { {} } + + let(:expected_response) do + tag_follows.map do |tag_follow| + a_hash_including(name: tag_follow.tag.name, following: true) + end + end + + before do + Fabricate(:tag_follow) + end + + it_behaves_like 'forbidden for wrong scope', 'write write:follows' + + it 'returns http success' do + subject + + expect(response).to have_http_status(:success) + end + + it 'returns the followed tags correctly' do + subject + + expect(body_as_json).to match_array(expected_response) + end + + context 'with limit param' do + let(:params) { { limit: 3 } } + + it 'returns only the requested number of follow tags' do + subject + + expect(body_as_json.size).to eq(params[:limit]) + end + + it 'sets the correct pagination header for the prev path' do + subject + + expect(response.headers['Link'].find_link(%w(rel prev)).href).to eq(api_v1_followed_tags_url(limit: params[:limit], since_id: tag_follows.last.id)) + end + + it 'sets the correct pagination header for the next path' do + subject + + expect(response.headers['Link'].find_link(%w(rel next)).href).to eq(api_v1_followed_tags_url(limit: params[:limit], max_id: tag_follows[2].id)) + end + end + end +end From abf0e1fa39f67baecab5c3893845e34a0f7be198 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 13 Oct 2023 09:19:40 -0400 Subject: [PATCH 41/58] Move `SignedReqestHelpers` rspec config to separate file (#25453) --- spec/rails_helper.rb | 20 -------------------- spec/support/signed_request_helpers.rb | 21 +++++++++++++++++++++ 2 files changed, 21 insertions(+), 20 deletions(-) create mode 100644 spec/support/signed_request_helpers.rb diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 7b8dccb6a0..06e8418a0e 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -54,26 +54,6 @@ Devise::Test::ControllerHelpers.module_eval do end end -module SignedRequestHelpers - def get(path, headers: nil, sign_with: nil, **args) - return super path, headers: headers, **args if sign_with.nil? - - headers ||= {} - headers['Date'] = Time.now.utc.httpdate - headers['Host'] = ENV.fetch('LOCAL_DOMAIN') - signed_headers = headers.merge('(request-target)' => "get #{path}").slice('(request-target)', 'Host', 'Date') - - key_id = ActivityPub::TagManager.instance.key_uri_for(sign_with) - keypair = sign_with.keypair - signed_string = signed_headers.map { |key, value| "#{key.downcase}: #{value}" }.join("\n") - signature = Base64.strict_encode64(keypair.sign(OpenSSL::Digest.new('SHA256'), signed_string)) - - headers['Signature'] = "keyId=\"#{key_id}\",algorithm=\"rsa-sha256\",headers=\"#{signed_headers.keys.join(' ').downcase}\",signature=\"#{signature}\"" - - super path, headers: headers, **args - end -end - RSpec.configure do |config| # This is set before running spec:system, see lib/tasks/tests.rake config.filter_run_excluding type: lambda { |type| diff --git a/spec/support/signed_request_helpers.rb b/spec/support/signed_request_helpers.rb new file mode 100644 index 0000000000..33d7dba6b8 --- /dev/null +++ b/spec/support/signed_request_helpers.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +module SignedRequestHelpers + def get(path, headers: nil, sign_with: nil, **args) + return super path, headers: headers, **args if sign_with.nil? + + headers ||= {} + headers['Date'] = Time.now.utc.httpdate + headers['Host'] = ENV.fetch('LOCAL_DOMAIN') + signed_headers = headers.merge('(request-target)' => "get #{path}").slice('(request-target)', 'Host', 'Date') + + key_id = ActivityPub::TagManager.instance.key_uri_for(sign_with) + keypair = sign_with.keypair + signed_string = signed_headers.map { |key, value| "#{key.downcase}: #{value}" }.join("\n") + signature = Base64.strict_encode64(keypair.sign(OpenSSL::Digest.new('SHA256'), signed_string)) + + headers['Signature'] = "keyId=\"#{key_id}\",algorithm=\"rsa-sha256\",headers=\"#{signed_headers.keys.join(' ').downcase}\",signature=\"#{signature}\"" + + super path, headers: headers, **args + end +end From 058f73a4f5f17fc33bb842115d1f69a4b2e9f740 Mon Sep 17 00:00:00 2001 From: Daniel M Brasil Date: Fri, 13 Oct 2023 10:30:40 -0300 Subject: [PATCH 42/58] Add request specs for `/api/v1/reports` (#25475) --- spec/requests/api/v1/reports_spec.rb | 106 +++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 spec/requests/api/v1/reports_spec.rb diff --git a/spec/requests/api/v1/reports_spec.rb b/spec/requests/api/v1/reports_spec.rb new file mode 100644 index 0000000000..ce74f17c48 --- /dev/null +++ b/spec/requests/api/v1/reports_spec.rb @@ -0,0 +1,106 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Reports' do + let(:user) { Fabricate(:user) } + let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) } + let(:scopes) { 'write:reports' } + let(:headers) { { 'Authorization' => "Bearer #{token.token}" } } + + describe 'POST /api/v1/reports' do + subject do + post '/api/v1/reports', headers: headers, params: params + end + + let!(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } + let(:status) { Fabricate(:status) } + let(:target_account) { status.account } + let(:category) { 'other' } + let(:forward) { nil } + let(:rule_ids) { nil } + + let(:params) do + { + status_ids: [status.id], + account_id: target_account.id, + comment: 'reasons', + category: category, + rule_ids: rule_ids, + forward: forward, + } + end + + it_behaves_like 'forbidden for wrong scope', 'read read:reports' + + it 'returns http success' do + subject + + expect(response).to have_http_status(200) + end + + it 'returns the created report' do + subject + + expect(body_as_json).to match( + a_hash_including( + status_ids: [status.id.to_s], + category: category, + comment: 'reasons' + ) + ) + end + + it 'creates a report' do + subject + + expect(target_account.targeted_reports).to_not be_empty + end + + it 'sends e-mails to admins' do + perform_enqueued_jobs do + subject + + expect(ActionMailer::Base.deliveries.first.to).to eq([admin.email]) + end + end + + context 'when a status does not belong to the reported account' do + let(:target_account) { Fabricate(:account) } + + it 'returns http not found' do + subject + + expect(response).to have_http_status(404) + end + end + + context 'when a category is chosen' do + let(:category) { 'spam' } + + it 'saves category' do + subject + + expect(target_account.targeted_reports.first.spam?).to be true + end + end + + context 'when violated rules are chosen' do + let(:rule) { Fabricate(:rule) } + let(:category) { 'violation' } + let(:rule_ids) { [rule.id] } + + it 'saves category' do + subject + + expect(target_account.targeted_reports.first.violation?).to be true + end + + it 'saves rule_ids' do + subject + + expect(target_account.targeted_reports.first.rule_ids).to contain_exactly(rule.id) + end + end + end +end From cad8cc90baf721fc4269b8ac36d4411ce8fe8539 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 13 Oct 2023 09:50:46 -0400 Subject: [PATCH 43/58] Speed-up on `MoveWorker` spec (#25528) --- spec/workers/move_worker_spec.rb | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/spec/workers/move_worker_spec.rb b/spec/workers/move_worker_spec.rb index 7577f6e896..efad92c047 100644 --- a/spec/workers/move_worker_spec.rb +++ b/spec/workers/move_worker_spec.rb @@ -67,39 +67,31 @@ describe MoveWorker do end shared_examples 'block and mute handling' do - it 'makes blocks carry over and add a note' do + it 'makes blocks and mutes carry over and adds a note' do subject.perform(source_account.id, target_account.id) + expect(block_service).to have_received(:call).with(blocking_account, target_account) expect(AccountNote.find_by(account: blocking_account, target_account: target_account).comment).to include(source_account.acct) - end - it 'makes mutes carry over and add a note' do - subject.perform(source_account.id, target_account.id) expect(muting_account.muting?(target_account)).to be true expect(AccountNote.find_by(account: muting_account, target_account: target_account).comment).to include(source_account.acct) end end shared_examples 'followers count handling' do - it 'updates the source account followers count' do + it 'updates the source and target account followers counts' do subject.perform(source_account.id, target_account.id) - expect(source_account.reload.followers_count).to eq(source_account.passive_relationships.count) - end - it 'updates the target account followers count' do - subject.perform(source_account.id, target_account.id) + expect(source_account.reload.followers_count).to eq(source_account.passive_relationships.count) expect(target_account.reload.followers_count).to eq(target_account.passive_relationships.count) end end shared_examples 'lists handling' do - it 'puts the new account on the list' do + it 'puts the new account on the list and makes valid lists', sidekiq: :inline do subject.perform(source_account.id, target_account.id) - expect(list.accounts.include?(target_account)).to be true - end - it 'does not create invalid list memberships' do - subject.perform(source_account.id, target_account.id) + expect(list.accounts.include?(target_account)).to be true expect(ListAccount.all).to all be_valid end end From 71cfdd78650b85251b0253acd11e55227f72f506 Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 13 Oct 2023 16:10:43 +0200 Subject: [PATCH 44/58] Fix duplicate tests (#27395) --- .../api/v1/reports_controller_spec.rb | 63 ------------------- spec/requests/api/v1/reports_spec.rb | 45 +++++-------- 2 files changed, 14 insertions(+), 94 deletions(-) delete mode 100644 spec/controllers/api/v1/reports_controller_spec.rb diff --git a/spec/controllers/api/v1/reports_controller_spec.rb b/spec/controllers/api/v1/reports_controller_spec.rb deleted file mode 100644 index 624ceb213e..0000000000 --- a/spec/controllers/api/v1/reports_controller_spec.rb +++ /dev/null @@ -1,63 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe Api::V1::ReportsController do - render_views - - let(:user) { Fabricate(:user) } - let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) } - - before do - allow(controller).to receive(:doorkeeper_token) { token } - end - - describe 'POST #create' do - let!(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } - - let(:scopes) { 'write:reports' } - let(:status) { Fabricate(:status) } - let(:target_account) { status.account } - let(:category) { nil } - let(:forward) { nil } - let(:rule_ids) { nil } - - before do - post :create, params: { status_ids: [status.id], account_id: target_account.id, comment: 'reasons', category: category, rule_ids: rule_ids, forward: forward } - end - - it 'creates a report', :aggregate_failures do - expect(response).to have_http_status(200) - expect(target_account.targeted_reports).to_not be_empty - expect(target_account.targeted_reports.first.comment).to eq 'reasons' - expect(ActionMailer::Base.deliveries.first.to).to eq([admin.email]) - end - - context 'when a status does not belong to the reported account' do - let(:target_account) { Fabricate(:account) } - - it 'returns http not found' do - expect(response).to have_http_status(404) - end - end - - context 'when a category is chosen' do - let(:category) { 'spam' } - - it 'saves category' do - expect(target_account.targeted_reports.first.spam?).to be true - end - end - - context 'when violated rules are chosen' do - let(:rule) { Fabricate(:rule) } - let(:category) { 'violation' } - let(:rule_ids) { [rule.id] } - - it 'saves category and rule_ids' do - expect(target_account.targeted_reports.first.violation?).to be true - expect(target_account.targeted_reports.first.rule_ids).to contain_exactly(rule.id) - end - end - end -end diff --git a/spec/requests/api/v1/reports_spec.rb b/spec/requests/api/v1/reports_spec.rb index ce74f17c48..ba3d2b3060 100644 --- a/spec/requests/api/v1/reports_spec.rb +++ b/spec/requests/api/v1/reports_spec.rb @@ -33,34 +33,22 @@ RSpec.describe 'Reports' do it_behaves_like 'forbidden for wrong scope', 'read read:reports' - it 'returns http success' do - subject - - expect(response).to have_http_status(200) - end - - it 'returns the created report' do - subject - - expect(body_as_json).to match( - a_hash_including( - status_ids: [status.id.to_s], - category: category, - comment: 'reasons' - ) - ) - end - - it 'creates a report' do - subject - - expect(target_account.targeted_reports).to_not be_empty - end - - it 'sends e-mails to admins' do + it 'creates a report', :aggregate_failures do perform_enqueued_jobs do subject + expect(response).to have_http_status(200) + expect(body_as_json).to match( + a_hash_including( + status_ids: [status.id.to_s], + category: category, + comment: 'reasons' + ) + ) + + expect(target_account.targeted_reports).to_not be_empty + expect(target_account.targeted_reports.first.comment).to eq 'reasons' + expect(ActionMailer::Base.deliveries.first.to).to eq([admin.email]) end end @@ -90,15 +78,10 @@ RSpec.describe 'Reports' do let(:category) { 'violation' } let(:rule_ids) { [rule.id] } - it 'saves category' do + it 'saves category and rule_ids' do subject expect(target_account.targeted_reports.first.violation?).to be true - end - - it 'saves rule_ids' do - subject - expect(target_account.targeted_reports.first.rule_ids).to contain_exactly(rule.id) end end From 1b195ce115bd1572eb883722c55c1db90eb3182b Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 13 Oct 2023 10:14:23 -0400 Subject: [PATCH 45/58] Speed-up on `Rack::Attack` spec (#25542) --- spec/config/initializers/rack_attack_spec.rb | 48 ++++++++++++++++---- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/spec/config/initializers/rack_attack_spec.rb b/spec/config/initializers/rack_attack_spec.rb index 7cd4ac76bb..c9ce9e27d0 100644 --- a/spec/config/initializers/rack_attack_spec.rb +++ b/spec/config/initializers/rack_attack_spec.rb @@ -16,37 +16,63 @@ describe Rack::Attack, type: :request do # https://github.com/rack/rack-attack/blob/v6.6.1/lib/rack/attack/cache.rb#L64-L66 # So we want to minimize `Time.now.to_i % period` - travel_to Time.zone.at((Time.now.to_i / period.seconds).to_i * period.seconds) + travel_to Time.zone.at(counter_prefix * period.seconds) end context 'when the number of requests is lower than the limit' do + before do + below_limit.times { increment_counter } + end + it 'does not change the request status' do - limit.times do - request.call - expect(response).to_not have_http_status(429) - end + expect { request.call }.to change { throttle_count }.by(1) + + expect(response).to_not have_http_status(429) end end context 'when the number of requests is higher than the limit' do + before do + above_limit.times { increment_counter } + end + it 'returns http too many requests after limit and returns to normal status after period' do - (limit * 2).times do |i| - request.call - expect(response).to have_http_status(429) if i > limit - end + expect { request.call }.to change { throttle_count }.by(1) + expect(response).to have_http_status(429) travel period - request.call + expect { request.call }.to change { throttle_count }.by(1) expect(response).to_not have_http_status(429) end end + + def below_limit + limit - 1 + end + + def above_limit + limit * 2 + end + + def throttle_count + described_class.cache.read("#{counter_prefix}:#{throttle}:#{remote_ip}") || 0 + end + + def counter_prefix + (Time.now.to_i / period.seconds).to_i + end + + def increment_counter + described_class.cache.count("#{throttle}:#{remote_ip}", period) + end end let(:remote_ip) { '1.2.3.5' } describe 'throttle excessive sign-up requests by IP address' do context 'when accessed through the website' do + let(:throttle) { 'throttle_sign_up_attempts/ip' } let(:limit) { 25 } let(:period) { 5.minutes } let(:request) { -> { post path, headers: { 'REMOTE_ADDR' => remote_ip } } } @@ -65,6 +91,7 @@ describe Rack::Attack, type: :request do end context 'when accessed through the API' do + let(:throttle) { 'throttle_api_sign_up' } let(:limit) { 5 } let(:period) { 30.minutes } let(:request) { -> { post path, headers: { 'REMOTE_ADDR' => remote_ip } } } @@ -87,6 +114,7 @@ describe Rack::Attack, type: :request do end describe 'throttle excessive sign-in requests by IP address' do + let(:throttle) { 'throttle_login_attempts/ip' } let(:limit) { 25 } let(:period) { 5.minutes } let(:request) { -> { post path, headers: { 'REMOTE_ADDR' => remote_ip } } } From 82beeb2f7ec0eb07a1bdc688d827ef1db5a3427d Mon Sep 17 00:00:00 2001 From: Daniel M Brasil Date: Fri, 13 Oct 2023 11:23:16 -0300 Subject: [PATCH 46/58] Migrate to request specs in `/api/v1/admin/trends/links` (#25739) --- .../v1/admin/trends/links_controller_spec.rb | 52 ------- .../api/v1/admin/trends/links/links_spec.rb | 129 ++++++++++++++++++ 2 files changed, 129 insertions(+), 52 deletions(-) delete mode 100644 spec/controllers/api/v1/admin/trends/links_controller_spec.rb create mode 100644 spec/requests/api/v1/admin/trends/links/links_spec.rb diff --git a/spec/controllers/api/v1/admin/trends/links_controller_spec.rb b/spec/controllers/api/v1/admin/trends/links_controller_spec.rb deleted file mode 100644 index d9aa06824d..0000000000 --- a/spec/controllers/api/v1/admin/trends/links_controller_spec.rb +++ /dev/null @@ -1,52 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -describe Api::V1::Admin::Trends::LinksController do - render_views - - let(:role) { UserRole.find_by(name: 'Admin') } - let(:user) { Fabricate(:user, role: role) } - let(:scopes) { 'admin:read admin:write' } - let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) } - let(:account) { Fabricate(:account) } - let(:preview_card) { Fabricate(:preview_card) } - - before do - allow(controller).to receive(:doorkeeper_token) { token } - end - - describe 'GET #index' do - it 'returns http success' do - get :index, params: { account_id: account.id, limit: 2 } - - expect(response).to have_http_status(200) - end - end - - describe 'POST #approve' do - before do - post :approve, params: { id: preview_card.id } - end - - it_behaves_like 'forbidden for wrong scope', 'write:statuses' - it_behaves_like 'forbidden for wrong role', '' - - it 'returns http success' do - expect(response).to have_http_status(200) - end - end - - describe 'POST #reject' do - before do - post :reject, params: { id: preview_card.id } - end - - it_behaves_like 'forbidden for wrong scope', 'write:statuses' - it_behaves_like 'forbidden for wrong role', '' - - it 'returns http success' do - expect(response).to have_http_status(200) - end - end -end diff --git a/spec/requests/api/v1/admin/trends/links/links_spec.rb b/spec/requests/api/v1/admin/trends/links/links_spec.rb new file mode 100644 index 0000000000..05020b0fd0 --- /dev/null +++ b/spec/requests/api/v1/admin/trends/links/links_spec.rb @@ -0,0 +1,129 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe 'Links' do + let(:role) { UserRole.find_by(name: 'Admin') } + let(:user) { Fabricate(:user, role: role) } + let(:scopes) { 'admin:read admin:write' } + let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) } + let(:headers) { { 'Authorization' => "Bearer #{token.token}" } } + + describe 'GET /api/v1/admin/trends/links' do + subject do + get '/api/v1/admin/trends/links', headers: headers + end + + it 'returns http success' do + subject + + expect(response).to have_http_status(200) + end + end + + describe 'POST /api/v1/admin/trends/links/:id/approve' do + subject do + post "/api/v1/admin/trends/links/#{preview_card.id}/approve", headers: headers + end + + let(:preview_card) { Fabricate(:preview_card, trendable: false) } + + it_behaves_like 'forbidden for wrong scope', 'read write' + it_behaves_like 'forbidden for wrong role', '' + + it 'returns http success' do + subject + + expect(response).to have_http_status(200) + end + + it 'sets the link as trendable' do + expect { subject }.to change { preview_card.reload.trendable }.from(false).to(true) + end + + it 'returns the link data' do + subject + + expect(body_as_json).to match( + a_hash_including( + url: preview_card.url, + title: preview_card.title, + description: preview_card.description, + type: 'link', + requires_review: false + ) + ) + end + + context 'when the link does not exist' do + it 'returns http not found' do + post '/api/v1/admin/trends/links/-1/approve', headers: headers + + expect(response).to have_http_status(404) + end + end + + context 'without an authorization header' do + let(:headers) { {} } + + it 'returns http forbidden' do + subject + + expect(response).to have_http_status(403) + end + end + end + + describe 'POST /api/v1/admin/trends/links/:id/reject' do + subject do + post "/api/v1/admin/trends/links/#{preview_card.id}/reject", headers: headers + end + + let(:preview_card) { Fabricate(:preview_card, trendable: false) } + + it_behaves_like 'forbidden for wrong scope', 'read write' + it_behaves_like 'forbidden for wrong role', '' + + it 'returns http success' do + subject + + expect(response).to have_http_status(200) + end + + it 'does not set the link as trendable' do + expect { subject }.to_not(change { preview_card.reload.trendable }) + end + + it 'returns the link data' do + subject + + expect(body_as_json).to match( + a_hash_including( + url: preview_card.url, + title: preview_card.title, + description: preview_card.description, + type: 'link', + requires_review: false + ) + ) + end + + context 'when the link does not exist' do + it 'returns http not found' do + post '/api/v1/admin/trends/links/-1/reject', headers: headers + + expect(response).to have_http_status(404) + end + end + + context 'without an authorization header' do + let(:headers) { {} } + + it 'returns http forbidden' do + subject + + expect(response).to have_http_status(403) + end + end + end +end From e0da64bb4e0ae84fb9380b6e2bff228c997eea62 Mon Sep 17 00:00:00 2001 From: Renaud Chaput Date: Fri, 13 Oct 2023 19:00:53 +0200 Subject: [PATCH 47/58] Fix empty ENV variables not using default nil value (#27400) --- config/initializers/chewy.rb | 6 +++--- config/initializers/devise.rb | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/config/initializers/chewy.rb b/config/initializers/chewy.rb index 66008a0009..076f383324 100644 --- a/config/initializers/chewy.rb +++ b/config/initializers/chewy.rb @@ -3,9 +3,9 @@ enabled = ENV['ES_ENABLED'] == 'true' host = ENV.fetch('ES_HOST') { 'localhost' } port = ENV.fetch('ES_PORT') { 9200 } -user = ENV.fetch('ES_USER') { nil } -password = ENV.fetch('ES_PASS') { nil } -fallback_prefix = ENV.fetch('REDIS_NAMESPACE') { nil } +user = ENV.fetch('ES_USER', nil).presence +password = ENV.fetch('ES_PASS', nil).presence +fallback_prefix = ENV.fetch('REDIS_NAMESPACE', nil).presence prefix = ENV.fetch('ES_PREFIX') { fallback_prefix } Chewy.settings = { diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 7bbaff71f0..41d0ee25b7 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -394,7 +394,7 @@ Devise.setup do |config| config.check_at_sign = true config.pam_default_suffix = ENV.fetch('PAM_EMAIL_DOMAIN') { ENV['LOCAL_DOMAIN'] } config.pam_default_service = ENV.fetch('PAM_DEFAULT_SERVICE') { 'rpam' } - config.pam_controlled_service = ENV.fetch('PAM_CONTROLLED_SERVICE') { nil } + config.pam_controlled_service = ENV.fetch('PAM_CONTROLLED_SERVICE', nil).presence end if ENV['LDAP_ENABLED'] == 'true' From f21c264b486ad51491eee55f50e8e48750a255ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Sat, 14 Oct 2023 07:56:46 +0900 Subject: [PATCH 48/58] =?UTF-8?q?Change:=20#52=20=E8=B3=BC=E8=AA=AD?= =?UTF-8?q?=E6=8B=92=E5=90=A6=E8=A8=AD=E5=AE=9A=E9=A0=85=E7=9B=AE=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0=E8=A8=AD=E5=AE=9A=E7=94=BB=E9=9D=A2=E3=81=AB?= =?UTF-8?q?=E7=A7=BB=E5=8B=95=20(#112)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/settings/privacy_controller.rb | 2 +- app/controllers/settings/privacy_extra_controller.rb | 2 +- app/views/settings/privacy/show.html.haml | 3 --- app/views/settings/privacy_extra/show.html.haml | 3 +++ 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/controllers/settings/privacy_controller.rb b/app/controllers/settings/privacy_controller.rb index e5c4e5a905..1102c89fad 100644 --- a/app/controllers/settings/privacy_controller.rb +++ b/app/controllers/settings/privacy_controller.rb @@ -18,7 +18,7 @@ class Settings::PrivacyController < Settings::BaseController private def account_params - params.require(:account).permit(:discoverable, :unlocked, :indexable, :show_collections, :dissubscribable, settings: UserSettings.keys) + params.require(:account).permit(:discoverable, :unlocked, :indexable, :show_collections, settings: UserSettings.keys) end def set_account diff --git a/app/controllers/settings/privacy_extra_controller.rb b/app/controllers/settings/privacy_extra_controller.rb index 54cedf2c4b..85364ec35d 100644 --- a/app/controllers/settings/privacy_extra_controller.rb +++ b/app/controllers/settings/privacy_extra_controller.rb @@ -18,7 +18,7 @@ class Settings::PrivacyExtraController < Settings::BaseController private def account_params - params.require(:account).permit(settings: UserSettings.keys) + params.require(:account).permit(:dissubscribable, settings: UserSettings.keys) end def set_account diff --git a/app/views/settings/privacy/show.html.haml b/app/views/settings/privacy/show.html.haml index 619429392e..9656ada005 100644 --- a/app/views/settings/privacy/show.html.haml +++ b/app/views/settings/privacy/show.html.haml @@ -24,9 +24,6 @@ .fields-group = ff.input :noai, wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_noai'), hint: I18n.t('simple_form.hints.defaults.setting_noai') - .fields-group - = f.input :dissubscribable, as: :boolean, wrapper: :with_label, kmyblue: true, hint: t('simple_form.hints.defaults.dissubscribable') - .fields-group = f.input :unlocked, as: :boolean, wrapper: :with_label diff --git a/app/views/settings/privacy_extra/show.html.haml b/app/views/settings/privacy_extra/show.html.haml index c688ad6373..5e102f6565 100644 --- a/app/views/settings/privacy_extra/show.html.haml +++ b/app/views/settings/privacy_extra/show.html.haml @@ -21,6 +21,9 @@ .fields-group = ff.input :link_preview, wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_link_preview'), hint: I18n.t('simple_form.hints.defaults.setting_link_preview') + .fields-group + = f.input :dissubscribable, as: :boolean, wrapper: :with_label, kmyblue: true, hint: t('simple_form.hints.defaults.dissubscribable') + .fields-group = ff.input :allow_quote, wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_allow_quote'), hint: false From f918a13c4846fd44905feccebd270c442fd4116b Mon Sep 17 00:00:00 2001 From: KMY Date: Sun, 15 Oct 2023 11:22:35 +0900 Subject: [PATCH 49/58] =?UTF-8?q?Fix:=20=E3=83=86=E3=82=B9=E3=83=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rest/admin/domain_block_serializer.rb | 2 +- .../api/v1/admin/domain_blocks_spec.rb | 35 +++++++++---------- spec/requests/api/v1/lists_spec.rb | 11 ------ 3 files changed, 18 insertions(+), 30 deletions(-) diff --git a/app/serializers/rest/admin/domain_block_serializer.rb b/app/serializers/rest/admin/domain_block_serializer.rb index e7cdc40ad1..e4f9e22d43 100644 --- a/app/serializers/rest/admin/domain_block_serializer.rb +++ b/app/serializers/rest/admin/domain_block_serializer.rb @@ -5,7 +5,7 @@ class REST::Admin::DomainBlockSerializer < ActiveModel::Serializer :reject_media, :reject_favourite, :reject_reply, :reject_reports, :reject_send_not_public_searchability, :reject_reply_exclude_followers, :reject_send_public_unlisted, :reject_send_dissubscribable, :reject_send_media, :reject_send_sensitive, - :reject_hashtag, :reject_straight_follow, :reject_new_follow, :detect_invalid_subscription, + :reject_hashtag, :reject_straight_follow, :reject_new_follow, :reject_friend, :detect_invalid_subscription, :private_comment, :public_comment, :obfuscate def id diff --git a/spec/requests/api/v1/admin/domain_blocks_spec.rb b/spec/requests/api/v1/admin/domain_blocks_spec.rb index 87f8bbf770..1041fdb713 100644 --- a/spec/requests/api/v1/admin/domain_blocks_spec.rb +++ b/spec/requests/api/v1/admin/domain_blocks_spec.rb @@ -45,22 +45,6 @@ RSpec.describe 'Domain Blocks' do ] end let(:expected_responde) do - domain_blocks.map do |domain_block| - { - id: domain_block.id.to_s, - domain: domain_block.domain, - created_at: domain_block.created_at.strftime('%Y-%m-%dT%H:%M:%S.%LZ'), - severity: domain_block.severity.to_s, - reject_media: domain_block.reject_media, - reject_reports: domain_block.reject_reports, - private_comment: domain_block.private_comment, - public_comment: domain_block.public_comment, - obfuscate: domain_block.obfuscate, - } - end - end - - let(:expected_responde_with_kb_custom) do domain_blocks.map do |domain_block| { id: domain_block.id.to_s, @@ -84,6 +68,7 @@ RSpec.describe 'Domain Blocks' do reject_send_public_unlisted: domain_block.reject_send_public_unlisted, reject_send_sensitive: domain_block.reject_send_sensitive, reject_straight_follow: domain_block.reject_straight_follow, + reject_friend: domain_block.reject_friend, } end end @@ -91,7 +76,7 @@ RSpec.describe 'Domain Blocks' do it 'returns the expected domain blocks' do subject - expect(body_as_json).to match_array(expected_responde_with_kb_custom) + expect(body_as_json).to match_array(expected_responde) end context 'with limit param' do @@ -136,6 +121,7 @@ RSpec.describe 'Domain Blocks' do reject_send_public_unlisted: domain_block.reject_send_public_unlisted, reject_send_sensitive: domain_block.reject_send_sensitive, reject_straight_follow: domain_block.reject_straight_follow, + reject_friend: domain_block.reject_friend, } end @@ -143,7 +129,7 @@ RSpec.describe 'Domain Blocks' do it_behaves_like 'forbidden for wrong role', '' it_behaves_like 'forbidden for wrong role', 'Moderator' - it 'returns the expected domain block content', :aggregate_failures do + it 'returns the expected domain block content', :aggregate_failures do # rubocop:disable RSpec/ExampleLength subject expect(response).to have_http_status(200) @@ -158,6 +144,19 @@ RSpec.describe 'Domain Blocks' do private_comment: domain_block.private_comment, public_comment: domain_block.public_comment, obfuscate: domain_block.obfuscate, + reject_favourite: domain_block.reject_favourite, + reject_hashtag: domain_block.reject_hashtag, + detect_invalid_subscription: domain_block.detect_invalid_subscription, + reject_new_follow: domain_block.reject_new_follow, + reject_reply: domain_block.reject_reply, + reject_reply_exclude_followers: domain_block.reject_reply_exclude_followers, + reject_send_dissubscribable: domain_block.reject_send_dissubscribable, + reject_send_media: domain_block.reject_send_media, + reject_send_not_public_searchability: domain_block.reject_send_not_public_searchability, + reject_send_public_unlisted: domain_block.reject_send_public_unlisted, + reject_send_sensitive: domain_block.reject_send_sensitive, + reject_straight_follow: domain_block.reject_straight_follow, + reject_friend: domain_block.reject_friend, } ) end diff --git a/spec/requests/api/v1/lists_spec.rb b/spec/requests/api/v1/lists_spec.rb index 0d3d93ae3e..a2466060c0 100644 --- a/spec/requests/api/v1/lists_spec.rb +++ b/spec/requests/api/v1/lists_spec.rb @@ -23,17 +23,6 @@ RSpec.describe 'Lists' do end let(:expected_response) do - lists.map do |list| - { - id: list.id.to_s, - title: list.title, - replies_policy: list.replies_policy, - exclusive: list.exclusive, - } - end - end - - let(:expected_response_with_antennas) do lists.map do |list| { id: list.id.to_s, From b896ab294b44652e5b75ea0234797fe79b32921d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Fri, 13 Oct 2023 18:15:47 +0900 Subject: [PATCH 50/58] Fix when unfollow a tag, my post also disappears from the home timeline (#27391) --- app/lib/feed_manager.rb | 1 + spec/lib/feed_manager_spec.rb | 38 +++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb index 7d530906c6..ff2ad7a01d 100644 --- a/app/lib/feed_manager.rb +++ b/app/lib/feed_manager.rb @@ -207,6 +207,7 @@ class FeedManager # also tagged with another followed hashtag or from a followed user scope = from_tag.statuses .where(id: timeline_status_ids) + .where.not(account: into_account) .where.not(account: into_account.following) .tagged_with_none(TagFollow.where(account: into_account).pluck(:tag_id)) diff --git a/spec/lib/feed_manager_spec.rb b/spec/lib/feed_manager_spec.rb index d2e5da6b92..f5a3367b2b 100644 --- a/spec/lib/feed_manager_spec.rb +++ b/spec/lib/feed_manager_spec.rb @@ -562,6 +562,44 @@ RSpec.describe FeedManager do end end + describe '#unmerge_tag_from_home' do + let(:receiver) { Fabricate(:account) } + let(:tag) { Fabricate(:tag) } + + it 'leaves a tagged status' do + status = Fabricate(:status) + status.tags << tag + described_class.instance.push_to_home(receiver, status) + + described_class.instance.unmerge_tag_from_home(tag, receiver) + + expect(redis.zrange("feed:home:#{receiver.id}", 0, -1)).to_not include(status.id.to_s) + end + + it 'remains a tagged status written by receiver\'s followee' do + followee = Fabricate(:account) + receiver.follow!(followee) + + status = Fabricate(:status, account: followee) + status.tags << tag + described_class.instance.push_to_home(receiver, status) + + described_class.instance.unmerge_tag_from_home(tag, receiver) + + expect(redis.zrange("feed:home:#{receiver.id}", 0, -1)).to include(status.id.to_s) + end + + it 'remains a tagged status written by receiver' do + status = Fabricate(:status, account: receiver) + status.tags << tag + described_class.instance.push_to_home(receiver, status) + + described_class.instance.unmerge_tag_from_home(tag, receiver) + + expect(redis.zrange("feed:home:#{receiver.id}", 0, -1)).to include(status.id.to_s) + end + end + describe '#clear_from_home' do let(:account) { Fabricate(:account) } let(:followed_account) { Fabricate(:account) } From c2f0960e3f898849be528bc9f7c6aec27fa5adfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Sat, 14 Oct 2023 07:56:46 +0900 Subject: [PATCH 51/58] =?UTF-8?q?Change:=20#52=20=E8=B3=BC=E8=AA=AD?= =?UTF-8?q?=E6=8B=92=E5=90=A6=E8=A8=AD=E5=AE=9A=E9=A0=85=E7=9B=AE=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0=E8=A8=AD=E5=AE=9A=E7=94=BB=E9=9D=A2=E3=81=AB?= =?UTF-8?q?=E7=A7=BB=E5=8B=95=20(#112)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/settings/privacy_controller.rb | 2 +- app/controllers/settings/privacy_extra_controller.rb | 2 +- app/views/settings/privacy/show.html.haml | 3 --- app/views/settings/privacy_extra/show.html.haml | 6 ++++++ 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app/controllers/settings/privacy_controller.rb b/app/controllers/settings/privacy_controller.rb index e5c4e5a905..1102c89fad 100644 --- a/app/controllers/settings/privacy_controller.rb +++ b/app/controllers/settings/privacy_controller.rb @@ -18,7 +18,7 @@ class Settings::PrivacyController < Settings::BaseController private def account_params - params.require(:account).permit(:discoverable, :unlocked, :indexable, :show_collections, :dissubscribable, settings: UserSettings.keys) + params.require(:account).permit(:discoverable, :unlocked, :indexable, :show_collections, settings: UserSettings.keys) end def set_account diff --git a/app/controllers/settings/privacy_extra_controller.rb b/app/controllers/settings/privacy_extra_controller.rb index 54cedf2c4b..85364ec35d 100644 --- a/app/controllers/settings/privacy_extra_controller.rb +++ b/app/controllers/settings/privacy_extra_controller.rb @@ -18,7 +18,7 @@ class Settings::PrivacyExtraController < Settings::BaseController private def account_params - params.require(:account).permit(settings: UserSettings.keys) + params.require(:account).permit(:dissubscribable, settings: UserSettings.keys) end def set_account diff --git a/app/views/settings/privacy/show.html.haml b/app/views/settings/privacy/show.html.haml index 619429392e..9656ada005 100644 --- a/app/views/settings/privacy/show.html.haml +++ b/app/views/settings/privacy/show.html.haml @@ -24,9 +24,6 @@ .fields-group = ff.input :noai, wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_noai'), hint: I18n.t('simple_form.hints.defaults.setting_noai') - .fields-group - = f.input :dissubscribable, as: :boolean, wrapper: :with_label, kmyblue: true, hint: t('simple_form.hints.defaults.dissubscribable') - .fields-group = f.input :unlocked, as: :boolean, wrapper: :with_label diff --git a/app/views/settings/privacy_extra/show.html.haml b/app/views/settings/privacy_extra/show.html.haml index c9ccd03013..dd07719bcb 100644 --- a/app/views/settings/privacy_extra/show.html.haml +++ b/app/views/settings/privacy_extra/show.html.haml @@ -21,6 +21,12 @@ .fields-group = ff.input :link_preview, wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_link_preview'), hint: I18n.t('simple_form.hints.defaults.setting_link_preview') + .fields-group + = f.input :dissubscribable, as: :boolean, wrapper: :with_label, kmyblue: true, hint: t('simple_form.hints.defaults.dissubscribable') + + .fields-group + = ff.input :allow_quote, wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_allow_quote'), hint: false + %h4= t 'privacy_extra.stop_deliver' %p.lead= t('privacy_extra.stop_deliver_hint_html') From dd46f62ba64210c56f323d9e58dd974e046dae76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Sun, 15 Oct 2023 11:36:33 +0900 Subject: [PATCH 52/58] Merge pull request from GHSA-jw42-6m49-65x8 --- app/services/emoji_react_service.rb | 3 + spec/services/emoji_react_service_spec.rb | 139 ++++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 spec/services/emoji_react_service_spec.rb diff --git a/app/services/emoji_react_service.rb b/app/services/emoji_react_service.rb index 9a166a3413..768fc7ac5c 100644 --- a/app/services/emoji_react_service.rb +++ b/app/services/emoji_react_service.rb @@ -22,7 +22,10 @@ class EmojiReactService < BaseService raise Mastodon::ValidationError, I18n.t('reactions.errors.duplication') unless emoji_reaction.nil? shortcode, domain = name.split('@') + domain = nil if TagManager.instance.local_domain?(domain) custom_emoji = CustomEmoji.find_by(shortcode: shortcode, domain: domain) + return if domain.present? && !EmojiReaction.exists?(status: status, custom_emoji: custom_emoji) + emoji_reaction = EmojiReaction.create!(account: account, status: status, name: shortcode, custom_emoji: custom_emoji) status.touch # rubocop:disable Rails/SkipsModelValidations diff --git a/spec/services/emoji_react_service_spec.rb b/spec/services/emoji_react_service_spec.rb new file mode 100644 index 0000000000..62d81d57c5 --- /dev/null +++ b/spec/services/emoji_react_service_spec.rb @@ -0,0 +1,139 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe EmojiReactService, type: :service do + subject do + described_class.new.call(sender, status, name) + EmojiReaction.where(status: status, account: sender) + end + + let(:name) { '😀' } + let(:sender) { Fabricate(:user).account } + let(:author) { Fabricate(:user).account } + let(:status) { Fabricate(:status, account: author) } + + it 'with a simple case' do + expect(subject.count).to eq 1 + expect(subject.first.name).to eq '😀' + expect(subject.first.custom_emoji_id).to be_nil + end + + context 'with name duplication on same account' do + before { Fabricate(:emoji_reaction, status: status, name: '😀') } + + it 'react with emoji' do + expect(subject.count).to eq 1 + expect(subject.first.name).to eq '😀' + end + end + + context 'when multiple reactions by same account' do + let(:name) { '😂' } + + before { Fabricate(:emoji_reaction, account: sender, status: status, name: '😀') } + + it 'react with emoji' do + expect(subject.count).to eq 2 + expect(subject.pluck(:name)).to contain_exactly('😀', '😂') + end + end + + context 'when already reacted by other account' do + let(:name) { '😂' } + + before { Fabricate(:emoji_reaction, status: status, name: '😀') } + + it 'react with emoji' do + expect(subject.count).to eq 1 + expect(subject.pluck(:name)).to contain_exactly('😂') + end + end + + context 'when already reacted same emoji by other account', :tag do + before { Fabricate(:emoji_reaction, status: status, name: '😀') } + + it 'react with emoji' do + expect(subject.count).to eq 1 + expect(subject.first.name).to eq '😀' + end + end + + context 'when over limit' do + let(:name) { '🚗' } + + before do + Fabricate(:emoji_reaction, status: status, account: sender, name: '😀') + Fabricate(:emoji_reaction, status: status, account: sender, name: '😎') + Fabricate(:emoji_reaction, status: status, account: sender, name: '🐟') + end + + it 'react with emoji' do + expect { subject.count }.to raise_error Mastodon::ValidationError + + reactions = EmojiReaction.where(status: status, account: sender).pluck(:name) + expect(reactions.size).to eq 3 + expect(reactions).to contain_exactly('😀', '😎', '🐟') + end + end + + context 'with custom emoji of local' do + let(:name) { 'ohagi' } + let!(:custom_emoji) { Fabricate(:custom_emoji, shortcode: 'ohagi') } + + it 'react with emoji' do + expect(subject.count).to eq 1 + expect(subject.first.name).to eq 'ohagi' + expect(subject.first.custom_emoji.id).to eq custom_emoji.id + end + end + + context 'with custom emoji but not existing' do + let(:name) { 'ohagi' } + + it 'react with emoji' do + expect { subject.count }.to raise_error ActiveRecord::RecordInvalid + expect(EmojiReaction.exists?(status: status, account: sender, name: 'ohagi')).to be false + end + end + + context 'with custom emoji of remote' do + let(:name) { 'ohagi@foo.bar' } + let!(:custom_emoji) { Fabricate(:custom_emoji, shortcode: 'ohagi', domain: 'foo.bar') } + + before { Fabricate(:emoji_reaction, status: status, name: 'ohagi', custom_emoji: custom_emoji) } + + it 'react with emoji' do + expect(subject.count).to eq 1 + expect(subject.first.name).to eq 'ohagi' + expect(subject.first.custom_emoji.id).to eq custom_emoji.id + end + end + + context 'with custom emoji of remote without existing one' do + let(:name) { 'ohagi@foo.bar' } + + before { Fabricate(:custom_emoji, shortcode: 'ohagi', domain: 'foo.bar') } + + it 'react with emoji' do + expect(subject.count).to eq 0 + end + end + + context 'with custom emoji of remote but local has same name emoji' do + let(:name) { 'ohagi@foo.bar' } + let!(:custom_emoji) { Fabricate(:custom_emoji, shortcode: 'ohagi', domain: 'foo.bar') } + + before do + Fabricate(:custom_emoji, shortcode: 'ohagi', domain: nil) + Fabricate(:emoji_reaction, status: status, name: 'ohagi', custom_emoji: custom_emoji) + end + + it 'react with emoji' do + expect(subject.count).to eq 1 + expect(subject.first.name).to eq 'ohagi' + expect(subject.first.custom_emoji.id).to eq custom_emoji.id + expect(subject.first.custom_emoji.domain).to eq 'foo.bar' + end + end +end From 5ac46b4dc69367fc9644ab198aa9062ff0426c6e Mon Sep 17 00:00:00 2001 From: KMY Date: Sun, 15 Oct 2023 11:39:52 +0900 Subject: [PATCH 53/58] Bump version to 5.5 LTS --- lib/mastodon/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index 3e443ad6c2..63ddbb0a5b 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -9,7 +9,7 @@ module Mastodon end def kmyblue_minor - 4 + 5 end def kmyblue_flag From e7e70b21d2ebefdb7d9ee9e599cc9ad5f751d327 Mon Sep 17 00:00:00 2001 From: KMY Date: Sun, 15 Oct 2023 12:21:39 +0900 Subject: [PATCH 54/58] =?UTF-8?q?Fix:=20=E3=82=B9=E3=82=BF=E3=83=B3?= =?UTF-8?q?=E3=83=97=E3=81=AE=E3=83=86=E3=82=B9=E3=83=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/emoji_reaction.rb | 8 ++++++++ spec/fabricators/emoji_reaction_fabricator.rb | 7 +++++++ spec/services/emoji_react_service_spec.rb | 6 +++--- 3 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 spec/fabricators/emoji_reaction_fabricator.rb diff --git a/app/models/emoji_reaction.rb b/app/models/emoji_reaction.rb index ce0a7dfb2e..f97679347c 100644 --- a/app/models/emoji_reaction.rb +++ b/app/models/emoji_reaction.rb @@ -43,6 +43,14 @@ class EmojiReaction < ApplicationRecord custom_emoji? && !custom_emoji.local? end + def sign? + true + end + + def object_type + :emoji_reaction + end + private def refresh_cache diff --git a/spec/fabricators/emoji_reaction_fabricator.rb b/spec/fabricators/emoji_reaction_fabricator.rb new file mode 100644 index 0000000000..2605a9f232 --- /dev/null +++ b/spec/fabricators/emoji_reaction_fabricator.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +Fabricator(:emoji_reaction) do + account { Fabricate.build(:account) } + status { Fabricate.build(:status) } + name '😀' +end diff --git a/spec/services/emoji_react_service_spec.rb b/spec/services/emoji_react_service_spec.rb index 62d81d57c5..629a7818d4 100644 --- a/spec/services/emoji_react_service_spec.rb +++ b/spec/services/emoji_react_service_spec.rb @@ -99,7 +99,7 @@ RSpec.describe EmojiReactService, type: :service do context 'with custom emoji of remote' do let(:name) { 'ohagi@foo.bar' } - let!(:custom_emoji) { Fabricate(:custom_emoji, shortcode: 'ohagi', domain: 'foo.bar') } + let!(:custom_emoji) { Fabricate(:custom_emoji, shortcode: 'ohagi', domain: 'foo.bar', uri: 'https://foo.bar/emoji/ohagi') } before { Fabricate(:emoji_reaction, status: status, name: 'ohagi', custom_emoji: custom_emoji) } @@ -113,7 +113,7 @@ RSpec.describe EmojiReactService, type: :service do context 'with custom emoji of remote without existing one' do let(:name) { 'ohagi@foo.bar' } - before { Fabricate(:custom_emoji, shortcode: 'ohagi', domain: 'foo.bar') } + before { Fabricate(:custom_emoji, shortcode: 'ohagi', domain: 'foo.bar', uri: 'https://foo.bar/emoji/ohagi') } it 'react with emoji' do expect(subject.count).to eq 0 @@ -122,7 +122,7 @@ RSpec.describe EmojiReactService, type: :service do context 'with custom emoji of remote but local has same name emoji' do let(:name) { 'ohagi@foo.bar' } - let!(:custom_emoji) { Fabricate(:custom_emoji, shortcode: 'ohagi', domain: 'foo.bar') } + let!(:custom_emoji) { Fabricate(:custom_emoji, shortcode: 'ohagi', domain: 'foo.bar', uri: 'https://foo.bar/emoji/ohagi') } before do Fabricate(:custom_emoji, shortcode: 'ohagi', domain: nil) From d0f0dd723c1c6cf91dab410c5ecbab2ac2fac620 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Sun, 15 Oct 2023 14:17:57 +0900 Subject: [PATCH 55/58] =?UTF-8?q?Change:=20#68=20=E9=99=90=E5=AE=9A?= =?UTF-8?q?=E6=8A=95=E7=A8=BF=E3=81=AE=E6=A4=9C=E7=B4=A2=E8=A8=B1=E5=8F=AF?= =?UTF-8?q?=E3=82=92=E5=8F=8D=E5=BF=9C=E8=80=85=E3=81=AB=E8=A8=AD=E5=AE=9A?= =?UTF-8?q?=E5=8F=AF=E8=83=BD=E3=81=AB=20(#120)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/status.rb | 6 ++---- spec/services/post_status_service_spec.rb | 11 +++++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/app/models/status.rb b/app/models/status.rb index 4b718cdc92..95d4f2b759 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -631,12 +631,10 @@ class Status < ApplicationRecord self.searchability = if %w(public public_unlisted login unlisted).include?(visibility) searchability - elsif visibility == 'limited' - :limited + elsif visibility == 'limited' || visibility == 'direct' + searchability == 'limited' ? :limited : :direct elsif visibility == 'private' searchability == 'public' || searchability == 'public_unlisted' ? :private : searchability - elsif visibility == 'direct' - searchability == 'limited' ? :limited : :direct else :direct end diff --git a/spec/services/post_status_service_spec.rb b/spec/services/post_status_service_spec.rb index 529ab09969..f63829f234 100644 --- a/spec/services/post_status_service_spec.rb +++ b/spec/services/post_status_service_spec.rb @@ -209,6 +209,17 @@ RSpec.describe PostStatusService, type: :service do expect(status.mentioned_accounts.first.id).to eq mutual_account.id end + it 'limited visibility and direct searchability' do + account = Fabricate(:account) + text = 'This is an English text.' + + status = subject.call(account, text: text, visibility: 'mutual', searchability: 'public') + + expect(status.visibility).to eq 'limited' + expect(status.limited_scope).to eq 'personal' + expect(status.searchability).to eq 'direct' + end + it 'personal visibility with mutual' do account = Fabricate(:account) text = 'This is an English text.' From 86a8b260e4d36ec0b03d7e53d0d94a996f8b7375 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Mon, 16 Oct 2023 13:09:56 +0900 Subject: [PATCH 56/58] =?UTF-8?q?Change:=20=E3=83=96=E3=83=83=E3=82=AF?= =?UTF-8?q?=E3=83=9E=E3=83=BC=E3=82=AF=E5=88=86=E9=A1=9E=E3=81=AE=E3=83=9A?= =?UTF-8?q?=E3=83=BC=E3=82=B8=E3=83=8D=E3=83=BC=E3=82=B7=E3=83=A7=E3=83=B3?= =?UTF-8?q?=20(#123)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Change: ブックマーク分類の投稿一覧のページネーション対応 * Fix: `console.dir`を削除(なぜ警告出ない) --- app/javascript/mastodon/actions/bookmark_categories.js | 7 ++++--- .../mastodon/features/bookmark_category_statuses/index.jsx | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/javascript/mastodon/actions/bookmark_categories.js b/app/javascript/mastodon/actions/bookmark_categories.js index b6f82b49c8..7d458b85ec 100644 --- a/app/javascript/mastodon/actions/bookmark_categories.js +++ b/app/javascript/mastodon/actions/bookmark_categories.js @@ -213,9 +213,10 @@ export const deleteBookmarkCategoryFail = (id, error) => ({ export const fetchBookmarkCategoryStatuses = bookmarkCategoryId => (dispatch, getState) => { dispatch(fetchBookmarkCategoryStatusesRequest(bookmarkCategoryId)); - api(getState).get(`/api/v1/bookmark_categories/${bookmarkCategoryId}/statuses`, { params: { limit: 0 } }).then(({ data }) => { - dispatch(importFetchedStatuses(data)); - dispatch(fetchBookmarkCategoryStatusesSuccess(bookmarkCategoryId, data)); + api(getState).get(`/api/v1/bookmark_categories/${bookmarkCategoryId}/statuses`).then((response) => { + const next = getLinks(response).refs.find(link => link.rel === 'next'); + dispatch(importFetchedStatuses(response.data)); + dispatch(fetchBookmarkCategoryStatusesSuccess(bookmarkCategoryId, response.data, next ? next.uri : null)); }).catch(err => dispatch(fetchBookmarkCategoryStatusesFail(bookmarkCategoryId, err))); }; diff --git a/app/javascript/mastodon/features/bookmark_category_statuses/index.jsx b/app/javascript/mastodon/features/bookmark_category_statuses/index.jsx index ed5fa17be7..5f5624fb46 100644 --- a/app/javascript/mastodon/features/bookmark_category_statuses/index.jsx +++ b/app/javascript/mastodon/features/bookmark_category_statuses/index.jsx @@ -113,7 +113,7 @@ class BookmarkCategoryStatuses extends ImmutablePureComponent { }; handleLoadMore = debounce(() => { - this.props.dispatch(expandBookmarkCategoryStatuses()); + this.props.dispatch(expandBookmarkCategoryStatuses(this.props.params.id)); }, 300, { leading: true }); render () { From 7d6684f0cdc8da0a43dfa83f5a94127dfa998906 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Mon, 16 Oct 2023 13:23:32 +0900 Subject: [PATCH 57/58] =?UTF-8?q?Fix:=20=E3=83=96=E3=83=83=E3=82=AF?= =?UTF-8?q?=E3=83=9E=E3=83=BC=E3=82=AF=E3=83=BB=E3=83=96=E3=83=83=E3=82=AF?= =?UTF-8?q?=E3=83=9E=E3=83=BC=E3=82=AF=E5=88=86=E9=A1=9E=E3=83=BB=E3=82=B5?= =?UTF-8?q?=E3=83=BC=E3=82=AF=E3=83=AB=E3=83=BB=E3=81=8A=E6=B0=97=E3=81=AB?= =?UTF-8?q?=E5=85=A5=E3=82=8A=E3=83=BB=E3=82=B9=E3=82=BF=E3=83=B3=E3=83=97?= =?UTF-8?q?=E3=81=AE=E6=8A=95=E7=A8=BF=E4=B8=80=E8=A6=A7=E3=81=A7=E3=80=81?= =?UTF-8?q?=E3=83=98=E3=83=83=E3=83=80=E3=82=92=E6=8A=BC=E3=81=97=E3=81=A6?= =?UTF-8?q?=E3=82=82=E3=82=B9=E3=82=AF=E3=83=AD=E3=83=BC=E3=83=AB=E3=81=A7?= =?UTF-8?q?=E3=81=8D=E3=81=AA=E3=81=84=E5=95=8F=E9=A1=8C=EF=BC=88=E6=9C=AC?= =?UTF-8?q?=E5=AE=B6=E7=94=B1=E6=9D=A5=EF=BC=89=20(#124)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mastodon/features/bookmark_category_statuses/index.jsx | 2 +- app/javascript/mastodon/features/bookmarked_statuses/index.jsx | 2 +- app/javascript/mastodon/features/circle_statuses/index.jsx | 2 +- .../mastodon/features/emoji_reacted_statuses/index.jsx | 2 +- app/javascript/mastodon/features/favourited_statuses/index.jsx | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/javascript/mastodon/features/bookmark_category_statuses/index.jsx b/app/javascript/mastodon/features/bookmark_category_statuses/index.jsx index 5f5624fb46..023091419d 100644 --- a/app/javascript/mastodon/features/bookmark_category_statuses/index.jsx +++ b/app/javascript/mastodon/features/bookmark_category_statuses/index.jsx @@ -13,12 +13,12 @@ import { debounce } from 'lodash'; import { deleteBookmarkCategory, expandBookmarkCategoryStatuses, fetchBookmarkCategory, fetchBookmarkCategoryStatuses , setupBookmarkCategoryEditor } from 'mastodon/actions/bookmark_categories'; import { addColumn, removeColumn, moveColumn } from 'mastodon/actions/columns'; import { openModal } from 'mastodon/actions/modal'; +import Column from 'mastodon/components/column'; import ColumnHeader from 'mastodon/components/column_header'; import { Icon } from 'mastodon/components/icon'; import { LoadingIndicator } from 'mastodon/components/loading_indicator'; import StatusList from 'mastodon/components/status_list'; import BundleColumnError from 'mastodon/features/ui/components/bundle_column_error'; -import Column from 'mastodon/features/ui/components/column'; import { getBookmarkCategoryStatusList } from 'mastodon/selectors'; import EditBookmarkCategoryForm from './components/edit_bookmark_category_form'; diff --git a/app/javascript/mastodon/features/bookmarked_statuses/index.jsx b/app/javascript/mastodon/features/bookmarked_statuses/index.jsx index b0c90a4302..d42ffab117 100644 --- a/app/javascript/mastodon/features/bookmarked_statuses/index.jsx +++ b/app/javascript/mastodon/features/bookmarked_statuses/index.jsx @@ -12,9 +12,9 @@ import { debounce } from 'lodash'; import { fetchBookmarkedStatuses, expandBookmarkedStatuses } from 'mastodon/actions/bookmarks'; import { addColumn, removeColumn, moveColumn } from 'mastodon/actions/columns'; +import Column from 'mastodon/components/column'; import ColumnHeader from 'mastodon/components/column_header'; import StatusList from 'mastodon/components/status_list'; -import Column from 'mastodon/features/ui/components/column'; import { getStatusList } from 'mastodon/selectors'; const messages = defineMessages({ diff --git a/app/javascript/mastodon/features/circle_statuses/index.jsx b/app/javascript/mastodon/features/circle_statuses/index.jsx index 2896455ab5..95f82521a8 100644 --- a/app/javascript/mastodon/features/circle_statuses/index.jsx +++ b/app/javascript/mastodon/features/circle_statuses/index.jsx @@ -13,12 +13,12 @@ import { debounce } from 'lodash'; import { deleteCircle, expandCircleStatuses, fetchCircle, fetchCircleStatuses } from 'mastodon/actions/circles'; import { addColumn, removeColumn, moveColumn } from 'mastodon/actions/columns'; import { openModal } from 'mastodon/actions/modal'; +import Column from 'mastodon/components/column'; import ColumnHeader from 'mastodon/components/column_header'; import { Icon } from 'mastodon/components/icon'; import { LoadingIndicator } from 'mastodon/components/loading_indicator'; import StatusList from 'mastodon/components/status_list'; import BundleColumnError from 'mastodon/features/ui/components/bundle_column_error'; -import Column from 'mastodon/features/ui/components/column'; import { getCircleStatusList } from 'mastodon/selectors'; diff --git a/app/javascript/mastodon/features/emoji_reacted_statuses/index.jsx b/app/javascript/mastodon/features/emoji_reacted_statuses/index.jsx index ad713f2d64..682f9f44f3 100644 --- a/app/javascript/mastodon/features/emoji_reacted_statuses/index.jsx +++ b/app/javascript/mastodon/features/emoji_reacted_statuses/index.jsx @@ -12,9 +12,9 @@ import { debounce } from 'lodash'; import { addColumn, removeColumn, moveColumn } from 'mastodon/actions/columns'; import { fetchEmojiReactedStatuses, expandEmojiReactedStatuses } from 'mastodon/actions/emoji_reactions'; +import Column from 'mastodon/components/column'; import ColumnHeader from 'mastodon/components/column_header'; import StatusList from 'mastodon/components/status_list'; -import Column from 'mastodon/features/ui/components/column'; const messages = defineMessages({ heading: { id: 'column.emoji_reactions', defaultMessage: 'Stamps' }, diff --git a/app/javascript/mastodon/features/favourited_statuses/index.jsx b/app/javascript/mastodon/features/favourited_statuses/index.jsx index 76cff7f8df..fb5447a11f 100644 --- a/app/javascript/mastodon/features/favourited_statuses/index.jsx +++ b/app/javascript/mastodon/features/favourited_statuses/index.jsx @@ -12,9 +12,9 @@ import { debounce } from 'lodash'; import { addColumn, removeColumn, moveColumn } from 'mastodon/actions/columns'; import { fetchFavouritedStatuses, expandFavouritedStatuses } from 'mastodon/actions/favourites'; +import Column from 'mastodon/components/column'; import ColumnHeader from 'mastodon/components/column_header'; import StatusList from 'mastodon/components/status_list'; -import Column from 'mastodon/features/ui/components/column'; import { getStatusList } from 'mastodon/selectors'; const messages = defineMessages({ From 9b746fa17e6f041d9415350d9ba5e009f723f54d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Mon, 16 Oct 2023 17:35:57 +0900 Subject: [PATCH 58/58] =?UTF-8?q?Fix:=20=E6=A6=82=E8=A6=81=E7=94=BB?= =?UTF-8?q?=E9=9D=A2=E3=81=A7=E3=82=A8=E3=83=A9=E3=83=BC=E3=81=8C=E7=99=BA?= =?UTF-8?q?=E7=94=9F=E3=81=99=E3=82=8B=E5=A0=B4=E5=90=88=E3=81=8C=E3=81=82?= =?UTF-8?q?=E3=82=8B=E5=95=8F=E9=A1=8C=20(#125)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix: 概要画面でエラーの発生する場合がある問題 * 単にロード中にデータ参照しただけでは? --- app/javascript/mastodon/features/about/index.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/mastodon/features/about/index.jsx b/app/javascript/mastodon/features/about/index.jsx index 85d9ca183b..6a24897319 100644 --- a/app/javascript/mastodon/features/about/index.jsx +++ b/app/javascript/mastodon/features/about/index.jsx @@ -127,7 +127,7 @@ class About extends PureComponent { const { multiColumn, intl, server, extendedDescription, domainBlocks } = this.props; const isLoading = server.get('isLoading'); - const fedibirdCapabilities = server.get('fedibird_capabilities'); + const fedibirdCapabilities = server.get('fedibird_capabilities') || []; // thinking about isLoading is true const isPublicUnlistedVisibility = fedibirdCapabilities.includes('kmyblue_visibility_public_unlisted'); const isEmojiReaction = fedibirdCapabilities.includes('emoji_reaction');