From af8fe6e1e9d728a4af39941e1bde918b0ca7d204 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 19 Mar 2021 17:15:36 +0100 Subject: [PATCH 01/27] WIP (#15222) --- app/models/concerns/omniauthable.rb | 1 - app/models/user.rb | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/models/concerns/omniauthable.rb b/app/models/concerns/omniauthable.rb index 79d671d10ac..791a9491102 100644 --- a/app/models/concerns/omniauthable.rb +++ b/app/models/concerns/omniauthable.rb @@ -68,7 +68,6 @@ module Omniauthable def user_params_from_auth(email, auth) { email: email || "#{TEMP_EMAIL_PREFIX}-#{auth.uid}-#{auth.provider}.com", - password: Devise.friendly_token[0, 20], agreement: true, external: true, account_attributes: { diff --git a/app/models/user.rb b/app/models/user.rb index b4508c2ebb1..5a149f573ed 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -468,7 +468,7 @@ class User < ApplicationRecord end def validate_email_dns? - email_changed? && !(Rails.env.test? || Rails.env.development?) + email_changed? && !external? && !(Rails.env.test? || Rails.env.development?) end def invite_text_required? From 8fa11b0e836fc2984fe8a771330d651fc7cc73cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczak?= Date: Fri, 19 Mar 2021 17:15:59 +0100 Subject: [PATCH 02/27] Add missing `en.notification_mailer.status.subject` (#15564) * Add missing `en.notification_mailer.status.subject` * Update en.yml --- config/locales/en.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/locales/en.yml b/config/locales/en.yml index beb56834694..4d452af6462 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1048,6 +1048,8 @@ en: body: 'Your status was boosted by %{name}:' subject: "%{name} boosted your status" title: New boost + status: + subject: "%{name} just posted" notifications: email_events: Events for e-mail notifications email_events_hint: 'Select events that you want to receive notifications for:' From 0ff4264c3e175226414a3782c91dde696132ed2e Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 19 Mar 2021 20:22:49 +0100 Subject: [PATCH 03/27] Add missing push notification title for polls (#15929) --- config/locales/en.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/locales/en.yml b/config/locales/en.yml index 4d452af6462..a6e54adf631 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1044,6 +1044,8 @@ en: body: 'You were mentioned by %{name} in:' subject: You were mentioned by %{name} title: New mention + poll: + title: A poll has ended reblog: body: 'Your status was boosted by %{name}:' subject: "%{name} boosted your status" From 39a490c70ebad27a1bd5e20c14722750756c79a4 Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 19 Mar 2021 20:23:08 +0100 Subject: [PATCH 04/27] Fix custom CSS when CDN_HOST is set (#15927) --- app/views/layouts/application.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 9501207e081..436024ee35e 100755 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -31,7 +31,7 @@ = stylesheet_link_tag '/inert.css', skip_pipeline: true, media: 'all', id: 'inert-style' - if Setting.custom_css.present? - = stylesheet_link_tag custom_css_path, media: 'all' + = stylesheet_link_tag custom_css_path, host: request.host, media: 'all' = yield :header_tags From 5d48402be1145201395e7fc297fe32a34638dd98 Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 19 Mar 2021 20:23:32 +0100 Subject: [PATCH 05/27] Fixing the hero widget (#15926) * Removing last-child padding conflicts with light theme in hero widget * Add missing background color to widget * Reset widget.scss to default * Hope this works Co-authored-by: koyu --- app/javascript/styles/mastodon-light/diff.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/app/javascript/styles/mastodon-light/diff.scss b/app/javascript/styles/mastodon-light/diff.scss index d4290d7e61a..8e6b0cdd5b8 100644 --- a/app/javascript/styles/mastodon-light/diff.scss +++ b/app/javascript/styles/mastodon-light/diff.scss @@ -707,7 +707,6 @@ html { .public-account-bio, .hero-widget__text { background: $account-background-color; - border: 1px solid lighten($ui-base-color, 8%); } .header { From d023eefbcc1e6c2221a53484e58e61ac12eaa1d4 Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 19 Mar 2021 23:47:31 +0100 Subject: [PATCH 06/27] Fix push notification title for polls (#15931) --- config/locales/en.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/en.yml b/config/locales/en.yml index a6e54adf631..b364e92373b 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1045,7 +1045,7 @@ en: subject: You were mentioned by %{name} title: New mention poll: - title: A poll has ended + subject: A poll by %{name} has ended reblog: body: 'Your status was boosted by %{name}:' subject: "%{name} boosted your status" From 051efed5edd544b4f88c63a1038274ae2db30038 Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 19 Mar 2021 23:48:47 +0100 Subject: [PATCH 07/27] Bypass MX validation for explicitly allowed domains (#15930) * Bypass MX validation for explicitly allowed domains This spares some lookups and prevent issues in some edge cases with local domains. * Add tests * Fix test --- app/validators/email_mx_validator.rb | 8 +++++++- spec/models/user_spec.rb | 2 +- spec/validators/email_mx_validator_spec.rb | 18 ++++++++++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/app/validators/email_mx_validator.rb b/app/validators/email_mx_validator.rb index 9f70a1469aa..dceef50290c 100644 --- a/app/validators/email_mx_validator.rb +++ b/app/validators/email_mx_validator.rb @@ -10,7 +10,7 @@ class EmailMxValidator < ActiveModel::Validator if domain.blank? user.errors.add(:email, :invalid) - else + elsif !on_allowlist?(domain) ips, hostnames = resolve_mx(domain) if ips.empty? @@ -33,6 +33,12 @@ class EmailMxValidator < ActiveModel::Validator nil end + def on_allowlist?(domain) + return false if Rails.configuration.x.email_domains_whitelist.blank? + + Rails.configuration.x.email_domains_whitelist.include?(domain) + end + def resolve_mx(domain) hostnames = [] ips = [] diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index cded4c99bdc..1dae4353608 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -206,7 +206,7 @@ RSpec.describe User, type: :model do describe 'whitelist' do around(:each) do |example| - old_whitelist = Rails.configuration.x.email_whitelist + old_whitelist = Rails.configuration.x.email_domains_whitelist Rails.configuration.x.email_domains_whitelist = 'mastodon.space' diff --git a/spec/validators/email_mx_validator_spec.rb b/spec/validators/email_mx_validator_spec.rb index 48e17a4f108..550e91996bb 100644 --- a/spec/validators/email_mx_validator_spec.rb +++ b/spec/validators/email_mx_validator_spec.rb @@ -6,6 +6,24 @@ describe EmailMxValidator do describe '#validate' do let(:user) { double(email: 'foo@example.com', errors: double(add: nil)) } + it 'does not add errors if there are no DNS records for an e-mail domain that is explicitly allowed' do + old_whitelist = Rails.configuration.x.email_domains_whitelist + Rails.configuration.x.email_domains_whitelist = 'example.com' + + resolver = double + + allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::MX).and_return([]) + allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::A).and_return([]) + allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::AAAA).and_return([]) + allow(resolver).to receive(:timeouts=).and_return(nil) + allow(Resolv::DNS).to receive(:open).and_yield(resolver) + + subject.validate(user) + expect(user.errors).to_not have_received(:add) + + Rails.configuration.x.email_domains_whitelist = old_whitelist + end + it 'adds an error if there are no DNS records for the e-mail domain' do resolver = double From 876840e9efceb4cde0af92e2a0f5d7afe906b5e9 Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 19 Mar 2021 23:48:59 +0100 Subject: [PATCH 08/27] Fix brakeman warning (#15870) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As far as I understand, the brakeman warning was a false-positive as `content_tag` properly escapes untrusted HTML. Furthermore, the interpolated string values are built from the “username” part of accounts, which is restricted to a small subset of ASCII that precludes any XML entity or HTML code. This proposed change should be functionally equivalent to the current code, however it is slightly more robust, it's more idiomatic, and Brakeman will stop complaining about it. --- .../admin/action_logs/_action_log.html.haml | 2 +- app/views/admin/reports/_action_log.html.haml | 2 +- config/locales/en.yml | 80 +++++++++---------- 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/app/views/admin/action_logs/_action_log.html.haml b/app/views/admin/action_logs/_action_log.html.haml index 59905f34181..a2fce2d1145 100644 --- a/app/views/admin/action_logs/_action_log.html.haml +++ b/app/views/admin/action_logs/_action_log.html.haml @@ -4,6 +4,6 @@ = image_tag action_log.account.avatar.url(:original), alt: '', width: 40, height: 40, class: 'avatar' .log-entry__content .log-entry__title - = t("admin.action_logs.actions.#{action_log.action}_#{action_log.target_type.underscore}", name: content_tag(:span, action_log.account.username, class: 'username'), target: content_tag(:span, log_target(action_log), class: 'target')).html_safe + = t("admin.action_logs.actions.#{action_log.action}_#{action_log.target_type.underscore}_html", name: content_tag(:span, action_log.account.username, class: 'username'), target: content_tag(:span, log_target(action_log), class: 'target')) .log-entry__timestamp %time.formatted{ datetime: action_log.created_at.iso8601 } diff --git a/app/views/admin/reports/_action_log.html.haml b/app/views/admin/reports/_action_log.html.haml index 024078eb9a6..0f7d0586792 100644 --- a/app/views/admin/reports/_action_log.html.haml +++ b/app/views/admin/reports/_action_log.html.haml @@ -1,6 +1,6 @@ .speech-bubble.positive .speech-bubble__bubble - = t("admin.action_logs.actions.#{action_log.action}_#{action_log.target_type.underscore}", name: content_tag(:span, action_log.account.username, class: 'username'), target: content_tag(:span, log_target(action_log), class: 'target')).html_safe + = t("admin.action_logs.actions.#{action_log.action}_#{action_log.target_type.underscore}_html", name: content_tag(:span, action_log.account.username, class: 'username'), target: content_tag(:span, log_target(action_log), class: 'target')) .speech-bubble__owner = admin_account_link_to(action_log.account) %time.formatted{ datetime: action_log.created_at.iso8601 }= l action_log.created_at diff --git a/config/locales/en.yml b/config/locales/en.yml index b364e92373b..14f1a08e4b2 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -261,46 +261,46 @@ en: update_domain_block: Update Domain Block update_status: Update Status actions: - assigned_to_self_report: "%{name} assigned report %{target} to themselves" - change_email_user: "%{name} changed the e-mail address of user %{target}" - confirm_user: "%{name} confirmed e-mail address of user %{target}" - create_account_warning: "%{name} sent a warning to %{target}" - create_announcement: "%{name} created new announcement %{target}" - create_custom_emoji: "%{name} uploaded new emoji %{target}" - create_domain_allow: "%{name} allowed federation with domain %{target}" - create_domain_block: "%{name} blocked domain %{target}" - create_email_domain_block: "%{name} blocked e-mail domain %{target}" - create_ip_block: "%{name} created rule for IP %{target}" - demote_user: "%{name} demoted user %{target}" - destroy_announcement: "%{name} deleted announcement %{target}" - destroy_custom_emoji: "%{name} destroyed emoji %{target}" - destroy_domain_allow: "%{name} disallowed federation with domain %{target}" - destroy_domain_block: "%{name} unblocked domain %{target}" - destroy_email_domain_block: "%{name} unblocked e-mail domain %{target}" - destroy_ip_block: "%{name} deleted rule for IP %{target}" - destroy_status: "%{name} removed status by %{target}" - disable_2fa_user: "%{name} disabled two factor requirement for user %{target}" - disable_custom_emoji: "%{name} disabled emoji %{target}" - disable_user: "%{name} disabled login for user %{target}" - enable_custom_emoji: "%{name} enabled emoji %{target}" - enable_user: "%{name} enabled login for user %{target}" - memorialize_account: "%{name} turned %{target}'s account into a memoriam page" - promote_user: "%{name} promoted user %{target}" - remove_avatar_user: "%{name} removed %{target}'s avatar" - reopen_report: "%{name} reopened report %{target}" - reset_password_user: "%{name} reset password of user %{target}" - resolve_report: "%{name} resolved report %{target}" - sensitive_account: "%{name} marked %{target}'s media as sensitive" - silence_account: "%{name} silenced %{target}'s account" - suspend_account: "%{name} suspended %{target}'s account" - unassigned_report: "%{name} unassigned report %{target}" - unsensitive_account: "%{name} unmarked %{target}'s media as sensitive" - unsilence_account: "%{name} unsilenced %{target}'s account" - unsuspend_account: "%{name} unsuspended %{target}'s account" - update_announcement: "%{name} updated announcement %{target}" - update_custom_emoji: "%{name} updated emoji %{target}" - update_domain_block: "%{name} updated domain block for %{target}" - update_status: "%{name} updated status by %{target}" + assigned_to_self_report_html: "%{name} assigned report %{target} to themselves" + change_email_user_html: "%{name} changed the e-mail address of user %{target}" + confirm_user_html: "%{name} confirmed e-mail address of user %{target}" + create_account_warning_html: "%{name} sent a warning to %{target}" + create_announcement_html: "%{name} created new announcement %{target}" + create_custom_emoji_html: "%{name} uploaded new emoji %{target}" + create_domain_allow_html: "%{name} allowed federation with domain %{target}" + create_domain_block_html: "%{name} blocked domain %{target}" + create_email_domain_block_html: "%{name} blocked e-mail domain %{target}" + create_ip_block_html: "%{name} created rule for IP %{target}" + demote_user_html: "%{name} demoted user %{target}" + destroy_announcement_html: "%{name} deleted announcement %{target}" + destroy_custom_emoji_html: "%{name} destroyed emoji %{target}" + destroy_domain_allow_html: "%{name} disallowed federation with domain %{target}" + destroy_domain_block_html: "%{name} unblocked domain %{target}" + destroy_email_domain_block_html: "%{name} unblocked e-mail domain %{target}" + destroy_ip_block_html: "%{name} deleted rule for IP %{target}" + destroy_status_html: "%{name} removed status by %{target}" + disable_2fa_user_html: "%{name} disabled two factor requirement for user %{target}" + disable_custom_emoji_html: "%{name} disabled emoji %{target}" + disable_user_html: "%{name} disabled login for user %{target}" + enable_custom_emoji_html: "%{name} enabled emoji %{target}" + enable_user_html: "%{name} enabled login for user %{target}" + memorialize_account_html: "%{name} turned %{target}'s account into a memoriam page" + promote_user_html: "%{name} promoted user %{target}" + remove_avatar_user_html: "%{name} removed %{target}'s avatar" + reopen_report_html: "%{name} reopened report %{target}" + reset_password_user_html: "%{name} reset password of user %{target}" + resolve_report_html: "%{name} resolved report %{target}" + sensitive_account_html: "%{name} marked %{target}'s media as sensitive" + silence_account_html: "%{name} silenced %{target}'s account" + suspend_account_html: "%{name} suspended %{target}'s account" + unassigned_report_html: "%{name} unassigned report %{target}" + unsensitive_account_html: "%{name} unmarked %{target}'s media as sensitive" + unsilence_account_html: "%{name} unsilenced %{target}'s account" + unsuspend_account_html: "%{name} unsuspended %{target}'s account" + update_announcement_html: "%{name} updated announcement %{target}" + update_custom_emoji_html: "%{name} updated emoji %{target}" + update_domain_block_html: "%{name} updated domain block for %{target}" + update_status_html: "%{name} updated status by %{target}" deleted_status: "(deleted status)" empty: No logs found. filter_by_action: Filter by action From 46d3d3169edad116aba82ba41c08111e18cd3769 Mon Sep 17 00:00:00 2001 From: Sandro Date: Sat, 20 Mar 2021 21:21:57 +0100 Subject: [PATCH 09/27] Docker: Use precompiled jemalloc, format, apply hadolint suggestions (#10823) * Format, apply hadolint suggestions, little nitpicks * Use pre compiled jemalloc * Use tini from package repository --- Dockerfile | 71 +++++++++++++++++------------------------------------- 1 file changed, 22 insertions(+), 49 deletions(-) diff --git a/Dockerfile b/Dockerfile index 1b89a97b74e..3b3d6dfcd18 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ FROM ubuntu:20.04 as build-dep # Use bash for the shell -SHELL ["/usr/bin/bash", "-c"] +SHELL ["/bin/bash", "-c"] # Install Node v12 (LTS) ENV NODE_VER="12.21.0" @@ -17,35 +17,19 @@ RUN ARCH= && \ *) echo "unsupported architecture"; exit 1 ;; \ esac && \ echo "Etc/UTC" > /etc/localtime && \ - apt update && \ - apt -y install wget python && \ + apt-get update && \ + apt-get install -y --no-install-recommends ca-certificates wget python && \ cd ~ && \ - wget https://nodejs.org/download/release/v$NODE_VER/node-v$NODE_VER-linux-$ARCH.tar.gz && \ + wget -q https://nodejs.org/download/release/v$NODE_VER/node-v$NODE_VER-linux-$ARCH.tar.gz && \ tar xf node-v$NODE_VER-linux-$ARCH.tar.gz && \ rm node-v$NODE_VER-linux-$ARCH.tar.gz && \ mv node-v$NODE_VER-linux-$ARCH /opt/node -# Install jemalloc -ENV JE_VER="5.2.1" -RUN apt update && \ - apt -y install make autoconf gcc g++ && \ - cd ~ && \ - wget https://github.com/jemalloc/jemalloc/archive/$JE_VER.tar.gz && \ - tar xf $JE_VER.tar.gz && \ - cd jemalloc-$JE_VER && \ - ./autogen.sh && \ - ./configure --prefix=/opt/jemalloc && \ - make -j$(nproc) > /dev/null && \ - make install_bin install_include install_lib && \ - cd .. && rm -rf jemalloc-$JE_VER $JE_VER.tar.gz - # Install Ruby ENV RUBY_VER="2.7.2" -ENV CPPFLAGS="-I/opt/jemalloc/include" -ENV LDFLAGS="-L/opt/jemalloc/lib/" -RUN apt update && \ - apt -y install build-essential \ - bison libyaml-dev libgdbm-dev libreadline-dev \ +RUN apt-get update && \ + apt-get install -y --no-install-recommends build-essential \ + bison libyaml-dev libgdbm-dev libreadline-dev libjemalloc-dev \ libncurses5-dev libffi-dev zlib1g-dev libssl-dev && \ cd ~ && \ wget https://cache.ruby-lang.org/pub/ruby/${RUBY_VER%.*}/ruby-$RUBY_VER.tar.gz && \ @@ -55,17 +39,16 @@ RUN apt update && \ --with-jemalloc \ --with-shared \ --disable-install-doc && \ - ln -s /opt/jemalloc/lib/* /usr/lib/ && \ - make -j$(nproc) > /dev/null && \ + make -j"$(nproc)" > /dev/null && \ make install && \ - cd .. && rm -rf ruby-$RUBY_VER.tar.gz ruby-$RUBY_VER + rm -rf ../ruby-$RUBY_VER.tar.gz ../ruby-$RUBY_VER ENV PATH="${PATH}:/opt/ruby/bin:/opt/node/bin" RUN npm install -g yarn && \ gem install bundler && \ - apt update && \ - apt -y install git libicu-dev libidn11-dev \ + apt-get update && \ + apt-get install -y --no-install-recommends git libicu-dev libidn11-dev \ libpq-dev libprotobuf-dev protobuf-compiler COPY Gemfile* package.json yarn.lock /opt/mastodon/ @@ -73,7 +56,7 @@ COPY Gemfile* package.json yarn.lock /opt/mastodon/ RUN cd /opt/mastodon && \ bundle config set deployment 'true' && \ bundle config set without 'development test' && \ - bundle install -j$(nproc) && \ + bundle install -j"$(nproc)" && \ yarn install --pure-lockfile FROM ubuntu:20.04 @@ -81,7 +64,6 @@ FROM ubuntu:20.04 # Copy over all the langs needed for runtime COPY --from=build-dep /opt/node /opt/node COPY --from=build-dep /opt/ruby /opt/ruby -COPY --from=build-dep /opt/jemalloc /opt/jemalloc # Add more PATHs to the PATH ENV PATH="${PATH}:/opt/ruby/bin:/opt/node/bin:/opt/mastodon/bin" @@ -89,35 +71,26 @@ ENV PATH="${PATH}:/opt/ruby/bin:/opt/node/bin:/opt/mastodon/bin" # Create the mastodon user ARG UID=991 ARG GID=991 -RUN apt update && \ +SHELL ["/bin/bash", "-o", "pipefail", "-c"] +RUN apt-get update && \ echo "Etc/UTC" > /etc/localtime && \ - ln -s /opt/jemalloc/lib/* /usr/lib/ && \ - apt install -y whois wget && \ + apt-get install -y --no-install-recommends whois wget && \ addgroup --gid $GID mastodon && \ useradd -m -u $UID -g $GID -d /opt/mastodon mastodon && \ - echo "mastodon:`head /dev/urandom | tr -dc A-Za-z0-9 | head -c 24 | mkpasswd -s -m sha-256`" | chpasswd + echo "mastodon:$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 24 | mkpasswd -s -m sha-256)" | chpasswd && \ + rm -rf /var/lib/apt/lists/* # Install mastodon runtime deps -RUN apt -y --no-install-recommends install \ - libssl1.1 libpq5 imagemagick ffmpeg \ +RUN apt-get update && \ + apt-get -y --no-install-recommends install \ + libssl1.1 libpq5 imagemagick ffmpeg libjemalloc2 \ libicu66 libprotobuf17 libidn11 libyaml-0-2 \ - file ca-certificates tzdata libreadline8 && \ - apt -y install gcc && \ + file ca-certificates tzdata libreadline8 gcc tini && \ ln -s /opt/mastodon /mastodon && \ gem install bundler && \ rm -rf /var/cache && \ rm -rf /var/lib/apt/lists/* -# Add tini -ENV TINI_VERSION="0.19.0" -RUN dpkgArch="$(dpkg --print-architecture)" && \ - ARCH=$dpkgArch && \ - wget https://github.com/krallin/tini/releases/download/v${TINI_VERSION}/tini-$ARCH \ - https://github.com/krallin/tini/releases/download/v${TINI_VERSION}/tini-$ARCH.sha256sum && \ - cat tini-$ARCH.sha256sum | sha256sum -c - && \ - mv tini-$ARCH /tini && rm tini-$ARCH.sha256sum && \ - chmod +x /tini - # Copy over mastodon source, and dependencies from building, and set permissions COPY --chown=mastodon:mastodon . /opt/mastodon COPY --from=build-dep --chown=mastodon:mastodon /opt/mastodon /opt/mastodon @@ -140,5 +113,5 @@ RUN cd ~ && \ # Set the work dir and the container entry point WORKDIR /opt/mastodon -ENTRYPOINT ["/tini", "--"] +ENTRYPOINT ["/usr/bin/tini", "--"] EXPOSE 3000 4000 From 829a598f1d8493a597dc655887e306b21bbbe0d0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Mar 2021 07:35:46 +0100 Subject: [PATCH 10/27] Bump sidekiq-unique-jobs from 7.0.4 to 7.0.7 (#15944) Bumps [sidekiq-unique-jobs](https://github.com/mhenrixon/sidekiq-unique-jobs) from 7.0.4 to 7.0.7. - [Release notes](https://github.com/mhenrixon/sidekiq-unique-jobs/releases) - [Changelog](https://github.com/mhenrixon/sidekiq-unique-jobs/blob/master/CHANGELOG.md) - [Commits](https://github.com/mhenrixon/sidekiq-unique-jobs/compare/v7.0.4...v7.0.7) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Gemfile.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 106c13554ca..f35a3468370 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -108,7 +108,7 @@ GEM msgpack (~> 1.0) brakeman (4.10.1) browser (4.2.0) - brpoplpush-redis_script (0.1.1) + brpoplpush-redis_script (0.1.2) concurrent-ruby (~> 1.0, >= 1.0.5) redis (>= 1.0, <= 5.0) builder (3.2.4) @@ -573,8 +573,8 @@ GEM sidekiq (>= 3) thwait tilt (>= 1.4.0) - sidekiq-unique-jobs (7.0.4) - brpoplpush-redis_script (> 0.0.0, <= 2.0.0) + sidekiq-unique-jobs (7.0.7) + brpoplpush-redis_script (> 0.1.1, <= 2.0.0) concurrent-ruby (~> 1.0, >= 1.0.5) sidekiq (>= 5.0, < 7.0) thor (>= 0.20, < 2.0) From 472d5005c0ee1dcbb17d942e789ca18f960ceaa4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Mar 2021 07:36:13 +0100 Subject: [PATCH 11/27] Bump blurhash from 0.1.4 to 0.1.5 (#15942) Bumps [blurhash](https://github.com/Gargron/blurhash) from 0.1.4 to 0.1.5. - [Release notes](https://github.com/Gargron/blurhash/releases) - [Commits](https://github.com/Gargron/blurhash/commits/v0.1.5) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Gemfile.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index f35a3468370..222eccdc314 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -102,8 +102,8 @@ GEM bindata (2.4.8) binding_of_caller (1.0.0) debug_inspector (>= 0.0.1) - blurhash (0.1.4) - ffi (~> 1.10.0) + blurhash (0.1.5) + ffi (~> 1.14) bootsnap (1.6.0) msgpack (~> 1.0) brakeman (4.10.1) @@ -222,7 +222,7 @@ GEM faraday-net_http (1.0.1) fast_blank (1.0.0) fastimage (2.2.3) - ffi (1.10.0) + ffi (1.14.2) ffi-compiler (1.0.1) ffi (>= 1.0.0) rake From 64942fa31d04a9fb8d488aa0eb2484207d7d2b96 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Mar 2021 07:37:51 +0100 Subject: [PATCH 12/27] Bump sidekiq from 6.1.3 to 6.2.0 (#15943) Bumps [sidekiq](https://github.com/mperham/sidekiq) from 6.1.3 to 6.2.0. - [Release notes](https://github.com/mperham/sidekiq/releases) - [Changelog](https://github.com/mperham/sidekiq/blob/master/Changes.md) - [Commits](https://github.com/mperham/sidekiq/compare/v6.1.3...v6.2.0) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index c3f50ec30c4..7d75f090279 100644 --- a/Gemfile +++ b/Gemfile @@ -83,7 +83,7 @@ gem 'rqrcode', '~> 1.2' gem 'ruby-progressbar', '~> 1.11' gem 'sanitize', '~> 5.2' gem 'scenic', '~> 1.5' -gem 'sidekiq', '~> 6.1' +gem 'sidekiq', '~> 6.2' gem 'sidekiq-scheduler', '~> 3.0' gem 'sidekiq-unique-jobs', '~> 7.0' gem 'sidekiq-bulk', '~>0.2.0' diff --git a/Gemfile.lock b/Gemfile.lock index 222eccdc314..4ca2154dad0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -560,7 +560,7 @@ GEM railties (>= 4.0.0) securecompare (1.0.0) semantic_range (2.3.0) - sidekiq (6.1.3) + sidekiq (6.2.0) connection_pool (>= 2.2.2) rack (~> 2.0) redis (>= 4.2.0) @@ -783,7 +783,7 @@ DEPENDENCIES ruby-progressbar (~> 1.11) sanitize (~> 5.2) scenic (~> 1.5) - sidekiq (~> 6.1) + sidekiq (~> 6.2) sidekiq-bulk (~> 0.2.0) sidekiq-scheduler (~> 3.0) sidekiq-unique-jobs (~> 7.0) From b5288798a8a25417b0bf6d4620dcaaef9db36f31 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Mar 2021 07:38:23 +0100 Subject: [PATCH 13/27] Bump ox from 2.14.3 to 2.14.4 (#15941) Bumps [ox](https://github.com/ohler55/ox) from 2.14.3 to 2.14.4. - [Release notes](https://github.com/ohler55/ox/releases) - [Changelog](https://github.com/ohler55/ox/blob/develop/CHANGELOG.md) - [Commits](https://github.com/ohler55/ox/compare/v2.14.3...v2.14.4) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 4ca2154dad0..c718dcd182e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -392,7 +392,7 @@ GEM openssl (2.2.0) openssl-signature_algorithm (0.4.0) orm_adapter (0.5.0) - ox (2.14.3) + ox (2.14.4) paperclip (6.0.0) activemodel (>= 4.2.0) activesupport (>= 4.2.0) From 229968bdff05838b0eea30a4f035995f0895f92e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Mar 2021 07:38:54 +0100 Subject: [PATCH 14/27] Bump rspec-rails from 5.0.0 to 5.0.1 (#15939) Bumps [rspec-rails](https://github.com/rspec/rspec-rails) from 5.0.0 to 5.0.1. - [Release notes](https://github.com/rspec/rspec-rails/releases) - [Changelog](https://github.com/rspec/rspec-rails/blob/main/Changelog.md) - [Commits](https://github.com/rspec/rspec-rails/compare/v5.0.0...v5.0.1) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index c718dcd182e..690b270dcc2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -514,7 +514,7 @@ GEM rspec-mocks (3.10.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.10.0) - rspec-rails (5.0.0) + rspec-rails (5.0.1) actionpack (>= 5.2) activesupport (>= 5.2) railties (>= 5.2) From 6b5cda6ec310bd07d70740baed2ecd427d2c3d19 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Mar 2021 07:39:19 +0100 Subject: [PATCH 15/27] Bump css-loader from 5.1.2 to 5.1.3 (#15940) Bumps [css-loader](https://github.com/webpack-contrib/css-loader) from 5.1.2 to 5.1.3. - [Release notes](https://github.com/webpack-contrib/css-loader/releases) - [Changelog](https://github.com/webpack-contrib/css-loader/blob/master/CHANGELOG.md) - [Commits](https://github.com/webpack-contrib/css-loader/compare/v5.1.2...v5.1.3) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index fd766cc8c1d..f68436721b8 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "color-blend": "^3.0.1", "compression-webpack-plugin": "^6.1.1", "cross-env": "^7.0.3", - "css-loader": "^5.1.2", + "css-loader": "^5.1.3", "cssnano": "^4.1.10", "detect-passive-events": "^2.0.3", "dotenv": "^8.2.0", diff --git a/yarn.lock b/yarn.lock index 3cc2c7f83ea..f0e6c8ed34c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3373,10 +3373,10 @@ css-list-helpers@^1.0.1: dependencies: tcomb "^2.5.0" -css-loader@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-5.1.2.tgz#b93dba498ec948b543b49d4fab5017205d4f5c3e" - integrity sha512-T7vTXHSx0KrVEg/xjcl7G01RcVXpcw4OELwDPvkr7izQNny85A84dK3dqrczuEfBcu7Yg7mdTjJLSTibRUoRZg== +css-loader@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-5.1.3.tgz#87f6fc96816b20debe3cf682f85c7e56a963d0d1" + integrity sha512-CoPZvyh8sLiGARK3gqczpfdedbM74klGWurF2CsNZ2lhNaXdLIUks+3Mfax3WBeRuHoglU+m7KG/+7gY6G4aag== dependencies: camelcase "^6.2.0" cssesc "^3.0.0" From 1b3ebcfe53e29e4a9e425b466079081aa92990df Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Mar 2021 07:39:39 +0100 Subject: [PATCH 16/27] Bump aws-sdk-s3 from 1.91.0 to 1.92.0 (#15938) Bumps [aws-sdk-s3](https://github.com/aws/aws-sdk-ruby) from 1.91.0 to 1.92.0. - [Release notes](https://github.com/aws/aws-sdk-ruby/releases) - [Changelog](https://github.com/aws/aws-sdk-ruby/blob/version-3/gems/aws-sdk-s3/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-ruby/commits) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Gemfile | 2 +- Gemfile.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gemfile b/Gemfile index 7d75f090279..98af92deff4 100644 --- a/Gemfile +++ b/Gemfile @@ -17,7 +17,7 @@ gem 'makara', '~> 0.5' gem 'pghero', '~> 2.8' gem 'dotenv-rails', '~> 2.7' -gem 'aws-sdk-s3', '~> 1.91', require: false +gem 'aws-sdk-s3', '~> 1.92', require: false gem 'fog-core', '<= 2.1.0' gem 'fog-openstack', '~> 0.3', require: false gem 'paperclip', '~> 6.0' diff --git a/Gemfile.lock b/Gemfile.lock index 690b270dcc2..1a67f893d63 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -79,7 +79,7 @@ GEM cocaine (~> 0.5.3) awrence (1.1.1) aws-eventstream (1.1.1) - aws-partitions (1.432.0) + aws-partitions (1.434.0) aws-sdk-core (3.113.0) aws-eventstream (~> 1, >= 1.0.2) aws-partitions (~> 1, >= 1.239.0) @@ -88,7 +88,7 @@ GEM aws-sdk-kms (1.43.0) aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.91.0) + aws-sdk-s3 (1.92.0) aws-sdk-core (~> 3, >= 3.112.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.1) @@ -681,7 +681,7 @@ DEPENDENCIES active_record_query_trace (~> 1.8) addressable (~> 2.7) annotate (~> 3.1) - aws-sdk-s3 (~> 1.91) + aws-sdk-s3 (~> 1.92) better_errors (~> 2.9) binding_of_caller (~> 1.0) blurhash (~> 0.1) From c3aef491d66aec743a3a53e934a494f653745b61 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Mar 2021 15:41:47 +0900 Subject: [PATCH 17/27] Bump react-select from 3.2.0 to 4.0.2 (#15624) * Bump react-select from 3.2.0 to 4.0.2 Bumps [react-select](https://github.com/JedWatson/react-select) from 3.2.0 to 4.0.2. - [Release notes](https://github.com/JedWatson/react-select/releases) - [Changelog](https://github.com/JedWatson/react-select/blob/master/docs/CHANGELOG.md) - [Commits](https://github.com/JedWatson/react-select/compare/react-select@3.2.0...react-select@4.0.2) Signed-off-by: dependabot[bot] * Add cacheKey to NonceProvider for react-select Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Yamagishi Kazutoshi --- .../components/column_settings.js | 2 +- package.json | 2 +- yarn.lock | 201 ++++++++++-------- 3 files changed, 109 insertions(+), 96 deletions(-) diff --git a/app/javascript/mastodon/features/hashtag_timeline/components/column_settings.js b/app/javascript/mastodon/features/hashtag_timeline/components/column_settings.js index 27300f020df..de1127b0d51 100644 --- a/app/javascript/mastodon/features/hashtag_timeline/components/column_settings.js +++ b/app/javascript/mastodon/features/hashtag_timeline/components/column_settings.js @@ -59,7 +59,7 @@ class ColumnSettings extends React.PureComponent { {this.modeLabel(mode)} - + Date: Wed, 24 Mar 2021 09:37:41 +0100 Subject: [PATCH 18/27] Switch from deprecated ClusterWS/cws to ws package (#15932) * Switch from deprecated ClusterWS/cws to ws package Fixes #15184 Co-authored-by: Edho Arief * Make bufferutil and utf-8-validate optional dependencies Co-authored-by: Edho Arief --- package.json | 8 ++++++-- streaming/index.js | 22 +++++++++++++++++++--- yarn.lock | 29 ++++++++++++++++++++++++----- 3 files changed, 49 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 1a6eb8001e8..a8896ecfb43 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,6 @@ "@babel/preset-env": "^7.13.10", "@babel/preset-react": "^7.12.13", "@babel/runtime": "^7.13.10", - "@clusterws/cws": "^3.0.0", "@gamestdio/websocket": "^0.3.2", "@github/webauthn-json": "^0.5.7", "@rails/ujs": "^6.1.3", @@ -169,7 +168,8 @@ "webpack-bundle-analyzer": "^4.4.0", "webpack-cli": "^3.3.12", "webpack-merge": "^5.7.3", - "wicg-inert": "^3.1.1" + "wicg-inert": "^3.1.1", + "ws": "^7.4.4" }, "devDependencies": { "@testing-library/jest-dom": "^5.11.9", @@ -191,5 +191,9 @@ }, "resolutions": { "kind-of": "^6.0.3" + }, + "optionalDependencies": { + "bufferutil": "^4.0.3", + "utf-8-validate": "^5.0.4" } } diff --git a/streaming/index.js b/streaming/index.js index 3279bd94ebc..c50d3558314 100644 --- a/streaming/index.js +++ b/streaming/index.js @@ -9,9 +9,9 @@ const redis = require('redis'); const pg = require('pg'); const log = require('npmlog'); const url = require('url'); -const { WebSocketServer } = require('@clusterws/cws'); const uuid = require('uuid'); const fs = require('fs'); +const WebSocket = require('ws'); const env = process.env.NODE_ENV || 'development'; const alwaysRequireAuth = process.env.LIMITED_FEDERATION_MODE === 'true' || process.env.WHITELIST_MODE === 'true' || process.env.AUTHORIZED_FETCH === 'true'; @@ -766,7 +766,7 @@ const startWorker = (workerId) => { }); }); - const wss = new WebSocketServer({ server, verifyClient: wsVerifyClient }); + const wss = new WebSocket.Server({ server, verifyClient: wsVerifyClient }); /** * @typedef StreamParams @@ -999,6 +999,12 @@ const startWorker = (workerId) => { req.requestId = uuid.v4(); req.remoteAddress = ws._socket.remoteAddress; + ws.isAlive = true; + + ws.on('pong', () => { + ws.isAlive = true; + }); + /** * @type {WebSocketSession} */ @@ -1048,7 +1054,17 @@ const startWorker = (workerId) => { } }); - wss.startAutoPing(30000); + setInterval(() => { + wss.clients.forEach(ws => { + if (ws.isAlive === false) { + ws.terminate(); + return; + } + + ws.isAlive = false; + ws.ping('', false, true); + }); + }, 30000); attachServerWithConfig(server, address => { log.info(`Worker ${workerId} now listening on ${address}`); diff --git a/yarn.lock b/yarn.lock index 236dd346af7..1adbca91611 100644 --- a/yarn.lock +++ b/yarn.lock @@ -991,11 +991,6 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@clusterws/cws@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@clusterws/cws/-/cws-3.0.0.tgz#518fc8e7d9066e220f6f6aef3158cc14d5a1e98e" - integrity sha512-6RO7IUbSlTO3l8XPN/9g21YGPF4HjfkidDzchkP0h6iwq5jYtji+KUCgyxcSYiuN7aWu8nGJDjBer7XJilPnOg== - "@cnakazawa/watch@^1.0.3": version "1.0.4" resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a" @@ -2623,6 +2618,13 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" +bufferutil@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.3.tgz#66724b756bed23cd7c28c4d306d7994f9943cc6b" + integrity sha512-yEYTwGndELGvfXsImMBLop58eaGW+YdONi1fNjTINSY98tmMmFijBG6WXgdkfuLNt4imzQNtIE+eBp1PVpMCSw== + dependencies: + node-gyp-build "^4.2.0" + builtin-status-codes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" @@ -7370,6 +7372,11 @@ node-forge@^0.10.0: resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA== +node-gyp-build@^4.2.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.2.3.tgz#ce6277f853835f718829efb47db20f3e4d9c4739" + integrity sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg== + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -10980,6 +10987,13 @@ user-home@^2.0.0: dependencies: os-homedir "^1.0.0" +utf-8-validate@^5.0.4: + version "5.0.4" + resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.4.tgz#72a1735983ddf7a05a43a9c6b67c5ce1c910f9b8" + integrity sha512-MEF05cPSq3AwJ2C7B7sHAA6i53vONoZbMGX8My5auEVm6W+dJ2Jd/TZPyGJ5CH42V2XtbI5FD28HeHeqlPzZ3Q== + dependencies: + node-gyp-build "^4.2.0" + util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -11461,6 +11475,11 @@ ws@^7.2.3, ws@^7.3.1: resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.0.tgz#a5dd76a24197940d4a8bb9e0e152bb4503764da7" integrity sha512-kyFwXuV/5ymf+IXhS6f0+eAFvydbaBW3zjpT6hUdAh/hbVjTIB5EHBGi0bPoCLSK2wcuz3BrEkB9LrYv1Nm4NQ== +ws@^7.4.4: + version "7.4.4" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.4.tgz#383bc9742cb202292c9077ceab6f6047b17f2d59" + integrity sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw== + xml-name-validator@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" From 034f37b85a716872f78a72048a5a225cdcaa840a Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 24 Mar 2021 10:19:07 +0100 Subject: [PATCH 19/27] Fix compose form behavior in mobile view (#15555) * Fix ComposeForm being mounted twice in mobile view Fixes #13094 * Fix compose form focus and pre-selection behavior in mobile view * Split _updateFocusAndSelection out of componentDidUpdate --- .../compose/components/compose_form.js | 8 +++++++ .../features/ui/components/columns_area.js | 21 +++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/app/javascript/mastodon/features/compose/components/compose_form.js b/app/javascript/mastodon/features/compose/components/compose_form.js index 8af806ec437..ba2d20cc7e6 100644 --- a/app/javascript/mastodon/features/compose/components/compose_form.js +++ b/app/javascript/mastodon/features/compose/components/compose_form.js @@ -132,7 +132,15 @@ class ComposeForm extends ImmutablePureComponent { } } + componentDidMount () { + this._updateFocusAndSelection({ }); + } + componentDidUpdate (prevProps) { + this._updateFocusAndSelection(prevProps); + } + + _updateFocusAndSelection = (prevProps) => { // This statement does several things: // - If we're beginning a reply, and, // - Replying to zero or one users, places the cursor at the end of the textbox. diff --git a/app/javascript/mastodon/features/ui/components/columns_area.js b/app/javascript/mastodon/features/ui/components/columns_area.js index 6837450eb58..85a92fc3a90 100644 --- a/app/javascript/mastodon/features/ui/components/columns_area.js +++ b/app/javascript/mastodon/features/ui/components/columns_area.js @@ -70,8 +70,12 @@ class ColumnsArea extends ImmutablePureComponent { children: PropTypes.node, }; + // Corresponds to (max-width: 600px + (285px * 1) + (10px * 1)) in SCSS + mediaQuery = 'matchMedia' in window && window.matchMedia('(max-width: 895px)'); + state = { shouldAnimate: false, + renderComposePanel: !(this.mediaQuery && this.mediaQuery.matches), } componentWillReceiveProps() { @@ -85,6 +89,11 @@ class ColumnsArea extends ImmutablePureComponent { this.node.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : false); } + if (this.mediaQuery) { + this.mediaQuery.addEventListener('change', this.handleLayoutChange); + this.setState({ renderComposePanel: !this.mediaQuery.matches }); + } + this.lastIndex = getIndex(this.context.router.history.location.pathname); this.isRtlLayout = document.getElementsByTagName('body')[0].classList.contains('rtl'); @@ -114,6 +123,10 @@ class ColumnsArea extends ImmutablePureComponent { if (!this.props.singleColumn) { this.node.removeEventListener('wheel', this.handleWheel); } + + if (this.mediaQuery) { + this.mediaQuery.removeEventListener('change', this.handleLayoutChange); + } } handleChildrenContentChange() { @@ -123,6 +136,10 @@ class ColumnsArea extends ImmutablePureComponent { } } + handleLayoutChange = (e) => { + this.setState({ renderComposePanel: !e.matches }); + } + handleSwipe = (index) => { this.pendingIndex = index; @@ -186,7 +203,7 @@ class ColumnsArea extends ImmutablePureComponent { render () { const { columns, children, singleColumn, isModalOpen, intl } = this.props; - const { shouldAnimate } = this.state; + const { shouldAnimate, renderComposePanel } = this.state; const columnIndex = getIndex(this.context.router.history.location.pathname); @@ -205,7 +222,7 @@ class ColumnsArea extends ImmutablePureComponent {
- + {renderComposePanel && }
From 1c4dee4554fdf0658c370dd7d4edfc49fd0494f7 Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 24 Mar 2021 10:19:40 +0100 Subject: [PATCH 20/27] Fix Mastodon not understanding as:Public and Public (#15948) Fixes #5551 --- app/lib/activitypub/activity/announce.rb | 4 +- app/lib/activitypub/activity/create.rb | 6 +- app/lib/activitypub/tag_manager.rb | 4 ++ spec/lib/activitypub/activity/create_spec.rb | 76 +++++++++++++++++++- 4 files changed, 83 insertions(+), 7 deletions(-) diff --git a/app/lib/activitypub/activity/announce.rb b/app/lib/activitypub/activity/announce.rb index 349e8f77e71..ae8b2db754e 100644 --- a/app/lib/activitypub/activity/announce.rb +++ b/app/lib/activitypub/activity/announce.rb @@ -43,9 +43,9 @@ class ActivityPub::Activity::Announce < ActivityPub::Activity end def visibility_from_audience - if audience_to.include?(ActivityPub::TagManager::COLLECTIONS[:public]) + if audience_to.any? { |to| ActivityPub::TagManager.instance.public_collection?(to) } :public - elsif audience_cc.include?(ActivityPub::TagManager::COLLECTIONS[:public]) + elsif audience_cc.any? { |cc| ActivityPub::TagManager.instance.public_collection?(cc) } :unlisted elsif audience_to.include?(@account.followers_url) :private diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 6127446763d..0fa306cddd0 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -123,7 +123,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity def process_audience (audience_to + audience_cc).uniq.each do |audience| - next if audience == ActivityPub::TagManager::COLLECTIONS[:public] + next if ActivityPub::TagManager.instance.public_collection?(audience) # Unlike with tags, there is no point in resolving accounts we don't already # know here, because silent mentions would only be used for local access @@ -356,9 +356,9 @@ class ActivityPub::Activity::Create < ActivityPub::Activity end def visibility_from_audience - if audience_to.include?(ActivityPub::TagManager::COLLECTIONS[:public]) + if audience_to.any? { |to| ActivityPub::TagManager.instance.public_collection?(to) } :public - elsif audience_cc.include?(ActivityPub::TagManager::COLLECTIONS[:public]) + elsif audience_cc.any? { |cc| ActivityPub::TagManager.instance.public_collection?(cc) } :unlisted elsif audience_to.include?(@account.followers_url) :private diff --git a/app/lib/activitypub/tag_manager.rb b/app/lib/activitypub/tag_manager.rb index 3f2ae1106b6..f6b5e10d39e 100644 --- a/app/lib/activitypub/tag_manager.rb +++ b/app/lib/activitypub/tag_manager.rb @@ -12,6 +12,10 @@ class ActivityPub::TagManager public: 'https://www.w3.org/ns/activitystreams#Public', }.freeze + def public_collection?(uri) + uri == COLLECTIONS[:public] || uri == 'as:Public' || uri == 'Public' + end + def url_for(target) return target.url if target.respond_to?(:local?) && !target.local? diff --git a/spec/lib/activitypub/activity/create_spec.rb b/spec/lib/activitypub/activity/create_spec.rb index d2e9fe33ce4..2703c18f39a 100644 --- a/spec/lib/activitypub/activity/create_spec.rb +++ b/spec/lib/activitypub/activity/create_spec.rb @@ -67,7 +67,7 @@ RSpec.describe ActivityPub::Activity::Create do end end - context 'public' do + context 'public with explicit public address' do let(:object_json) do { id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join, @@ -85,7 +85,43 @@ RSpec.describe ActivityPub::Activity::Create do end end - context 'unlisted' do + context 'public with as:Public' do + let(:object_json) do + { + id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join, + type: 'Note', + content: 'Lorem ipsum', + to: 'as:Public', + } + end + + it 'creates status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.visibility).to eq 'public' + end + end + + context 'public with Public' do + let(:object_json) do + { + id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join, + type: 'Note', + content: 'Lorem ipsum', + to: 'Public', + } + end + + it 'creates status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.visibility).to eq 'public' + end + end + + context 'unlisted with explicit public address' do let(:object_json) do { id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join, @@ -103,6 +139,42 @@ RSpec.describe ActivityPub::Activity::Create do end end + context 'unlisted with as:Public' do + let(:object_json) do + { + id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join, + type: 'Note', + content: 'Lorem ipsum', + cc: 'as:Public', + } + end + + it 'creates status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.visibility).to eq 'unlisted' + end + end + + context 'unlisted with Public' do + let(:object_json) do + { + id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join, + type: 'Note', + content: 'Lorem ipsum', + cc: 'Public', + } + end + + it 'creates status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.visibility).to eq 'unlisted' + end + end + context 'private' do let(:object_json) do { From 82556834cf816030eac0d3f962028cb8dafac2aa Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 24 Mar 2021 10:37:24 +0100 Subject: [PATCH 21/27] Change mastodon:setup to not call assets:precompile in docker (#13942) It appears assets are built during image build, and they shouldn't need to be rebuilt, since we now have reproducible builds. --- lib/tasks/mastodon.rake | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/lib/tasks/mastodon.rake b/lib/tasks/mastodon.rake index 2ad1e778ba3..72bacb5eb25 100644 --- a/lib/tasks/mastodon.rake +++ b/lib/tasks/mastodon.rake @@ -371,18 +371,20 @@ namespace :mastodon do end end - prompt.say "\n" - prompt.say 'The final step is compiling CSS/JS assets.' - prompt.say 'This may take a while and consume a lot of RAM.' + unless using_docker + prompt.say "\n" + prompt.say 'The final step is compiling CSS/JS assets.' + prompt.say 'This may take a while and consume a lot of RAM.' - if prompt.yes?('Compile the assets now?') - prompt.say 'Running `RAILS_ENV=production rails assets:precompile` ...' - prompt.say "\n\n" + if prompt.yes?('Compile the assets now?') + prompt.say 'Running `RAILS_ENV=production rails assets:precompile` ...' + prompt.say "\n\n" - if !system(env.transform_values(&:to_s).merge({ 'RAILS_ENV' => 'production' }), 'rails assets:precompile') - prompt.error 'That failed! Maybe you need swap space?' - else - prompt.say 'Done!' + if !system(env.transform_values(&:to_s).merge({ 'RAILS_ENV' => 'production' }), 'rails assets:precompile') + prompt.error 'That failed! Maybe you need swap space?' + else + prompt.say 'Done!' + end end end From cbd0ee1d07c0d48e4ed14bd446cd23d334e76da8 Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 24 Mar 2021 10:44:31 +0100 Subject: [PATCH 22/27] Update Mastodon to Rails 6.1 (#15910) * Update devise-two-factor to unreleased fork for Rails 6 support Update tests to match new `rotp` version. * Update nsa gem to unreleased fork for Rails 6 support * Update rails to 6.1.3 and rails-i18n to 6.0 * Update to unreleased fork of pluck_each for Ruby 6 support * Run "rails app:update" * Add missing ActiveStorage config file * Use config.ssl_options instead of removed ApplicationController#force_ssl Disabled force_ssl-related tests as they do not seem to be easily testable anymore. * Fix nonce directives by removing Rails 5 specific monkey-patching * Fix fixture_file_upload deprecation warning * Fix yield-based test failing with Rails 6 * Use Rails 6's index_with when possible * Use ActiveRecord::Cache::Store#delete_multi from Rails 6 This will yield better performances when deleting an account * Disable Rails 6.1's automatic preload link headers Since Rails 6.1, ActionView adds preload links for javascript files in the Links header per default. In our case, that will bloat headers too much and potentially cause issues with reverse proxies. Furhermore, we don't need those links, as we already output them as HTML link tags. * Switch to Rails 6.0 default config * Switch to Rails 6.1 default config * Do not include autoload paths in the load path --- Gemfile | 10 +- Gemfile.lock | 181 +++++++++++------- app/controllers/application_controller.rb | 6 - app/lib/delivery_failure_tracker.rb | 2 +- app/lib/feed_manager.rb | 12 +- app/lib/settings/scoped_settings.rb | 2 +- app/models/concerns/account_interactions.rb | 2 +- app/models/report.rb | 2 +- app/services/delete_account_service.rb | 3 +- app/services/import_service.rb | 4 +- bin/setup | 16 +- bin/yarn | 12 +- config/application.rb | 3 +- config/environments/production.rb | 7 + .../application_controller_renderer.rb | 10 +- config/initializers/backtrace_silencers.rb | 7 +- .../initializers/content_security_policy.rb | 12 +- config/initializers/permissions_policy.rb | 11 ++ config/initializers/preload_link_headers.rb | 8 + config/storage.yml | 0 lib/tasks/emojis.rake | 2 +- .../accounts/credentials_controller_spec.rb | 4 +- .../api/v1/media_controller_spec.rb | 10 +- .../application_controller_spec.rb | 14 -- .../settings/imports_controller_spec.rb | 4 +- .../settings/profiles_controller_spec.rb | 4 +- .../confirmations_controller_spec.rb | 2 +- spec/models/setting_spec.rb | 11 +- spec/models/user_spec.rb | 2 +- 29 files changed, 204 insertions(+), 159 deletions(-) create mode 100644 config/initializers/permissions_policy.rb create mode 100644 config/initializers/preload_link_headers.rb create mode 100644 config/storage.yml diff --git a/Gemfile b/Gemfile index 98af92deff4..0b2fdf1560d 100644 --- a/Gemfile +++ b/Gemfile @@ -6,7 +6,7 @@ ruby '>= 2.5.0', '< 3.0.0' gem 'pkg-config', '~> 1.4' gem 'puma', '~> 5.2' -gem 'rails', '~> 5.2.4.5' +gem 'rails', '~> 6.1.3' gem 'sprockets', '~> 3.7.2' gem 'thor', '~> 1.1' gem 'rack', '~> 2.2.3' @@ -34,7 +34,7 @@ gem 'iso-639' gem 'chewy', '~> 5.2' gem 'cld3', '~> 3.4.1' gem 'devise', '~> 4.7' -gem 'devise-two-factor', '~> 3.1' +gem 'devise-two-factor', git: 'https://github.com/ClearlyClaire/devise-two-factor', ref: '594bb8a32e6f94df7e5ba7c9399eaf9ff25bac0d' group :pam_authentication, optional: true do gem 'devise_pam_authenticatable2', '~> 9.2' @@ -65,7 +65,7 @@ gem 'link_header', '~> 0.0' gem 'mime-types', '~> 3.3.1', require: 'mime/types/columnar' gem 'nilsimsa', git: 'https://github.com/witgo/nilsimsa', ref: 'fd184883048b922b176939f851338d0a4971a532' gem 'nokogiri', '~> 1.11' -gem 'nsa', '~> 0.2' +gem 'nsa', git: 'https://github.com/Gargron/nsa', ref: 'd1079e0cdafdfed7f9f35478d13b9bdaa65965c0' gem 'oj', '~> 3.11' gem 'ox', '~> 2.14' gem 'parslet' @@ -75,7 +75,7 @@ gem 'pundit', '~> 2.1' gem 'premailer-rails' gem 'rack-attack', '~> 6.5' gem 'rack-cors', '~> 1.1', require: 'rack/cors' -gem 'rails-i18n', '~> 5.1' +gem 'rails-i18n', '~> 6.0' gem 'rails-settings-cached', '~> 0.6' gem 'redis', '~> 4.2', require: ['redis', 'redis/connection/hiredis'] gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock' @@ -159,4 +159,4 @@ gem 'concurrent-ruby', require: false gem 'connection_pool', require: false gem 'xorcist', '~> 1.1' -gem 'pluck_each', '~> 0.1.3' +gem 'pluck_each', git: 'https://github.com/nsommer/pluck_each', ref: '73be0947c52fc54bf6d7085378db008358aac5eb' diff --git a/Gemfile.lock b/Gemfile.lock index 1a67f893d63..1f7183b9d00 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,3 +1,26 @@ +GIT + remote: https://github.com/ClearlyClaire/devise-two-factor + revision: 594bb8a32e6f94df7e5ba7c9399eaf9ff25bac0d + ref: 594bb8a32e6f94df7e5ba7c9399eaf9ff25bac0d + specs: + devise-two-factor (3.1.0) + activesupport (< 7.0) + attr_encrypted (>= 1.3, < 4, != 2) + devise + railties (< 7.0) + rotp (~> 6) + +GIT + remote: https://github.com/Gargron/nsa + revision: d1079e0cdafdfed7f9f35478d13b9bdaa65965c0 + ref: d1079e0cdafdfed7f9f35478d13b9bdaa65965c0 + specs: + nsa (0.2.8) + activesupport (>= 4.2, < 7) + concurrent-ruby (~> 1.0, >= 1.0.2) + sidekiq (>= 3.5) + statsd-ruby (~> 1.4, >= 1.4.0) + GIT remote: https://github.com/ianheggie/health_check revision: 0b799ead604f900ed50685e9b2d469cd2befba5b @@ -6,6 +29,15 @@ GIT health_check (4.0.0.pre) rails (>= 4.0) +GIT + remote: https://github.com/nsommer/pluck_each + revision: 73be0947c52fc54bf6d7085378db008358aac5eb + ref: 73be0947c52fc54bf6d7085378db008358aac5eb + specs: + pluck_each (0.1.3) + activerecord (>= 6.1.0) + activesupport (>= 6.1.0) + GIT remote: https://github.com/witgo/nilsimsa revision: fd184883048b922b176939f851338d0a4971a532 @@ -16,53 +48,71 @@ GIT GEM remote: https://rubygems.org/ specs: - actioncable (5.2.4.5) - actionpack (= 5.2.4.5) + actioncable (6.1.3) + actionpack (= 6.1.3) + activesupport (= 6.1.3) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailer (5.2.4.5) - actionpack (= 5.2.4.5) - actionview (= 5.2.4.5) - activejob (= 5.2.4.5) + actionmailbox (6.1.3) + actionpack (= 6.1.3) + activejob (= 6.1.3) + activerecord (= 6.1.3) + activestorage (= 6.1.3) + activesupport (= 6.1.3) + mail (>= 2.7.1) + actionmailer (6.1.3) + actionpack (= 6.1.3) + actionview (= 6.1.3) + activejob (= 6.1.3) + activesupport (= 6.1.3) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (5.2.4.5) - actionview (= 5.2.4.5) - activesupport (= 5.2.4.5) - rack (~> 2.0, >= 2.0.8) + actionpack (6.1.3) + actionview (= 6.1.3) + activesupport (= 6.1.3) + rack (~> 2.0, >= 2.0.9) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.2.4.5) - activesupport (= 5.2.4.5) + rails-html-sanitizer (~> 1.0, >= 1.2.0) + actiontext (6.1.3) + actionpack (= 6.1.3) + activerecord (= 6.1.3) + activestorage (= 6.1.3) + activesupport (= 6.1.3) + nokogiri (>= 1.8.5) + actionview (6.1.3) + activesupport (= 6.1.3) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.0.3) + rails-html-sanitizer (~> 1.1, >= 1.2.0) active_model_serializers (0.10.12) actionpack (>= 4.1, < 6.2) activemodel (>= 4.1, < 6.2) case_transform (>= 0.2) jsonapi-renderer (>= 0.1.1.beta1, < 0.3) active_record_query_trace (1.8) - activejob (5.2.4.5) - activesupport (= 5.2.4.5) + activejob (6.1.3) + activesupport (= 6.1.3) globalid (>= 0.3.6) - activemodel (5.2.4.5) - activesupport (= 5.2.4.5) - activerecord (5.2.4.5) - activemodel (= 5.2.4.5) - activesupport (= 5.2.4.5) - arel (>= 9.0) - activestorage (5.2.4.5) - actionpack (= 5.2.4.5) - activerecord (= 5.2.4.5) + activemodel (6.1.3) + activesupport (= 6.1.3) + activerecord (6.1.3) + activemodel (= 6.1.3) + activesupport (= 6.1.3) + activestorage (6.1.3) + actionpack (= 6.1.3) + activejob (= 6.1.3) + activerecord (= 6.1.3) + activesupport (= 6.1.3) marcel (~> 0.3.1) - activesupport (5.2.4.5) + mimemagic (~> 0.3.2) + activesupport (6.1.3) concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + zeitwerk (~> 2.3) addressable (2.7.0) public_suffix (>= 2.0.2, < 5.0) airbrussh (1.4.0) @@ -71,7 +121,6 @@ GEM annotate (3.1.1) activerecord (>= 3.2, < 7.0) rake (>= 10.4, < 14.0) - arel (9.0.0) ast (2.4.2) attr_encrypted (3.1.0) encryptor (~> 3.0.0) @@ -175,12 +224,6 @@ GEM railties (>= 4.1.0) responders warden (~> 1.2.3) - devise-two-factor (3.1.0) - activesupport (< 6.1) - attr_encrypted (>= 1.3, < 4, != 2) - devise (~> 4.0) - railties (< 6.1) - rotp (~> 2.0) devise_pam_authenticatable2 (9.2.0) devise (>= 4.0.0) rpam2 (~> 4.0) @@ -370,11 +413,6 @@ GEM racc (~> 1.4) nokogumbo (2.0.4) nokogiri (~> 1.8, >= 1.8.4) - nsa (0.2.7) - activesupport (>= 4.2, < 6) - concurrent-ruby (~> 1.0, >= 1.0.2) - sidekiq (>= 3.5) - statsd-ruby (~> 1.4, >= 1.4.0) oj (3.11.3) omniauth (1.9.1) hashie (>= 3.4.6) @@ -414,9 +452,6 @@ GEM pghero (2.8.0) activerecord (>= 5) pkg-config (1.4.5) - pluck_each (0.1.3) - activerecord (> 3.2.0) - activesupport (> 3.0.0) posix-spawn (0.3.15) premailer (1.14.2) addressable @@ -450,18 +485,20 @@ GEM rack rack-test (1.1.0) rack (>= 1.0, < 3) - rails (5.2.4.5) - actioncable (= 5.2.4.5) - actionmailer (= 5.2.4.5) - actionpack (= 5.2.4.5) - actionview (= 5.2.4.5) - activejob (= 5.2.4.5) - activemodel (= 5.2.4.5) - activerecord (= 5.2.4.5) - activestorage (= 5.2.4.5) - activesupport (= 5.2.4.5) - bundler (>= 1.3.0) - railties (= 5.2.4.5) + rails (6.1.3) + actioncable (= 6.1.3) + actionmailbox (= 6.1.3) + actionmailer (= 6.1.3) + actionpack (= 6.1.3) + actiontext (= 6.1.3) + actionview (= 6.1.3) + activejob (= 6.1.3) + activemodel (= 6.1.3) + activerecord (= 6.1.3) + activestorage (= 6.1.3) + activesupport (= 6.1.3) + bundler (>= 1.15.0) + railties (= 6.1.3) sprockets-rails (>= 2.0.0) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) @@ -472,17 +509,17 @@ GEM nokogiri (>= 1.6) rails-html-sanitizer (1.3.0) loofah (~> 2.3) - rails-i18n (5.1.3) + rails-i18n (6.0.0) i18n (>= 0.7, < 2) - railties (>= 5.0, < 6) + railties (>= 6.0.0, < 7) rails-settings-cached (0.6.6) rails (>= 4.2.0) - railties (5.2.4.5) - actionpack (= 5.2.4.5) - activesupport (= 5.2.4.5) + railties (6.1.3) + actionpack (= 6.1.3) + activesupport (= 6.1.3) method_source rake (>= 0.8.7) - thor (>= 0.19.0, < 2.0) + thor (~> 1.0) rainbow (3.0.0) rake (13.0.3) rdf (3.1.13) @@ -500,7 +537,7 @@ GEM actionpack (>= 5.0) railties (>= 5.0) rexml (3.2.4) - rotp (2.1.2) + rotp (6.2.0) rpam2 (4.0.2) rqrcode (1.2.0) chunky_png (~> 1.0) @@ -600,7 +637,7 @@ GEM net-scp (>= 1.1.2) net-ssh (>= 2.8.0) stackprof (0.2.16) - statsd-ruby (1.4.0) + statsd-ruby (1.5.0) stoplight (2.2.1) streamio-ffmpeg (3.0.2) multi_json (~> 1.8) @@ -612,7 +649,6 @@ GEM terrapin (0.6.0) climate_control (>= 0.0.3, < 1.0) thor (1.1.0) - thread_safe (0.3.6) thwait (0.2.0) e2mmap tilt (2.0.10) @@ -632,8 +668,8 @@ GEM twitter-text (3.1.0) idn-ruby unf (~> 0.1.0) - tzinfo (1.2.9) - thread_safe (~> 0.1) + tzinfo (2.0.4) + concurrent-ruby (~> 1.0) tzinfo-data (1.2021.1) tzinfo (>= 1.0.0) unf (0.1.4) @@ -672,6 +708,7 @@ GEM xorcist (1.1.2) xpath (3.2.0) nokogiri (~> 1.8) + zeitwerk (2.4.2) PLATFORMS ruby @@ -703,7 +740,7 @@ DEPENDENCIES concurrent-ruby connection_pool devise (~> 4.7) - devise-two-factor (~> 3.1) + devise-two-factor! devise_pam_authenticatable2 (~> 9.2) discard (~> 1.2) doorkeeper (~> 5.5) @@ -741,7 +778,7 @@ DEPENDENCIES net-ldap (~> 0.17) nilsimsa! nokogiri (~> 1.11) - nsa (~> 0.2) + nsa! oj (~> 3.11) omniauth (~> 1.9) omniauth-cas (~> 2.0) @@ -756,7 +793,7 @@ DEPENDENCIES pg (~> 1.2) pghero (~> 2.8) pkg-config (~> 1.4) - pluck_each (~> 0.1.3) + pluck_each! posix-spawn premailer-rails private_address_check (~> 0.5) @@ -767,9 +804,9 @@ DEPENDENCIES rack (~> 2.2.3) rack-attack (~> 6.5) rack-cors (~> 1.1) - rails (~> 5.2.4.5) + rails (~> 6.1.3) rails-controller-testing (~> 1.0) - rails-i18n (~> 5.1) + rails-i18n (~> 6.0) rails-settings-cached (~> 0.6) rdf-normalize (~> 0.4) redis (~> 4.2) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 5b7eec94f75..6361d4b276f 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -5,8 +5,6 @@ class ApplicationController < ActionController::Base # For APIs, you may want to use :null_session instead. protect_from_forgery with: :exception - force_ssl if: :https_enabled? - include Localized include UserTrackingConcern include SessionTrackingConcern @@ -42,10 +40,6 @@ class ApplicationController < ActionController::Base private - def https_enabled? - Rails.env.production? && !request.path.start_with?('/health') && !request.headers["Host"].end_with?(".onion") - end - def authorized_fetch_mode? ENV['AUTHORIZED_FETCH'] == 'true' || Rails.configuration.x.whitelist_mode end diff --git a/app/lib/delivery_failure_tracker.rb b/app/lib/delivery_failure_tracker.rb index 25fa694d22f..2cd6ef7adf8 100644 --- a/app/lib/delivery_failure_tracker.rb +++ b/app/lib/delivery_failure_tracker.rb @@ -29,7 +29,7 @@ class DeliveryFailureTracker class << self def without_unavailable(urls) - unavailable_domains_map = Rails.cache.fetch('unavailable_domains') { UnavailableDomain.pluck(:domain).each_with_object({}) { |domain, hash| hash[domain] = true } } + unavailable_domains_map = Rails.cache.fetch('unavailable_domains') { UnavailableDomain.pluck(:domain).index_with(true) } urls.reject do |url| host = Addressable::URI.parse(url).normalized_host diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb index 165338437bc..43aeecb3531 100644 --- a/app/lib/feed_manager.rb +++ b/app/lib/feed_manager.rb @@ -533,12 +533,12 @@ class FeedManager arr end - crutches[:following] = Follow.where(account_id: receiver_id, target_account_id: statuses.map(&:in_reply_to_account_id).compact).pluck(:target_account_id).each_with_object({}) { |id, mapping| mapping[id] = true } - crutches[:hiding_reblogs] = Follow.where(account_id: receiver_id, target_account_id: statuses.map { |s| s.account_id if s.reblog? }.compact, show_reblogs: false).pluck(:target_account_id).each_with_object({}) { |id, mapping| mapping[id] = true } - crutches[:blocking] = Block.where(account_id: receiver_id, target_account_id: check_for_blocks).pluck(:target_account_id).each_with_object({}) { |id, mapping| mapping[id] = true } - crutches[:muting] = Mute.where(account_id: receiver_id, target_account_id: check_for_blocks).pluck(:target_account_id).each_with_object({}) { |id, mapping| mapping[id] = true } - crutches[:domain_blocking] = AccountDomainBlock.where(account_id: receiver_id, domain: statuses.map { |s| s.reblog&.account&.domain }.compact).pluck(:domain).each_with_object({}) { |domain, mapping| mapping[domain] = true } - crutches[:blocked_by] = Block.where(target_account_id: receiver_id, account_id: statuses.map { |s| s.reblog&.account_id }.compact).pluck(:account_id).each_with_object({}) { |id, mapping| mapping[id] = true } + crutches[:following] = Follow.where(account_id: receiver_id, target_account_id: statuses.map(&:in_reply_to_account_id).compact).pluck(:target_account_id).index_with(true) + crutches[:hiding_reblogs] = Follow.where(account_id: receiver_id, target_account_id: statuses.map { |s| s.account_id if s.reblog? }.compact, show_reblogs: false).pluck(:target_account_id).index_with(true) + crutches[:blocking] = Block.where(account_id: receiver_id, target_account_id: check_for_blocks).pluck(:target_account_id).index_with(true) + crutches[:muting] = Mute.where(account_id: receiver_id, target_account_id: check_for_blocks).pluck(:target_account_id).index_with(true) + crutches[:domain_blocking] = AccountDomainBlock.where(account_id: receiver_id, domain: statuses.map { |s| s.reblog&.account&.domain }.compact).pluck(:domain).index_with(true) + crutches[:blocked_by] = Block.where(target_account_id: receiver_id, account_id: statuses.map { |s| s.reblog&.account_id }.compact).pluck(:account_id).index_with(true) crutches end diff --git a/app/lib/settings/scoped_settings.rb b/app/lib/settings/scoped_settings.rb index acabf0c8e05..1e18d6d463d 100644 --- a/app/lib/settings/scoped_settings.rb +++ b/app/lib/settings/scoped_settings.rb @@ -63,7 +63,7 @@ module Settings class << self def default_settings - defaulting = DEFAULTING_TO_UNSCOPED.each_with_object({}) { |k, h| h[k] = Setting[k] } + defaulting = DEFAULTING_TO_UNSCOPED.index_with { |k| Setting[k] } Setting.default_settings.merge!(defaulting) end end diff --git a/app/models/concerns/account_interactions.rb b/app/models/concerns/account_interactions.rb index 974f57820d0..51e8e04a80d 100644 --- a/app/models/concerns/account_interactions.rb +++ b/app/models/concerns/account_interactions.rb @@ -67,7 +67,7 @@ module AccountInteractions private def follow_mapping(query, field) - query.pluck(field).each_with_object({}) { |id, mapping| mapping[id] = true } + query.pluck(field).index_with(true) end end diff --git a/app/models/report.rb b/app/models/report.rb index cd08120e413..ef41547d99c 100644 --- a/app/models/report.rb +++ b/app/models/report.rb @@ -32,7 +32,7 @@ class Report < ApplicationRecord scope :unresolved, -> { where(action_taken: false) } scope :resolved, -> { where(action_taken: true) } - scope :with_accounts, -> { includes([:account, :target_account, :action_taken_by_account, :assigned_account].each_with_object({}) { |k, h| h[k] = { user: [:invite_request, :invite] } }) } + scope :with_accounts, -> { includes([:account, :target_account, :action_taken_by_account, :assigned_account].index_with({ user: [:invite_request, :invite] })) } validates :comment, length: { maximum: 1000 } diff --git a/app/services/delete_account_service.rb b/app/services/delete_account_service.rb index 802799ccd9b..182f0e1277f 100644 --- a/app/services/delete_account_service.rb +++ b/app/services/delete_account_service.rb @@ -188,8 +188,7 @@ class DeleteAccountService < BaseService ids = favourites.pluck(:status_id) StatusStat.where(status_id: ids).update_all('favourites_count = GREATEST(0, favourites_count - 1)') Chewy.strategy.current.update(StatusesIndex::Status, ids) if Chewy.enabled? - # Rails.cache.delete_multi would be better, but we don't have it yet - ids.each { |id| Rails.cache.delete("statuses/#{id}") } + Rails.cache.delete_multi(ids.map { |id| "statuses/#{id}" }) favourites.delete_all end end diff --git a/app/services/import_service.rb b/app/services/import_service.rb index b115322831b..74ad5b79f42 100644 --- a/app/services/import_service.rb +++ b/app/services/import_service.rb @@ -45,7 +45,7 @@ class ImportService < BaseService items = @data.take(ROWS_PROCESSING_LIMIT).map { |row| row['#domain'].strip } if @import.overwrite? - presence_hash = items.each_with_object({}) { |id, mapping| mapping[id] = true } + presence_hash = items.index_with(true) @account.domain_blocks.find_each do |domain_block| if presence_hash[domain_block.domain] @@ -96,7 +96,7 @@ class ImportService < BaseService items = @data.take(ROWS_PROCESSING_LIMIT).map { |row| row['#uri'].strip } if @import.overwrite? - presence_hash = items.each_with_object({}) { |id, mapping| mapping[id] = true } + presence_hash = items.index_with(true) @account.bookmarks.find_each do |bookmark| if presence_hash[bookmark.status.uri] diff --git a/bin/setup b/bin/setup index fc77b080906..90700ac4f9a 100755 --- a/bin/setup +++ b/bin/setup @@ -1,6 +1,5 @@ #!/usr/bin/env ruby -require 'fileutils' -include FileUtils +require "fileutils" # path to your application root. APP_ROOT = File.expand_path('..', __dir__) @@ -9,22 +8,25 @@ def system!(*args) system(*args) || abort("\n== Command #{args} failed ==") end -chdir APP_ROOT do - # This script is a starting point to setup your application. +FileUtils.chdir APP_ROOT do + # This script is a way to set up or update your development environment automatically. + # This script is idempotent, so that you can run it at any time and get an expectable outcome. # Add necessary setup steps to this file. puts '== Installing dependencies ==' system! 'gem install bundler --conservative' system('bundle check') || system!('bundle install') - system!('yarn install') + + # Install JavaScript dependencies + system! 'bin/yarn' # puts "\n== Copying sample files ==" # unless File.exist?('config/database.yml') - # cp 'config/database.yml.sample', 'config/database.yml' + # FileUtils.cp 'config/database.yml.sample', 'config/database.yml' # end puts "\n== Preparing database ==" - system! 'bin/rails db:setup' + system! 'bin/rails db:prepare' puts "\n== Removing old logs and tempfiles ==" system! 'bin/rails log:clear tmp:clear' diff --git a/bin/yarn b/bin/yarn index 460dd565b4a..9fab2c35079 100755 --- a/bin/yarn +++ b/bin/yarn @@ -1,9 +1,15 @@ #!/usr/bin/env ruby APP_ROOT = File.expand_path('..', __dir__) Dir.chdir(APP_ROOT) do - begin - exec "yarnpkg", *ARGV - rescue Errno::ENOENT + yarn = ENV["PATH"].split(File::PATH_SEPARATOR). + select { |dir| File.expand_path(dir) != __dir__ }. + product(["yarn", "yarn.cmd", "yarn.ps1"]). + map { |dir, file| File.expand_path(file, dir) }. + find { |file| File.executable?(file) } + + if yarn + exec yarn, *ARGV + else $stderr.puts "Yarn executable was not detected in the system." $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install" exit 1 diff --git a/config/application.rb b/config/application.rb index 3267fa71be5..c911e76dcff 100644 --- a/config/application.rb +++ b/config/application.rb @@ -39,7 +39,8 @@ require_relative '../lib/mastodon/redis_config' module Mastodon class Application < Rails::Application # Initialize configuration defaults for originally generated Rails version. - config.load_defaults 5.2 + config.load_defaults 6.1 + config.add_autoload_paths_to_load_path = false # Settings in config/environments/* take precedence over those specified here. # Application configuration should go into files in config/initializers diff --git a/config/environments/production.rb b/config/environments/production.rb index 81a67902ead..6df0a336513 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -44,6 +44,13 @@ Rails.application.configure do # Allow to specify public IP of reverse proxy if it's needed config.action_dispatch.trusted_proxies = ENV['TRUSTED_PROXY_IP'].split.map { |item| IPAddr.new(item) } if ENV['TRUSTED_PROXY_IP'].present? + config.force_ssl = true + config.ssl_options = { + redirect: { + exclude: -> request { request.path.start_with?('/health') || request.headers["Host"].end_with?('.onion') } + } + } + # Use the lowest log level to ensure availability of diagnostic information # when problems arise. config.log_level = ENV.fetch('RAILS_LOG_LEVEL', 'info').to_sym diff --git a/config/initializers/application_controller_renderer.rb b/config/initializers/application_controller_renderer.rb index 51639b67a00..89d2efab2ba 100644 --- a/config/initializers/application_controller_renderer.rb +++ b/config/initializers/application_controller_renderer.rb @@ -1,6 +1,8 @@ # Be sure to restart your server when you modify this file. -# ApplicationController.renderer.defaults.merge!( -# http_host: 'example.org', -# https: false -# ) +# ActiveSupport::Reloader.to_prepare do +# ApplicationController.renderer.defaults.merge!( +# http_host: 'example.org', +# https: false +# ) +# end diff --git a/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb index 59385cdf379..33699c30910 100644 --- a/config/initializers/backtrace_silencers.rb +++ b/config/initializers/backtrace_silencers.rb @@ -1,7 +1,8 @@ # Be sure to restart your server when you modify this file. # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. -# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } +# Rails.backtrace_cleaner.add_silencer { |line| /my_noisy_library/.match?(line) } -# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. -# Rails.backtrace_cleaner.remove_silencers! +# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code +# by setting BACKTRACE=1 before calling your invocation, like "BACKTRACE=1 ./bin/rails runner 'MyClass.perform'". +Rails.backtrace_cleaner.remove_silencers! if ENV["BACKTRACE"] diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb index 98dc711e1b8..92645ff2884 100644 --- a/config/initializers/content_security_policy.rb +++ b/config/initializers/content_security_policy.rb @@ -49,17 +49,7 @@ end Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } -# Monkey-patching Rails 5 -module ActionDispatch - class ContentSecurityPolicy - def nonce_directive?(directive) - directive == 'style-src' - end - end -end - -# Rails 6 would require the following instead: -# Rails.application.config.content_security_policy_nonce_directives = %w(style-src) +Rails.application.config.content_security_policy_nonce_directives = %w(style-src) PgHero::HomeController.content_security_policy do |p| p.script_src :self, :unsafe_inline, assets_host diff --git a/config/initializers/permissions_policy.rb b/config/initializers/permissions_policy.rb new file mode 100644 index 00000000000..00f64d71b03 --- /dev/null +++ b/config/initializers/permissions_policy.rb @@ -0,0 +1,11 @@ +# Define an application-wide HTTP permissions policy. For further +# information see https://developers.google.com/web/updates/2018/06/feature-policy +# +# Rails.application.config.permissions_policy do |f| +# f.camera :none +# f.gyroscope :none +# f.microphone :none +# f.usb :none +# f.fullscreen :self +# f.payment :self, "https://secure.example.com" +# end diff --git a/config/initializers/preload_link_headers.rb b/config/initializers/preload_link_headers.rb new file mode 100644 index 00000000000..9f21c45ecfe --- /dev/null +++ b/config/initializers/preload_link_headers.rb @@ -0,0 +1,8 @@ +# Since Rails 6.1, ActionView adds preload links for javascript files +# in the Links header per default. + +# In our case, that will bloat headers too much and potentially cause +# issues with reverse proxies. Furhermore, we don't need those links, +# as we already output them as HTML link tags. + +Rails.application.config.action_view.preload_links_header = false diff --git a/config/storage.yml b/config/storage.yml new file mode 100644 index 00000000000..e69de29bb2d diff --git a/lib/tasks/emojis.rake b/lib/tasks/emojis.rake index 01ae955643b..c8655cc4785 100644 --- a/lib/tasks/emojis.rake +++ b/lib/tasks/emojis.rake @@ -69,7 +69,7 @@ namespace :emojis do end end - existence_maps = grouped_codes.map { |c| c.map { |cc| [cc, File.exist?(Rails.root.join('public', 'emoji', codepoints_to_filename(cc) + '.svg'))] }.to_h } + existence_maps = grouped_codes.map { |c| c.index_with { |cc| File.exist?(Rails.root.join('public', 'emoji', codepoints_to_filename(cc) + '.svg')) } } map = {} existence_maps.each do |group| diff --git a/spec/controllers/api/v1/accounts/credentials_controller_spec.rb b/spec/controllers/api/v1/accounts/credentials_controller_spec.rb index ebd462a0394..9fb0d877004 100644 --- a/spec/controllers/api/v1/accounts/credentials_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/credentials_controller_spec.rb @@ -30,8 +30,8 @@ describe Api::V1::Accounts::CredentialsController do patch :update, params: { display_name: "Alice Isn't Dead", note: "Hi!\n\nToot toot!", - avatar: fixture_file_upload('files/avatar.gif', 'image/gif'), - header: fixture_file_upload('files/attachment.jpg', 'image/jpeg'), + avatar: fixture_file_upload('avatar.gif', 'image/gif'), + header: fixture_file_upload('attachment.jpg', 'image/jpeg'), source: { privacy: 'unlisted', sensitive: true, diff --git a/spec/controllers/api/v1/media_controller_spec.rb b/spec/controllers/api/v1/media_controller_spec.rb index 4e303720843..3eb015a1ca4 100644 --- a/spec/controllers/api/v1/media_controller_spec.rb +++ b/spec/controllers/api/v1/media_controller_spec.rb @@ -15,7 +15,7 @@ RSpec.describe Api::V1::MediaController, type: :controller do context 'when imagemagick cant identify the file type' do before do expect_any_instance_of(Account).to receive_message_chain(:media_attachments, :create!).and_raise(Paperclip::Errors::NotIdentifiedByImageMagickError) - post :create, params: { file: fixture_file_upload('files/attachment.jpg', 'image/jpeg') } + post :create, params: { file: fixture_file_upload('attachment.jpg', 'image/jpeg') } end it 'returns http 422' do @@ -26,7 +26,7 @@ RSpec.describe Api::V1::MediaController, type: :controller do context 'when there is a generic error' do before do expect_any_instance_of(Account).to receive_message_chain(:media_attachments, :create!).and_raise(Paperclip::Error) - post :create, params: { file: fixture_file_upload('files/attachment.jpg', 'image/jpeg') } + post :create, params: { file: fixture_file_upload('attachment.jpg', 'image/jpeg') } end it 'returns http 422' do @@ -37,7 +37,7 @@ RSpec.describe Api::V1::MediaController, type: :controller do context 'image/jpeg' do before do - post :create, params: { file: fixture_file_upload('files/attachment.jpg', 'image/jpeg') } + post :create, params: { file: fixture_file_upload('attachment.jpg', 'image/jpeg') } end it 'returns http success' do @@ -59,7 +59,7 @@ RSpec.describe Api::V1::MediaController, type: :controller do context 'image/gif' do before do - post :create, params: { file: fixture_file_upload('files/attachment.gif', 'image/gif') } + post :create, params: { file: fixture_file_upload('attachment.gif', 'image/gif') } end it 'returns http success' do @@ -81,7 +81,7 @@ RSpec.describe Api::V1::MediaController, type: :controller do context 'video/webm' do before do - post :create, params: { file: fixture_file_upload('files/attachment.webm', 'video/webm') } + post :create, params: { file: fixture_file_upload('attachment.webm', 'video/webm') } end it do diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index e73a08a0e99..458298a6b9e 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -42,20 +42,6 @@ describe ApplicationController, type: :controller do include_examples 'respond_with_error', 422 end - it "does not force ssl if Rails.env.production? is not 'true'" do - routes.draw { get 'success' => 'anonymous#success' } - allow(Rails.env).to receive(:production?).and_return(false) - get 'success' - expect(response).to have_http_status(200) - end - - it "forces ssl if Rails.env.production? is 'true'" do - routes.draw { get 'success' => 'anonymous#success' } - allow(Rails.env).to receive(:production?).and_return(true) - get 'success' - expect(response).to redirect_to('https://test.host/success') - end - describe 'helper_method :current_account' do it 'returns nil if not signed in' do expect(controller.view_context.current_account).to be_nil diff --git a/spec/controllers/settings/imports_controller_spec.rb b/spec/controllers/settings/imports_controller_spec.rb index 7a9b021957f..b8caf59413a 100644 --- a/spec/controllers/settings/imports_controller_spec.rb +++ b/spec/controllers/settings/imports_controller_spec.rb @@ -21,7 +21,7 @@ RSpec.describe Settings::ImportsController, type: :controller do post :create, params: { import: { type: 'following', - data: fixture_file_upload('files/imports.txt') + data: fixture_file_upload('imports.txt') } } @@ -34,7 +34,7 @@ RSpec.describe Settings::ImportsController, type: :controller do post :create, params: { import: { type: 'blocking', - data: fixture_file_upload('files/imports.txt') + data: fixture_file_upload('imports.txt') } } diff --git a/spec/controllers/settings/profiles_controller_spec.rb b/spec/controllers/settings/profiles_controller_spec.rb index 5b1fe3acad6..1ac286254f3 100644 --- a/spec/controllers/settings/profiles_controller_spec.rb +++ b/spec/controllers/settings/profiles_controller_spec.rb @@ -33,7 +33,7 @@ RSpec.describe Settings::ProfilesController, type: :controller do account = Fabricate(:account, user: @user, display_name: 'AvatarTest') expect(account.avatar.instance.avatar_file_name).to be_nil - put :update, params: { account: { avatar: fixture_file_upload('files/avatar.gif', 'image/gif') } } + put :update, params: { account: { avatar: fixture_file_upload('avatar.gif', 'image/gif') } } expect(response).to redirect_to(settings_profile_path) expect(account.reload.avatar.instance.avatar_file_name).not_to be_nil expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_async).with(account.id) @@ -44,7 +44,7 @@ RSpec.describe Settings::ProfilesController, type: :controller do it 'gives the user an error message' do allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_async) account = Fabricate(:account, user: @user, display_name: 'AvatarTest') - put :update, params: { account: { avatar: fixture_file_upload('files/4096x4097.png', 'image/png') } } + put :update, params: { account: { avatar: fixture_file_upload('4096x4097.png', 'image/png') } } expect(response.body).to include('images are not supported') end end diff --git a/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb b/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb index cdfeef8d6a7..7b86513bef6 100644 --- a/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb +++ b/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb @@ -11,7 +11,7 @@ describe Settings::TwoFactorAuthentication::ConfirmationsController do subject expect(assigns(:confirmation)).to be_instance_of Form::TwoFactorConfirmation - expect(assigns(:provision_url)).to eq 'otpauth://totp/local-part@domain?secret=thisisasecretforthespecofnewview&issuer=cb6e6126.ngrok.io' + expect(assigns(:provision_url)).to eq 'otpauth://totp/cb6e6126.ngrok.io:local-part%40domain?secret=thisisasecretforthespecofnewview&issuer=cb6e6126.ngrok.io' expect(assigns(:qrcode)).to be_instance_of RQRCode::QRCode expect(response).to have_http_status(200) expect(response).to render_template(:new) diff --git a/spec/models/setting_spec.rb b/spec/models/setting_spec.rb index 1cc5286748a..3ccc21d6c41 100644 --- a/spec/models/setting_spec.rb +++ b/spec/models/setting_spec.rb @@ -99,11 +99,12 @@ RSpec.describe Setting, type: :model do end it 'does not query the database' do - expect do |callback| - ActiveSupport::Notifications.subscribed callback, 'sql.active_record' do - described_class[key] - end - end.not_to yield_control + callback = double + allow(callback).to receive(:call) + ActiveSupport::Notifications.subscribed callback, 'sql.active_record' do + described_class[key] + end + expect(callback).not_to have_received(:call) end it 'returns the cached value' do diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 1dae4353608..5db249be2a9 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -175,7 +175,7 @@ RSpec.describe User, type: :model do user = Fabricate(:user) ActiveJob::Base.queue_adapter = :test - expect { user.send_confirmation_instructions }.to have_enqueued_job(ActionMailer::DeliveryJob) + expect { user.send_confirmation_instructions }.to have_enqueued_job(ActionMailer::MailDeliveryJob) end end From 297a3cf904f3d95ceaed64b57713997b2b285f87 Mon Sep 17 00:00:00 2001 From: Yurii Izorkin Date: Wed, 24 Mar 2021 12:46:13 +0300 Subject: [PATCH 23/27] templates/systemd/mastodon: enable sandbox mode (#15937) --- dist/mastodon-sidekiq.service | 27 +++++++++++++++++++++++++++ dist/mastodon-streaming.service | 27 +++++++++++++++++++++++++++ dist/mastodon-web.service | 27 +++++++++++++++++++++++++++ 3 files changed, 81 insertions(+) diff --git a/dist/mastodon-sidekiq.service b/dist/mastodon-sidekiq.service index 721a8660902..0bb0a800fe2 100644 --- a/dist/mastodon-sidekiq.service +++ b/dist/mastodon-sidekiq.service @@ -12,6 +12,33 @@ Environment="MALLOC_ARENA_MAX=2" ExecStart=/home/mastodon/.rbenv/shims/bundle exec sidekiq -c 25 TimeoutSec=15 Restart=always +# Capabilities +CapabilityBoundingSet= +# Security +NoNewPrivileges=true +# Sandboxing +ProtectSystem=strict +PrivateTmp=true +PrivateDevices=true +PrivateUsers=true +ProtectHostname=true +ProtectKernelLogs=true +ProtectKernelModules=true +ProtectKernelTunables=true +ProtectControlGroups=true +RestrictAddressFamilies=AF_INET +RestrictAddressFamilies=AF_INET6 +RestrictAddressFamilies=AF_NETLINK +RestrictAddressFamilies=AF_UNIX +RestrictNamespaces=true +LockPersonality=true +RestrictRealtime=true +RestrictSUIDSGID=true +PrivateMounts=true +ProtectClock=true +# System Call Filtering +SystemCallArchitectures=native +SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @reboot @resources @setuid @swap [Install] WantedBy=multi-user.target diff --git a/dist/mastodon-streaming.service b/dist/mastodon-streaming.service index c324fccf467..1443ca1c885 100644 --- a/dist/mastodon-streaming.service +++ b/dist/mastodon-streaming.service @@ -12,6 +12,33 @@ Environment="STREAMING_CLUSTER_NUM=1" ExecStart=/usr/bin/node ./streaming TimeoutSec=15 Restart=always +# Capabilities +CapabilityBoundingSet= +# Security +NoNewPrivileges=true +# Sandboxing +ProtectSystem=strict +PrivateTmp=true +PrivateDevices=true +PrivateUsers=true +ProtectHostname=true +ProtectKernelLogs=true +ProtectKernelModules=true +ProtectKernelTunables=true +ProtectControlGroups=true +RestrictAddressFamilies=AF_INET +RestrictAddressFamilies=AF_INET6 +RestrictAddressFamilies=AF_NETLINK +RestrictAddressFamilies=AF_UNIX +RestrictNamespaces=true +LockPersonality=true +RestrictRealtime=true +RestrictSUIDSGID=true +PrivateMounts=true +ProtectClock=true +# System Call Filtering +SystemCallArchitectures=native +SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @reboot @resources @setuid @swap [Install] WantedBy=multi-user.target diff --git a/dist/mastodon-web.service b/dist/mastodon-web.service index 30fcbec1e00..3383f33e3aa 100644 --- a/dist/mastodon-web.service +++ b/dist/mastodon-web.service @@ -12,6 +12,33 @@ ExecStart=/home/mastodon/.rbenv/shims/bundle exec puma -C config/puma.rb ExecReload=/bin/kill -SIGUSR1 $MAINPID TimeoutSec=15 Restart=always +# Capabilities +CapabilityBoundingSet= +# Security +NoNewPrivileges=true +# Sandboxing +ProtectSystem=strict +PrivateTmp=true +PrivateDevices=true +PrivateUsers=true +ProtectHostname=true +ProtectKernelLogs=true +ProtectKernelModules=true +ProtectKernelTunables=true +ProtectControlGroups=true +RestrictAddressFamilies=AF_INET +RestrictAddressFamilies=AF_INET6 +RestrictAddressFamilies=AF_NETLINK +RestrictAddressFamilies=AF_UNIX +RestrictNamespaces=true +LockPersonality=true +RestrictRealtime=true +RestrictSUIDSGID=true +PrivateMounts=true +ProtectClock=true +# System Call Filtering +SystemCallArchitectures=native +SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @reboot @resources @setuid @swap [Install] WantedBy=multi-user.target From 88d69d3261c2f02278d07dc302ff7fc15bd68e8c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Mar 2021 10:53:23 +0100 Subject: [PATCH 24/27] Bump brakeman from 4.10.1 to 5.0.0 (#15656) Bumps [brakeman](https://github.com/presidentbeef/brakeman) from 4.10.1 to 5.0.0. - [Release notes](https://github.com/presidentbeef/brakeman/releases) - [Changelog](https://github.com/presidentbeef/brakeman/blob/main/CHANGES.md) - [Commits](https://github.com/presidentbeef/brakeman/compare/v4.10.1...v5.0.0) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 0b2fdf1560d..4682275a095 100644 --- a/Gemfile +++ b/Gemfile @@ -140,7 +140,7 @@ group :development do gem 'memory_profiler' gem 'rubocop', '~> 1.11', require: false gem 'rubocop-rails', '~> 2.9', require: false - gem 'brakeman', '~> 4.10', require: false + gem 'brakeman', '~> 5.0', require: false gem 'bundler-audit', '~> 0.8', require: false gem 'capistrano', '~> 3.16' diff --git a/Gemfile.lock b/Gemfile.lock index 1f7183b9d00..a62305dc050 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -155,7 +155,7 @@ GEM ffi (~> 1.14) bootsnap (1.6.0) msgpack (~> 1.0) - brakeman (4.10.1) + brakeman (5.0.0) browser (4.2.0) brpoplpush-redis_script (0.1.2) concurrent-ruby (~> 1.0, >= 1.0.5) @@ -723,7 +723,7 @@ DEPENDENCIES binding_of_caller (~> 1.0) blurhash (~> 0.1) bootsnap (~> 1.6.0) - brakeman (~> 4.10) + brakeman (~> 5.0) browser bullet (~> 6.1) bundler-audit (~> 0.8) From 9541605024d11a93ef6722477f8443a13511ec3b Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 19 Mar 2021 14:31:10 +0100 Subject: [PATCH 25/27] Fix ActiveRecord monkey-patching migration hack --- config/initializers/0_duplicate_migrations.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/initializers/0_duplicate_migrations.rb b/config/initializers/0_duplicate_migrations.rb index 194aff70cb0..6c45e4bd23e 100644 --- a/config/initializers/0_duplicate_migrations.rb +++ b/config/initializers/0_duplicate_migrations.rb @@ -16,7 +16,7 @@ ALLOWED_DUPLICATES = [20180410220657, 20180831171112].freeze module ActiveRecord class Migrator - def self.new(direction, migrations, target_version = nil) + def self.new(direction, migrations, schema_migration, target_version = nil) migrated = Set.new(Base.connection.migration_context.get_all_versions) migrations.group_by(&:name).each do |name, duplicates| @@ -34,7 +34,7 @@ module ActiveRecord end end - super(direction, migrations, target_version) + super(direction, migrations, schema_migration, target_version) end end From b61e44461cffb887556e20ba5a07caef72133e10 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Mar 2021 15:41:47 +0900 Subject: [PATCH 26/27] [Glitch] Bump react-select from 3.2.0 to 4.0.2 Add cacheKey to NonceProvider for react-select Port changes from c3aef491d66aec743a3a53e934a494f653745b61 to glitch-soc Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Yamagishi Kazutoshi Signed-off-by: Claire --- .../features/hashtag_timeline/components/column_settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/flavours/glitch/features/hashtag_timeline/components/column_settings.js b/app/javascript/flavours/glitch/features/hashtag_timeline/components/column_settings.js index 27300f020df..de1127b0d51 100644 --- a/app/javascript/flavours/glitch/features/hashtag_timeline/components/column_settings.js +++ b/app/javascript/flavours/glitch/features/hashtag_timeline/components/column_settings.js @@ -59,7 +59,7 @@ class ColumnSettings extends React.PureComponent { {this.modeLabel(mode)} - + Date: Wed, 24 Mar 2021 10:19:07 +0100 Subject: [PATCH 27/27] [Glitch] Fix compose form behavior in mobile view Port 034f37b85a716872f78a72048a5a225cdcaa840a to glitch-soc Signed-off-by: Claire --- .../compose/components/compose_form.js | 10 ++++++++- .../features/ui/components/columns_area.js | 21 +++++++++++++++++-- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/app/javascript/flavours/glitch/features/compose/components/compose_form.js b/app/javascript/flavours/glitch/features/compose/components/compose_form.js index 164f4a960d9..d4804a3c286 100644 --- a/app/javascript/flavours/glitch/features/compose/components/compose_form.js +++ b/app/javascript/flavours/glitch/features/compose/components/compose_form.js @@ -199,6 +199,14 @@ class ComposeForm extends ImmutablePureComponent { } } + componentDidMount () { + this._updateFocusAndSelection({ }); + } + + componentDidUpdate (prevProps) { + this._updateFocusAndSelection(prevProps); + } + // This statement does several things: // - If we're beginning a reply, and, // - Replying to zero or one users, places the cursor at the end @@ -206,7 +214,7 @@ class ComposeForm extends ImmutablePureComponent { // - Replying to more than one user, selects any usernames past // the first; this provides a convenient shortcut to drop // everyone else from the conversation. - componentDidUpdate (prevProps) { + _updateFocusAndSelection = (prevProps) => { const { textarea, spoilerText, diff --git a/app/javascript/flavours/glitch/features/ui/components/columns_area.js b/app/javascript/flavours/glitch/features/ui/components/columns_area.js index 640be19aba0..b41de58d70e 100644 --- a/app/javascript/flavours/glitch/features/ui/components/columns_area.js +++ b/app/javascript/flavours/glitch/features/ui/components/columns_area.js @@ -70,8 +70,12 @@ class ColumnsArea extends ImmutablePureComponent { openSettings: PropTypes.func, }; + // Corresponds to (max-width: 600px + (285px * 1) + (10px * 1)) in SCSS + mediaQuery = 'matchMedia' in window && window.matchMedia('(max-width: 895px)'); + state = { shouldAnimate: false, + renderComposePanel: !(this.mediaQuery && this.mediaQuery.matches), } componentWillReceiveProps() { @@ -85,6 +89,11 @@ class ColumnsArea extends ImmutablePureComponent { this.node.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : false); } + if (this.mediaQuery) { + this.mediaQuery.addEventListener('change', this.handleLayoutChange); + this.setState({ renderComposePanel: !this.mediaQuery.matches }); + } + this.lastIndex = getIndex(this.context.router.history.location.pathname); this.isRtlLayout = document.getElementsByTagName('body')[0].classList.contains('rtl'); @@ -114,6 +123,10 @@ class ColumnsArea extends ImmutablePureComponent { if (!this.props.singleColumn) { this.node.removeEventListener('wheel', this.handleWheel); } + + if (this.mediaQuery) { + this.mediaQuery.removeEventListener('change', this.handleLayoutChange); + } } handleChildrenContentChange() { @@ -123,6 +136,10 @@ class ColumnsArea extends ImmutablePureComponent { } } + handleLayoutChange = (e) => { + this.setState({ renderComposePanel: !e.matches }); + } + handleSwipe = (index) => { this.pendingIndex = index; @@ -186,7 +203,7 @@ class ColumnsArea extends ImmutablePureComponent { render () { const { columns, children, singleColumn, swipeToChangeColumns, intl, navbarUnder, openSettings } = this.props; - const { shouldAnimate } = this.state; + const { shouldAnimate, renderComposePanel } = this.state; const columnIndex = getIndex(this.context.router.history.location.pathname); @@ -205,7 +222,7 @@ class ColumnsArea extends ImmutablePureComponent {
- + {renderComposePanel && }