From fd385e256d1ca99fa9a6f1bd8068d083cb0e39ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczak?= Date: Tue, 13 Mar 2018 18:17:48 +0100 Subject: [PATCH 01/41] i18n: Update Polish translation (#6780) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marcin Mikołajczak --- app/javascript/mastodon/locales/pl.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json index 2d6f0c01b..8496495f5 100644 --- a/app/javascript/mastodon/locales/pl.json +++ b/app/javascript/mastodon/locales/pl.json @@ -60,10 +60,10 @@ "compose_form.placeholder": "Co Ci chodzi po głowie?", "compose_form.publish": "Wyślij", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.marked": "Media is marked as sensitive", - "compose_form.sensitive.unmarked": "Media is not marked as sensitive", - "compose_form.spoiler.marked": "Text is hidden behind warning", - "compose_form.spoiler.unmarked": "Text is not hidden", + "compose_form.sensitive.marked": "Zawartość multimedia jest oznaczona jako wrażliwa", + "compose_form.sensitive.unmarked": "Zawartość multimedialna nie jest oznaczona jako wrażliwa", + "compose_form.spoiler.marked": "Tekst jest ukryty za ostrzeżeniem", + "compose_form.spoiler.unmarked": "Tekst nie jest ukryty", "compose_form.spoiler_placeholder": "Wprowadź swoje ostrzeżenie o zawartości", "confirmation_modal.cancel": "Anuluj", "confirmations.block.confirm": "Zablokuj", From 64fc8d2b077c76530f59f4da173659982caa9964 Mon Sep 17 00:00:00 2001 From: Daniel Hunsaker Date: Sat, 17 Mar 2018 01:39:14 -0600 Subject: [PATCH 02/41] [Nanobox] Stream backups to the warehouse (#6799) The `curl` docs are terrible. Use `-X POST -T` instead of `--data-binary`, to avoid loading entire backups into memory _before_ transferring to the warehouse, and just stream the data across as it comes in. --- boxfile.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/boxfile.yml b/boxfile.yml index 70774dac9..aa2003a1b 100644 --- a/boxfile.yml +++ b/boxfile.yml @@ -195,7 +195,7 @@ data.db: command: | PGPASSWORD=${DATA_DB_PASS} pg_dump -U ${DATA_DB_USER} -w -Fc -O gonano | gzip | - curl -k -H "X-AUTH-TOKEN: ${WAREHOUSE_DATA_HOARDER_TOKEN}" https://${WAREHOUSE_DATA_HOARDER_HOST}:7410/blobs/backup-${HOSTNAME}-$(date -u +%Y-%m-%d.%H-%M-%S).sql.gz --data-binary @- && + curl -k -H "X-AUTH-TOKEN: ${WAREHOUSE_DATA_HOARDER_TOKEN}" https://${WAREHOUSE_DATA_HOARDER_HOST}:7410/blobs/backup-${HOSTNAME}-$(date -u +%Y-%m-%d.%H-%M-%S).sql.gz -X POST -T - >&2 curl -k -s -H "X-AUTH-TOKEN: ${WAREHOUSE_DATA_HOARDER_TOKEN}" https://${WAREHOUSE_DATA_HOARDER_HOST}:7410/blobs/ | sed 's/,/\n/g' | grep ${HOSTNAME} | @@ -215,7 +215,7 @@ data.redis: - id: backup schedule: '0 3 * * *' command: | - curl -k -H "X-AUTH-TOKEN: ${WAREHOUSE_DATA_HOARDER_TOKEN}" https://${WAREHOUSE_DATA_HOARDER_HOST}:7410/blobs/backup-${HOSTNAME}-$(date -u +%Y-%m-%d.%H-%M-%S).rdb --data-binary @/data/var/db/redis/dump.rdb && + curl -k -H "X-AUTH-TOKEN: ${WAREHOUSE_DATA_HOARDER_TOKEN}" https://${WAREHOUSE_DATA_HOARDER_HOST}:7410/blobs/backup-${HOSTNAME}-$(date -u +%Y-%m-%d.%H-%M-%S).rdb -X POST -T /data/var/db/redis/dump.rdb >&2 curl -k -s -H "X-AUTH-TOKEN: ${WAREHOUSE_DATA_HOARDER_TOKEN}" https://${WAREHOUSE_DATA_HOARDER_HOST}:7410/blobs/ | sed 's/,/\n/g' | grep ${HOSTNAME} | @@ -236,7 +236,7 @@ data.storage: schedule: '0 3 * * *' command: | tar cz -C /data/var/db/unfs/ . | - curl -k -H "X-AUTH-TOKEN: ${WAREHOUSE_DATA_HOARDER_TOKEN}" https://${WAREHOUSE_DATA_HOARDER_HOST}:7410/blobs/backup-${HOSTNAME}-$(date -u +%Y-%m-%d.%H-%M-%S).tgz --data-binary @- && + curl -k -H "X-AUTH-TOKEN: ${WAREHOUSE_DATA_HOARDER_TOKEN}" https://${WAREHOUSE_DATA_HOARDER_HOST}:7410/blobs/backup-${HOSTNAME}-$(date -u +%Y-%m-%d.%H-%M-%S).tgz -X POST -T - >&2 curl -k -s -H "X-AUTH-TOKEN: ${WAREHOUSE_DATA_HOARDER_TOKEN}" https://${WAREHOUSE_DATA_HOARDER_HOST}:7410/blobs/ | sed 's/,/\n/g' | grep ${HOSTNAME} | From f0cd957c7a8a53dea2eb08a45578084b4d8bb5b4 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Sat, 17 Mar 2018 20:35:13 +0900 Subject: [PATCH 03/41] Cache HTML page with Service Worker (#6802) This is the first step to make Mastodon work offline. It is also required by Chromium to trigger Web Manifest automated install prompt. --- .../mastodon/service_worker/entry.js | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/app/javascript/mastodon/service_worker/entry.js b/app/javascript/mastodon/service_worker/entry.js index eea4cfc3c..ad933b95e 100644 --- a/app/javascript/mastodon/service_worker/entry.js +++ b/app/javascript/mastodon/service_worker/entry.js @@ -1,10 +1,30 @@ import './web_push_notifications'; +function fetchRoot() { + return fetch('/', { credentials: 'include' }); +} + // Cause a new version of a registered Service Worker to replace an existing one // that is already installed, and replace the currently active worker on open pages. self.addEventListener('install', function(event) { - event.waitUntil(self.skipWaiting()); + const promises = Promise.all([caches.open('mastodon-web'), fetchRoot()]); + const asyncAdd = promises.then(([cache, root]) => cache.put('/', root)); + + event.waitUntil(asyncAdd); }); self.addEventListener('activate', function(event) { event.waitUntil(self.clients.claim()); }); +self.addEventListener('fetch', function(event) { + const url = new URL(event.request.url); + + if (url.pathname.startsWith('/web/')) { + event.respondWith(fetchRoot().then(response => { + if (response.ok) { + return response; + } + + throw null; + }).catch(() => caches.match('/'))); + } +}); From ca7e6a6d2ec2310fd026f2694580f839b4124dd2 Mon Sep 17 00:00:00 2001 From: trwnh Date: Sat, 17 Mar 2018 06:35:35 -0500 Subject: [PATCH 04/41] Properly center .nothing-here (#6787) (#6788) Apply "margin: 0 auto;" at line 443 to fix issue #6787 --- app/javascript/styles/mastodon/accounts.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/app/javascript/styles/mastodon/accounts.scss b/app/javascript/styles/mastodon/accounts.scss index 873963c90..dd82ab375 100644 --- a/app/javascript/styles/mastodon/accounts.scss +++ b/app/javascript/styles/mastodon/accounts.scss @@ -440,6 +440,7 @@ text-align: center; padding: 60px 0; padding-top: 55px; + margin: 0 auto; cursor: default; } From b88fcd53f711673b21e5ff4a547dbf929866a2ee Mon Sep 17 00:00:00 2001 From: Yamagishi Kazutoshi Date: Sat, 17 Mar 2018 20:37:58 +0900 Subject: [PATCH 05/41] Upgrade Paperclip to version 6.0.0 (#6754) --- Gemfile | 4 ++-- Gemfile.lock | 29 ++++++++++++++++++----------- config/initializers/paperclip.rb | 3 +-- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/Gemfile b/Gemfile index 3fce2ddc7..54fcabb05 100644 --- a/Gemfile +++ b/Gemfile @@ -13,11 +13,11 @@ gem 'pg', '~> 0.20' gem 'pghero', '~> 1.7' gem 'dotenv-rails', '~> 2.2' -gem 'aws-sdk', '~> 2.10', require: false +gem 'aws-sdk-s3', '~> 1.8', require: false gem 'fog-core', '~> 1.45' gem 'fog-local', '~> 0.4', require: false gem 'fog-openstack', '~> 0.1', require: false -gem 'paperclip', '~> 5.1' +gem 'paperclip', '~> 6.0' gem 'paperclip-av-transcoder', '~> 0.6' gem 'streamio-ffmpeg', '~> 3.0' diff --git a/Gemfile.lock b/Gemfile.lock index 0640b140b..dd17be944 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -57,13 +57,18 @@ GEM encryptor (~> 3.0.0) av (0.9.0) cocaine (~> 0.5.3) - aws-sdk (2.10.100) - aws-sdk-resources (= 2.10.100) - aws-sdk-core (2.10.100) + aws-partitions (1.70.0) + aws-sdk-core (3.17.0) + aws-partitions (~> 1.0) aws-sigv4 (~> 1.0) jmespath (~> 1.0) - aws-sdk-resources (2.10.100) - aws-sdk-core (= 2.10.100) + aws-sdk-kms (1.5.0) + aws-sdk-core (~> 3) + aws-sigv4 (~> 1.0) + aws-sdk-s3 (1.8.2) + aws-sdk-core (~> 3) + aws-sdk-kms (~> 1) + aws-sigv4 (~> 1.0) aws-sigv4 (1.0.2) bcrypt (3.1.11) better_errors (2.4.0) @@ -236,7 +241,7 @@ GEM httplog (0.99.7) colorize rack - i18n (0.9.3) + i18n (0.9.5) concurrent-ruby (~> 1.0) i18n-tasks (0.9.19) activesupport (>= 4.0.2) @@ -342,12 +347,12 @@ GEM http (~> 3.0) nokogiri (~> 1.8) ox (2.8.2) - paperclip (5.2.1) + paperclip (6.0.0) activemodel (>= 4.2.0) activesupport (>= 4.2.0) - cocaine (~> 0.5.5) mime-types mimemagic (~> 0.3.0) + terrapin (~> 0.6.0) paperclip-av-transcoder (0.6.4) av (~> 0.9.0) paperclip (>= 2.5.2) @@ -552,6 +557,8 @@ GEM temple (0.8.0) terminal-table (1.8.0) unicode-display_width (~> 1.1, >= 1.1.1) + terrapin (0.6.0) + climate_control (>= 0.0.3, < 1.0) thor (0.20.0) thread (0.2.2) thread_safe (0.3.6) @@ -575,7 +582,7 @@ GEM tty-screen (0.6.4) twitter-text (1.14.7) unf (~> 0.1.0) - tzinfo (1.2.4) + tzinfo (1.2.5) thread_safe (~> 0.1) tzinfo-data (1.2017.3) tzinfo (>= 1.0.0) @@ -612,7 +619,7 @@ DEPENDENCIES active_record_query_trace (~> 1.5) addressable (~> 2.5) annotate (~> 2.7) - aws-sdk (~> 2.10) + aws-sdk-s3 (~> 1.8) better_errors (~> 2.4) binding_of_caller (~> 0.7) bootsnap @@ -671,7 +678,7 @@ DEPENDENCIES omniauth-saml (~> 1.10) ostatus2 (~> 2.0) ox (~> 2.8) - paperclip (~> 5.1) + paperclip (~> 6.0) paperclip-av-transcoder (~> 0.6) parallel_tests (~> 2.17) pg (~> 0.20) diff --git a/config/initializers/paperclip.rb b/config/initializers/paperclip.rb index 8aa1d1b6e..17a520aa2 100644 --- a/config/initializers/paperclip.rb +++ b/config/initializers/paperclip.rb @@ -14,8 +14,7 @@ Paperclip::Attachment.default_options.merge!( ) if ENV['S3_ENABLED'] == 'true' - require 'aws-sdk' - Aws.eager_autoload!(services: %w(S3)) + require 'aws-sdk-s3' s3_region = ENV.fetch('S3_REGION') { 'us-east-1' } s3_protocol = ENV.fetch('S3_PROTOCOL') { 'https' } From 338bff8b93fa939c2968818e53386fd0c013d9a9 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Sat, 17 Mar 2018 21:27:19 +0900 Subject: [PATCH 06/41] Correct the reference to user's password in mastodon:add_user task (#6800) --- lib/tasks/mastodon.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tasks/mastodon.rake b/lib/tasks/mastodon.rake index 13df76f91..cf32b1495 100644 --- a/lib/tasks/mastodon.rake +++ b/lib/tasks/mastodon.rake @@ -472,7 +472,7 @@ namespace :mastodon do if user.save prompt.ok 'User created and confirmation mail sent to the user\'s email address.' - prompt.ok "Here is the random password generated for the user: #{password}" + prompt.ok "Here is the random password generated for the user: #{user.password}" else prompt.warn 'User was not created because of the following errors:' From 4a0a19fe54f1d2d433ad3d72c35f2bbb915279f6 Mon Sep 17 00:00:00 2001 From: Daniel Hunsaker Date: Sat, 17 Mar 2018 06:27:50 -0600 Subject: [PATCH 07/41] Handle Mastodon::HostValidationError when pulling remoteable assets (#6782) This will prevent, for example, `rake mastodon:redownload_avatars` from crashing when an instance is no longer responding to connection attempts, instead silently continuing as expected. --- app/models/concerns/remotable.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/concerns/remotable.rb b/app/models/concerns/remotable.rb index 020303a2f..69685ec83 100644 --- a/app/models/concerns/remotable.rb +++ b/app/models/concerns/remotable.rb @@ -38,7 +38,7 @@ module Remotable send("#{attachment_name}_file_name=", basename + extname) self[attribute_name] = url if has_attribute?(attribute_name) - rescue HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError, Paperclip::Errors::NotIdentifiedByImageMagickError, Addressable::URI::InvalidURIError => e + rescue HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError, Paperclip::Errors::NotIdentifiedByImageMagickError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError => e Rails.logger.debug "Error fetching remote #{attachment_name}: #{e}" nil end From 0074cad44ffcbbdbc798f57a21829359741e60d9 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 17 Mar 2018 14:06:25 +0100 Subject: [PATCH 08/41] Downgrade Dockerfile to Ruby 2.4.3 on Alpine 3.6 (#6806) Fix 6734 --- Dockerfile | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 9eb5e609d..a5d1d9caa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ruby:2.5.0-alpine3.7 +FROM ruby:2.4.3-alpine3.6 LABEL maintainer="https://github.com/tootsuite/mastodon" \ description="Your self-hosted, globally interconnected microblogging community" @@ -9,6 +9,8 @@ ARG GID=991 ENV RAILS_SERVE_STATIC_FILES=true \ RAILS_ENV=production NODE_ENV=production +ARG YARN_VERSION=1.3.2 +ARG YARN_DOWNLOAD_SHA256=6cfe82e530ef0837212f13e45c1565ba53f5199eec2527b85ecbcd88bf26821d ARG LIBICONV_VERSION=1.15 ARG LIBICONV_DOWNLOAD_SHA256=ccf536620a45458d26ba83887a983b96827001e92a13847b45e4925cc8913178 @@ -38,9 +40,14 @@ RUN apk -U upgrade \ protobuf \ tini \ tzdata \ - yarn \ && update-ca-certificates \ - && mkdir -p /tmp/src \ + && mkdir -p /tmp/src /opt \ + && wget -O yarn.tar.gz "https://github.com/yarnpkg/yarn/releases/download/v$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ + && echo "$YARN_DOWNLOAD_SHA256 *yarn.tar.gz" | sha256sum -c - \ + && tar -xzf yarn.tar.gz -C /tmp/src \ + && rm yarn.tar.gz \ + && mv /tmp/src/yarn-v$YARN_VERSION /opt/yarn \ + && ln -s /opt/yarn/bin/yarn /usr/local/bin/yarn \ && wget -O libiconv.tar.gz "https://ftp.gnu.org/pub/gnu/libiconv/libiconv-$LIBICONV_VERSION.tar.gz" \ && echo "$LIBICONV_DOWNLOAD_SHA256 *libiconv.tar.gz" | sha256sum -c - \ && tar -xzf libiconv.tar.gz -C /tmp/src \ From cdf8b92fea269209cedf38c50bca276cdf47b1fe Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 17 Mar 2018 14:07:00 +0100 Subject: [PATCH 09/41] Bump version to 2.3.2rc1 --- lib/mastodon/version.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index 05b13c802..4f524e9cf 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -13,7 +13,7 @@ module Mastodon end def patch - 1 + 2 end def pre @@ -21,7 +21,7 @@ module Mastodon end def flags - '' + 'rc1' end def to_a From 40871caa4b06c7ee1c3b07f439ed984ead295ced Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 17 Mar 2018 14:20:35 +0100 Subject: [PATCH 10/41] Revert "Upgrade Paperclip to version 6.0.0" (#6807) * Revert "Bump version to 2.3.2rc1" This reverts commit cdf8b92fea269209cedf38c50bca276cdf47b1fe. * Revert "Downgrade Dockerfile to Ruby 2.4.3 on Alpine 3.6 (#6806)" This reverts commit 0074cad44ffcbbdbc798f57a21829359741e60d9. * Revert "Handle Mastodon::HostValidationError when pulling remoteable assets (#6782)" This reverts commit 4a0a19fe54f1d2d433ad3d72c35f2bbb915279f6. * Revert "Correct the reference to user's password in mastodon:add_user task (#6800)" This reverts commit 338bff8b93fa939c2968818e53386fd0c013d9a9. * Revert "Upgrade Paperclip to version 6.0.0 (#6754)" This reverts commit b88fcd53f711673b21e5ff4a547dbf929866a2ee. --- Gemfile | 4 ++-- Gemfile.lock | 29 +++++++++++------------------ config/initializers/paperclip.rb | 3 ++- 3 files changed, 15 insertions(+), 21 deletions(-) diff --git a/Gemfile b/Gemfile index 54fcabb05..3fce2ddc7 100644 --- a/Gemfile +++ b/Gemfile @@ -13,11 +13,11 @@ gem 'pg', '~> 0.20' gem 'pghero', '~> 1.7' gem 'dotenv-rails', '~> 2.2' -gem 'aws-sdk-s3', '~> 1.8', require: false +gem 'aws-sdk', '~> 2.10', require: false gem 'fog-core', '~> 1.45' gem 'fog-local', '~> 0.4', require: false gem 'fog-openstack', '~> 0.1', require: false -gem 'paperclip', '~> 6.0' +gem 'paperclip', '~> 5.1' gem 'paperclip-av-transcoder', '~> 0.6' gem 'streamio-ffmpeg', '~> 3.0' diff --git a/Gemfile.lock b/Gemfile.lock index dd17be944..0640b140b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -57,18 +57,13 @@ GEM encryptor (~> 3.0.0) av (0.9.0) cocaine (~> 0.5.3) - aws-partitions (1.70.0) - aws-sdk-core (3.17.0) - aws-partitions (~> 1.0) + aws-sdk (2.10.100) + aws-sdk-resources (= 2.10.100) + aws-sdk-core (2.10.100) aws-sigv4 (~> 1.0) jmespath (~> 1.0) - aws-sdk-kms (1.5.0) - aws-sdk-core (~> 3) - aws-sigv4 (~> 1.0) - aws-sdk-s3 (1.8.2) - aws-sdk-core (~> 3) - aws-sdk-kms (~> 1) - aws-sigv4 (~> 1.0) + aws-sdk-resources (2.10.100) + aws-sdk-core (= 2.10.100) aws-sigv4 (1.0.2) bcrypt (3.1.11) better_errors (2.4.0) @@ -241,7 +236,7 @@ GEM httplog (0.99.7) colorize rack - i18n (0.9.5) + i18n (0.9.3) concurrent-ruby (~> 1.0) i18n-tasks (0.9.19) activesupport (>= 4.0.2) @@ -347,12 +342,12 @@ GEM http (~> 3.0) nokogiri (~> 1.8) ox (2.8.2) - paperclip (6.0.0) + paperclip (5.2.1) activemodel (>= 4.2.0) activesupport (>= 4.2.0) + cocaine (~> 0.5.5) mime-types mimemagic (~> 0.3.0) - terrapin (~> 0.6.0) paperclip-av-transcoder (0.6.4) av (~> 0.9.0) paperclip (>= 2.5.2) @@ -557,8 +552,6 @@ GEM temple (0.8.0) terminal-table (1.8.0) unicode-display_width (~> 1.1, >= 1.1.1) - terrapin (0.6.0) - climate_control (>= 0.0.3, < 1.0) thor (0.20.0) thread (0.2.2) thread_safe (0.3.6) @@ -582,7 +575,7 @@ GEM tty-screen (0.6.4) twitter-text (1.14.7) unf (~> 0.1.0) - tzinfo (1.2.5) + tzinfo (1.2.4) thread_safe (~> 0.1) tzinfo-data (1.2017.3) tzinfo (>= 1.0.0) @@ -619,7 +612,7 @@ DEPENDENCIES active_record_query_trace (~> 1.5) addressable (~> 2.5) annotate (~> 2.7) - aws-sdk-s3 (~> 1.8) + aws-sdk (~> 2.10) better_errors (~> 2.4) binding_of_caller (~> 0.7) bootsnap @@ -678,7 +671,7 @@ DEPENDENCIES omniauth-saml (~> 1.10) ostatus2 (~> 2.0) ox (~> 2.8) - paperclip (~> 6.0) + paperclip (~> 5.1) paperclip-av-transcoder (~> 0.6) parallel_tests (~> 2.17) pg (~> 0.20) diff --git a/config/initializers/paperclip.rb b/config/initializers/paperclip.rb index 17a520aa2..8aa1d1b6e 100644 --- a/config/initializers/paperclip.rb +++ b/config/initializers/paperclip.rb @@ -14,7 +14,8 @@ Paperclip::Attachment.default_options.merge!( ) if ENV['S3_ENABLED'] == 'true' - require 'aws-sdk-s3' + require 'aws-sdk' + Aws.eager_autoload!(services: %w(S3)) s3_region = ENV.fetch('S3_REGION') { 'us-east-1' } s3_protocol = ENV.fetch('S3_PROTOCOL') { 'https' } From 844616e9505953c9c2735c83b32784588a20c505 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 17 Mar 2018 15:28:09 +0100 Subject: [PATCH 11/41] Re-add git and nodejs-npm to Dockerfile (#6810) Fix #6809 I don't know why, either --- Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Dockerfile b/Dockerfile index a5d1d9caa..0801f5747 100644 --- a/Dockerfile +++ b/Dockerfile @@ -32,11 +32,13 @@ RUN apk -U upgrade \ ca-certificates \ ffmpeg \ file \ + git \ icu-libs \ imagemagick \ libidn \ libpq \ nodejs \ + nodejs-npm \ protobuf \ tini \ tzdata \ From 092f1df9d0a730df8ae6624feed3b11c321f604a Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 17 Mar 2018 15:28:52 +0100 Subject: [PATCH 12/41] Bump version to 2.3.2rc2 --- lib/mastodon/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index 4f524e9cf..fefe63276 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -21,7 +21,7 @@ module Mastodon end def flags - 'rc1' + 'rc2' end def to_a From 566ace2d6479c05e51dd8ce24283b8606be631de Mon Sep 17 00:00:00 2001 From: nightpool Date: Sat, 17 Mar 2018 12:39:28 -0400 Subject: [PATCH 13/41] Add entropy to download filenames (#6811) pretty quick fix, and with the 1 week expiration i don't think we need to be too worried about the existing files closes #6798 --- app/services/backup_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/backup_service.rb b/app/services/backup_service.rb index fadc24a82..8492c1117 100644 --- a/app/services/backup_service.rb +++ b/app/services/backup_service.rb @@ -49,7 +49,7 @@ class BackupService < BaseService end end - archive_filename = ['archive', Time.now.utc.strftime('%Y%m%d%H%M%S'), SecureRandom.hex(2)].join('-') + '.tar.gz' + archive_filename = ['archive', Time.now.utc.strftime('%Y%m%d%H%M%S'), SecureRandom.hex(16)].join('-') + '.tar.gz' @backup.dump = ActionDispatch::Http::UploadedFile.new(tempfile: tmp_file, filename: archive_filename) @backup.processed = true From 721234230c8eb4bc0d1388276e59350103c01577 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Sun, 18 Mar 2018 23:14:38 +0900 Subject: [PATCH 14/41] Synchronize HTML page cache with sessions (#6815) --- .babelrc | 2 ++ .../mastodon/service_worker/entry.js | 30 +++++++++++++++---- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/.babelrc b/.babelrc index de922f389..ed28aa500 100644 --- a/.babelrc +++ b/.babelrc @@ -4,6 +4,8 @@ [ "env", { + "debug": true, + "exclude": ["transform-async-to-generator", "transform-regenerator"], "loose": true, "modules": false, "targets": { diff --git a/app/javascript/mastodon/service_worker/entry.js b/app/javascript/mastodon/service_worker/entry.js index ad933b95e..8b65f27a3 100644 --- a/app/javascript/mastodon/service_worker/entry.js +++ b/app/javascript/mastodon/service_worker/entry.js @@ -1,5 +1,9 @@ import './web_push_notifications'; +function openCache() { + return caches.open('mastodon-web'); +} + function fetchRoot() { return fetch('/', { credentials: 'include' }); } @@ -7,10 +11,7 @@ function fetchRoot() { // Cause a new version of a registered Service Worker to replace an existing one // that is already installed, and replace the currently active worker on open pages. self.addEventListener('install', function(event) { - const promises = Promise.all([caches.open('mastodon-web'), fetchRoot()]); - const asyncAdd = promises.then(([cache, root]) => cache.put('/', root)); - - event.waitUntil(asyncAdd); + event.waitUntil(Promise.all([openCache(), fetchRoot()]).then(([cache, root]) => cache.put('/', root))); }); self.addEventListener('activate', function(event) { event.waitUntil(self.clients.claim()); @@ -19,12 +20,29 @@ self.addEventListener('fetch', function(event) { const url = new URL(event.request.url); if (url.pathname.startsWith('/web/')) { - event.respondWith(fetchRoot().then(response => { + const asyncResponse = fetchRoot(); + const asyncCache = openCache(); + + event.respondWith(asyncResponse.then(async response => { if (response.ok) { - return response; + const cache = await asyncCache; + await cache.put('/', response); + return response.clone(); } throw null; }).catch(() => caches.match('/'))); + } else if (url.pathname === '/auth/sign_out') { + const asyncResponse = fetch(event.request); + const asyncCache = openCache(); + + event.respondWith(asyncResponse.then(async response => { + if (response.ok || response.type === 'opaqueredirect') { + const cache = await asyncCache; + await cache.delete('/'); + } + + return response; + })); } }); From 39f27b6cf3868806fc3a35003f8600f60795d737 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sun, 18 Mar 2018 16:57:04 +0100 Subject: [PATCH 15/41] If DEFAULT_LOCALE is set, enforce it instead of HTTP request locale (#6817) Fix #6784 --- app/controllers/concerns/localized.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/controllers/concerns/localized.rb b/app/controllers/concerns/localized.rb index e697284a8..abd85ea27 100644 --- a/app/controllers/concerns/localized.rb +++ b/app/controllers/concerns/localized.rb @@ -17,7 +17,11 @@ module Localized end def default_locale - request_locale || I18n.default_locale + if ENV['DEFAULT_LOCALE'].present? + I18n.default_locale + else + request_locale || I18n.default_locale + end end def request_locale From 3b440bd5af92682c388140035c1bcdc6f9711b1d Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sun, 18 Mar 2018 20:32:44 +0100 Subject: [PATCH 16/41] Fix elephant graphic being draggable and selectable (#6819) --- app/javascript/mastodon/features/compose/index.js | 2 +- app/javascript/styles/mastodon/components.scss | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/javascript/mastodon/features/compose/index.js b/app/javascript/mastodon/features/compose/index.js index 138bc4e2e..d5cd854db 100644 --- a/app/javascript/mastodon/features/compose/index.js +++ b/app/javascript/mastodon/features/compose/index.js @@ -97,7 +97,7 @@ export default class Compose extends React.PureComponent { {multiColumn && (
- +
)} diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 587fe62da..20e07a042 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -1842,6 +1842,9 @@ object-position: bottom left; width: 100%; height: 100%; + pointer-events: none; + user-drag: none; + user-select: none; } } From a568e3ca8e754b690224ae79e75aeb60efa49b78 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sun, 18 Mar 2018 20:33:07 +0100 Subject: [PATCH 17/41] Revert #6479, hide sensitive text/images from OpenGraph previews (#6818) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Display summary of attachments in description, and mark up content warning if present, e.g.: Attached: 3 images · Content warning: Dota 2 When text is not supposed to be hidden, it looks more like: Attached: 3 images Here is the text of the toot With #6817, multilinguagility should be assured... --- app/helpers/stream_entries_helper.rb | 29 +++++++++++++++++++ app/views/accounts/_og.html.haml | 2 +- app/views/accounts/show.html.haml | 2 +- .../stream_entries/_og_description.html.haml | 2 +- app/views/stream_entries/_og_image.html.haml | 2 +- app/views/stream_entries/show.html.haml | 4 +-- config/i18n-tasks.yml | 1 + config/locales/en.yml | 9 ++++++ 8 files changed, 45 insertions(+), 6 deletions(-) diff --git a/app/helpers/stream_entries_helper.rb b/app/helpers/stream_entries_helper.rb index 54b92bdf4..3992432db 100644 --- a/app/helpers/stream_entries_helper.rb +++ b/app/helpers/stream_entries_helper.rb @@ -29,6 +29,35 @@ module StreamEntriesHelper [prepend_str, account.note].join(' · ') end + def media_summary(status) + attachments = { image: 0, video: 0 } + + status.media_attachments.each do |media| + if media.video? + attachments[:video] += 1 + else + attachments[:image] += 1 + end + end + + text = attachments.to_a.reject { |_, value| value.zero? }.map { |key, value| t("statuses.attached.#{key}", count: value) }.join(' · ') + + return if text.blank? + + t('statuses.attached.description', attached: text) + end + + def status_text_summary(status) + return if status.spoiler_text.blank? + t('statuses.content_warning', warning: status.spoiler_text) + end + + def status_description(status) + components = [[media_summary(status), status_text_summary(status)].reject(&:blank?).join(' · ')] + components << status.text if status.spoiler_text.blank? + components.reject(&:blank?).join("\n\n") + end + def stream_link_target embedded_view? ? '_blank' : nil end diff --git a/app/views/accounts/_og.html.haml b/app/views/accounts/_og.html.haml index 26424a49c..a583b39c2 100644 --- a/app/views/accounts/_og.html.haml +++ b/app/views/accounts/_og.html.haml @@ -1,6 +1,6 @@ = opengraph 'og:url', url = opengraph 'og:site_name', site_title -= opengraph 'og:title', [yield(:page_title).strip.presence, site_title].compact.join(' - ') += opengraph 'og:title', yield(:page_title).strip = opengraph 'og:description', account_description(account) = opengraph 'og:image', full_asset_url(account.avatar.url(:original)) = opengraph 'og:image:width', '120' diff --git a/app/views/accounts/show.html.haml b/app/views/accounts/show.html.haml index c62a573b0..bbf2139a5 100644 --- a/app/views/accounts/show.html.haml +++ b/app/views/accounts/show.html.haml @@ -1,5 +1,5 @@ - content_for :page_title do - = "#{display_name(@account)} (@#{@account.username})" + = "#{display_name(@account)} (@#{@account.local_username_and_domain})" - content_for :header_tags do %meta{ name: 'description', content: account_description(@account) }/ diff --git a/app/views/stream_entries/_og_description.html.haml b/app/views/stream_entries/_og_description.html.haml index 9c24e0a61..3d122b94e 100644 --- a/app/views/stream_entries/_og_description.html.haml +++ b/app/views/stream_entries/_og_description.html.haml @@ -1 +1 @@ -= opengraph 'og:description', [activity.spoiler_text, activity.text].reject(&:blank?).join("\n\n") += opengraph 'og:description', status_description(activity) diff --git a/app/views/stream_entries/_og_image.html.haml b/app/views/stream_entries/_og_image.html.haml index 526034faa..40530f567 100644 --- a/app/views/stream_entries/_og_image.html.haml +++ b/app/views/stream_entries/_og_image.html.haml @@ -1,4 +1,4 @@ -- if activity.is_a?(Status) && activity.media_attachments.any? +- if activity.is_a?(Status) && activity.non_sensitive_with_media? - player_card = false - activity.media_attachments.each do |media| - if media.image? diff --git a/app/views/stream_entries/show.html.haml b/app/views/stream_entries/show.html.haml index a87c51952..dfb83e747 100644 --- a/app/views/stream_entries/show.html.haml +++ b/app/views/stream_entries/show.html.haml @@ -11,8 +11,8 @@ = opengraph 'og:site_name', site_title = opengraph 'og:type', 'article' - = opengraph 'og:title', "#{@account.display_name.presence || @account.username} on #{site_hostname}" - = opengraph 'og:url', account_stream_entry_url(@account, @stream_entry) + = opengraph 'og:title', "#{display_name(@account)} (@#{@account.local_username_and_domain})" + = opengraph 'og:url', short_account_status_url(@account, @stream_entry) = render 'stream_entries/og_description', activity: @stream_entry.activity = render 'stream_entries/og_image', activity: @stream_entry.activity, account: @account diff --git a/config/i18n-tasks.yml b/config/i18n-tasks.yml index bcd816d30..eec8b6dbe 100644 --- a/config/i18n-tasks.yml +++ b/config/i18n-tasks.yml @@ -62,3 +62,4 @@ ignore_unused: - 'errors.429' - 'admin.accounts.roles.*' - 'admin.action_logs.actions.*' + - 'statuses.attached.*' diff --git a/config/locales/en.yml b/config/locales/en.yml index 2dd09626d..735a3490f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -634,6 +634,15 @@ en: two_factor_authentication: Two-factor Auth your_apps: Your applications statuses: + attached: + description: 'Attached: %{attached}' + image: + one: "%{count} image" + other: "%{count} images" + video: + one: "%{count} video" + other: "%{count} videos" + content_warning: 'Content warning: %{warning}' open_in_web: Open in web over_character_limit: character limit of %{max} exceeded pin_errors: From f02411da404f730e3c05dc7dca1ac0f2d631315e Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 19 Mar 2018 01:51:19 +0100 Subject: [PATCH 18/41] Ignore media validation when attaching to status during processing (#6822) Fix #6821 --- app/lib/activitypub/activity/create.rb | 2 +- app/lib/ostatus/activity/creation.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 5a1c13d67..676e885c0 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -53,7 +53,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity visibility: visibility_from_audience, thread: replied_to_status, conversation: conversation_from_uri(@object['conversation']), - media_attachments: process_attachments.take(4), + media_attachment_ids: process_attachments.take(4).map(&:id), } end diff --git a/app/lib/ostatus/activity/creation.rb b/app/lib/ostatus/activity/creation.rb index aa46267dc..6235127b2 100644 --- a/app/lib/ostatus/activity/creation.rb +++ b/app/lib/ostatus/activity/creation.rb @@ -45,7 +45,7 @@ class OStatus::Activity::Creation < OStatus::Activity::Base visibility: visibility_scope, conversation: find_or_create_conversation, thread: thread? ? find_status(thread.first) || find_activitypub_status(thread.first, thread.second) : nil, - media_attachments: media_attachments + media_attachment_ids: media_attachments.map(&:id) ) save_mentions(status) From 74c39fada0e3d02836f85316077c5d1dc2e44588 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 19 Mar 2018 12:20:57 +0100 Subject: [PATCH 19/41] Bump version to 2.3.2rc3 --- lib/mastodon/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index fefe63276..78a2dd901 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -21,7 +21,7 @@ module Mastodon end def flags - 'rc2' + 'rc3' end def to_a From f7c46fc1138ff573c482e0c3059a2e7be43ef07e Mon Sep 17 00:00:00 2001 From: "Renato \"Lond\" Cerqueira" Date: Mon, 19 Mar 2018 15:12:06 +0100 Subject: [PATCH 20/41] Weblate translations 20180319 (#6827) * Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (280 of 280 strings) Translation: Mastodon/React Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/pt_BR/ * Translated using Weblate (Spanish) Currently translated at 99.6% (579 of 581 strings) Translation: Mastodon/Backend Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/es/ * Translated using Weblate (Spanish) Currently translated at 100.0% (58 of 58 strings) Translation: Mastodon/Preferences Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/es/ * Translated using Weblate (Japanese) Currently translated at 100.0% (280 of 280 strings) Translation: Mastodon/React Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/ja/ * Translated using Weblate (French) Currently translated at 100.0% (280 of 280 strings) Translation: Mastodon/React Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/fr/ * Translated using Weblate (Spanish) Currently translated at 100.0% (58 of 58 strings) Translation: Mastodon/Preferences Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/es/ * Translated using Weblate (Indonesian) Currently translated at 100.0% (280 of 280 strings) Translation: Mastodon/React Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/id/ * Translated using Weblate (Spanish) Currently translated at 100.0% (280 of 280 strings) Translation: Mastodon/React Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/es/ * Translated using Weblate (Indonesian) Currently translated at 94.6% (71 of 75 strings) Translation: Mastodon/Doorkeeper Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/doorkeeper/id/ * Translated using Weblate (Indonesian) Currently translated at 100.0% (280 of 280 strings) Translation: Mastodon/React Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/id/ * Translated using Weblate (Arabic) Currently translated at 100.0% (62 of 62 strings) Translation: Mastodon/Devise Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/devise/ar/ * Translated using Weblate (Indonesian) Currently translated at 100.0% (280 of 280 strings) Translation: Mastodon/React Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/id/ * Translated using Weblate (Dutch) Currently translated at 100.0% (280 of 280 strings) Translation: Mastodon/React Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/nl/ * Translated using Weblate (Arabic) Currently translated at 75.5% (439 of 581 strings) Translation: Mastodon/Backend Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ar/ * Translated using Weblate (Arabic) Currently translated at 76.2% (443 of 581 strings) Translation: Mastodon/Backend Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ar/ * Translated using Weblate (Russian) Currently translated at 95.8% (557 of 581 strings) Translation: Mastodon/Backend Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ru/ * Translated using Weblate (Finnish) Currently translated at 100.0% (280 of 280 strings) Translation: Mastodon/React Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/fi/ * Translated using Weblate (Slovak) Currently translated at 100.0% (280 of 280 strings) Translation: Mastodon/React Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/sk/ * Translated using Weblate (Slovak) Currently translated at 91.7% (533 of 581 strings) Translation: Mastodon/Backend Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/sk/ * Translated using Weblate (Dutch) Currently translated at 100.0% (280 of 280 strings) Translation: Mastodon/React Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/nl/ * Translated using Weblate (Spanish) Currently translated at 99.8% (580 of 581 strings) Translation: Mastodon/Backend Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/es/ * Translated using Weblate (Finnish) Currently translated at 100.0% (280 of 280 strings) Translation: Mastodon/React Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/fi/ * Translated using Weblate (Slovak) Currently translated at 100.0% (280 of 280 strings) Translation: Mastodon/React Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/sk/ * Translated using Weblate (Spanish) Currently translated at 100.0% (280 of 280 strings) Translation: Mastodon/React Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/es/ * Translated using Weblate (Swedish) Currently translated at 100.0% (280 of 280 strings) Translation: Mastodon/React Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/sv/ * Translated using Weblate (Finnish) Currently translated at 93.1% (54 of 58 strings) Translation: Mastodon/Preferences Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/fi/ * Translated using Weblate (Arabic) Currently translated at 76.7% (446 of 581 strings) Translation: Mastodon/Backend Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ar/ * Translated using Weblate (Slovak) Currently translated at 93.2% (542 of 581 strings) Translation: Mastodon/Backend Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/sk/ * Translated using Weblate (Arabic) Currently translated at 100.0% (280 of 280 strings) Translation: Mastodon/React Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/ar/ * Normalize translations Ran i18n-tasks normalize && yarn manage:translations --- app/javascript/mastodon/locales/ar.json | 10 +++---- app/javascript/mastodon/locales/fi.json | 20 ++++++------- app/javascript/mastodon/locales/sk.json | 38 ++++++++++++------------ app/javascript/mastodon/locales/sv.json | 12 ++++---- config/locales/ar.yml | 3 ++ config/locales/es.yml | 1 + config/locales/simple_form.fi.yml | 39 +++++++++++++++++++------ config/locales/sk.yml | 14 ++++++++- 8 files changed, 87 insertions(+), 50 deletions(-) diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json index 4928930fe..73680a1a1 100644 --- a/app/javascript/mastodon/locales/ar.json +++ b/app/javascript/mastodon/locales/ar.json @@ -60,10 +60,10 @@ "compose_form.placeholder": "فيمَ تفكّر؟", "compose_form.publish": "بوّق", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.marked": "Media is marked as sensitive", + "compose_form.sensitive.marked": "لقد تم تحديد هذه الصورة كحساسة", "compose_form.sensitive.unmarked": "Media is not marked as sensitive", - "compose_form.spoiler.marked": "Text is hidden behind warning", - "compose_form.spoiler.unmarked": "Text is not hidden", + "compose_form.spoiler.marked": "إنّ النص مخفي وراء تحذير", + "compose_form.spoiler.unmarked": "النص غير مخفي", "compose_form.spoiler_placeholder": "تنبيه عن المحتوى", "confirmation_modal.cancel": "إلغاء", "confirmations.block.confirm": "حجب", @@ -254,9 +254,9 @@ "status.sensitive_warning": "محتوى حساس", "status.share": "مشاركة", "status.show_less": "إعرض أقلّ", - "status.show_less_all": "Show less for all", + "status.show_less_all": "طي الكل", "status.show_more": "أظهر المزيد", - "status.show_more_all": "Show more for all", + "status.show_more_all": "توسيع الكل", "status.unmute_conversation": "فك الكتم عن المحادثة", "status.unpin": "فك التدبيس من الملف الشخصي", "tabs_bar.federated_timeline": "الموحَّد", diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json index 1dea42ed4..1741445ed 100644 --- a/app/javascript/mastodon/locales/fi.json +++ b/app/javascript/mastodon/locales/fi.json @@ -3,7 +3,7 @@ "account.block_domain": "Piilota kaikki sisältö verkkotunnuksesta {domain}", "account.blocked": "Estetty", "account.disclaimer_full": "Alla olevat käyttäjän profiilitiedot saattavat olla epätäydellisiä.", - "account.domain_blocked": "Domain hidden", + "account.domain_blocked": "Verkko-osoite piilotettu", "account.edit_profile": "Muokkaa", "account.follow": "Seuraa", "account.followers": "Seuraajia", @@ -60,10 +60,10 @@ "compose_form.placeholder": "Mitä sinulla on mielessä?", "compose_form.publish": "Toot", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.marked": "Media is marked as sensitive", - "compose_form.sensitive.unmarked": "Media is not marked as sensitive", - "compose_form.spoiler.marked": "Text is hidden behind warning", - "compose_form.spoiler.unmarked": "Text is not hidden", + "compose_form.sensitive.marked": "Media on merkitty arkaluontoiseksi", + "compose_form.sensitive.unmarked": "Mediaa ei ole merkitty arkaluontoiseksi", + "compose_form.spoiler.marked": "Teksti on piilotettu varoituksen taakse", + "compose_form.spoiler.unmarked": "Teksti ei ole piilotettu", "compose_form.spoiler_placeholder": "Content warning", "confirmation_modal.cancel": "Peruuta", "confirmations.block.confirm": "Estä", @@ -182,13 +182,13 @@ "onboarding.page_four.notifications": "Ilmoitukset-sarake näyttää sinulle, kun joku on viestii kanssasi.", "onboarding.page_one.federation": "Mastodon on yhteisöpalvelu, joka toimii monen itsenäisen palvelimen muodostamassa verkossa. Me kutsumme näitä palvelimia instansseiksi.", "onboarding.page_one.full_handle": "Koko käyttäjänimesi", - "onboarding.page_one.handle_hint": "This is what you would tell your friends to search for.", + "onboarding.page_one.handle_hint": "Tämä on se, mitä voisit ehdottaa ystäviäsi etsimään.", "onboarding.page_one.welcome": "Tervetuloa Mastodoniin!", "onboarding.page_six.admin": "Instanssisi ylläpitäjä on {admin}.", "onboarding.page_six.almost_done": "Melkein valmista...", "onboarding.page_six.appetoot": "Bon Appetööt!", "onboarding.page_six.apps_available": "{apps} on saatavilla iOS:lle, Androidille ja muille alustoille.", - "onboarding.page_six.github": "Mastodon is free open-source software. You can report bugs, request features, or contribute to the code on {github}.", + "onboarding.page_six.github": "Mastodon on ilmainen, vapaan lähdekoodin ohjelma. Voit raportoida bugeja, pyytää ominaisuuksia tai osallistua kehittämiseen GitHub-palvelussa: {github}.", "onboarding.page_six.guidelines": "yhteisön säännöt", "onboarding.page_six.read_guidelines": "Ole hyvä ja lue {domain}:n {guidelines}!", "onboarding.page_six.various_app": "mobiilisovellukset", @@ -254,12 +254,12 @@ "status.sensitive_warning": "Arkaluontoista sisältöä", "status.share": "Jaa", "status.show_less": "Näytä vähemmän", - "status.show_less_all": "Show less for all", + "status.show_less_all": "Näytä vähemmän kaikista", "status.show_more": "Näytä lisää", - "status.show_more_all": "Show more for all", + "status.show_more_all": "Näytä enemmän kaikista", "status.unmute_conversation": "Poista mykistys keskustelulta", "status.unpin": "Irrota profiilista", - "tabs_bar.federated_timeline": "Federated", + "tabs_bar.federated_timeline": "Yleinen", "tabs_bar.home": "Koti", "tabs_bar.local_timeline": "Paikallinen", "tabs_bar.notifications": "Ilmoitukset", diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json index 2cb249d2a..683f2aadb 100644 --- a/app/javascript/mastodon/locales/sk.json +++ b/app/javascript/mastodon/locales/sk.json @@ -18,7 +18,7 @@ "account.muted": "Utíšený/á", "account.posts": "Hlášky", "account.posts_with_replies": "Príspevky s odpoveďami", - "account.report": "Nahlásiť @{name}", + "account.report": "Nahlás @{name}", "account.requested": "Čaká na schválenie. Kliknite pre zrušenie žiadosti", "account.share": "Zdieľať @{name} profil", "account.show_reblogs": "Zobraziť povýšenia od @{name}", @@ -35,13 +35,13 @@ "bundle_modal_error.close": "Zatvoriť", "bundle_modal_error.message": "Nastala chyba pri načítaní tohto komponentu.", "bundle_modal_error.retry": "Skúsiť znova", - "column.blocks": "Blokovaní používatelia", + "column.blocks": "Blokovaní užívatelia", "column.community": "Lokálna časová os", "column.favourites": "Obľúbené", "column.follow_requests": "Žiadosti o sledovaní", "column.home": "Domov", "column.lists": "Zoznamy", - "column.mutes": "Ignorovaní používatelia", + "column.mutes": "Ignorovaní užívatelia", "column.notifications": "Notifikácie", "column.pins": "Pripnuté toots", "column.public": "Federovaná časová os", @@ -50,20 +50,20 @@ "column_header.moveLeft_settings": "Presunúť stĺpec doľava", "column_header.moveRight_settings": "Presunúť stĺpec doprava", "column_header.pin": "Pripnúť", - "column_header.show_settings": "Ukázať nastavenia", + "column_header.show_settings": "Ukáž nastavenia", "column_header.unpin": "Odopnúť", "column_subheading.navigation": "Navigácia", "column_subheading.settings": "Nastavenia", - "compose_form.hashtag_warning": "Tento toot nebude zobrazený pod žiadným haštagom lebo nieje listovaný. Iba verejné toots môžu byť nájdené podľa haštagu.", + "compose_form.hashtag_warning": "Tento toot nebude zobrazený pod žiadným haštagom lebo nieje listovaný. Iba verejné tooty môžu byť nájdené podľa haštagu.", "compose_form.lock_disclaimer": "Váš účet nie je zamknutý. Ktokoľvek ťa môže nasledovať a vidieť tvoje správy pre sledujúcich.", "compose_form.lock_disclaimer.lock": "zamknutý", "compose_form.placeholder": "Na čo myslíš?", "compose_form.publish": "Toot", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.marked": "Media is marked as sensitive", - "compose_form.sensitive.unmarked": "Media is not marked as sensitive", - "compose_form.spoiler.marked": "Text is hidden behind warning", - "compose_form.spoiler.unmarked": "Text is not hidden", + "compose_form.sensitive.marked": "Médiálny obsah je označený ako chúlostivý", + "compose_form.sensitive.unmarked": "Médiálny obsah nieje označený ako chúlostivý", + "compose_form.spoiler.marked": "Text je ukrytý za varovaním", + "compose_form.spoiler.unmarked": "Text nieje ukrytý", "compose_form.spoiler_placeholder": "Sem napíšte vaše varovanie", "confirmation_modal.cancel": "Zrušiť", "confirmations.block.confirm": "Blokovať", @@ -101,14 +101,14 @@ "empty_column.list": "Tento zoznam je ešte prázdny. Keď ale členovia tohoto zoznamu napíšu nové správy, tak tie sa objavia priamo tu.", "empty_column.notifications": "Nemáte ešte žiadne notifikácie. Napíšte niekomu, následujte niekoho a komunikujte s ostatnými aby diskusia mohla začať.", "empty_column.public": "Ešte tu nič nie je. Napíšte niečo verejne alebo začnite sledovať používateľov z iných Mastodon serverov aby tu niečo pribudlo", - "follow_request.authorize": "Povoliť prístup", - "follow_request.reject": "Odmietnúť", + "follow_request.authorize": "Povoľ prístup", + "follow_request.reject": "Odmietni", "getting_started.appsshort": "Aplikácie", - "getting_started.faq": "FAQ", - "getting_started.heading": "Začíname", + "getting_started.faq": "Časté otázky", + "getting_started.heading": "Začni tu", "getting_started.open_source_notice": "Mastodon má otvorený kód. Nahlásiť chyby, alebo prispievať vlastným kódom môžete na GitHube v {github}.", "getting_started.userguide": "Používateľská príručka", - "home.column_settings.advanced": "Rozšírené", + "home.column_settings.advanced": "Pokročilé", "home.column_settings.basic": "Základné", "home.column_settings.filter_regex": "Filtrovať použitím regulárnych výrazov", "home.column_settings.show_reblogs": "Zobraziť povýšené", @@ -147,7 +147,7 @@ "missing_indicator.label": "Nenájdené", "missing_indicator.sublabel": "Tento zdroj sa nepodarilo nájsť", "mute_modal.hide_notifications": "Skryť notifikácie od tohoto užívateľa?", - "navigation_bar.blocks": "Blokovaní používatelia", + "navigation_bar.blocks": "Blokovaní užívatelia", "navigation_bar.community_timeline": "Lokálna časová os", "navigation_bar.edit_profile": "Upraviť profil", "navigation_bar.favourites": "Obľúbené", @@ -156,9 +156,9 @@ "navigation_bar.keyboard_shortcuts": "Klávesové skratky", "navigation_bar.lists": "Zoznamy", "navigation_bar.logout": "Odhlásiť", - "navigation_bar.mutes": "Ignorovaní používatelia", + "navigation_bar.mutes": "Ignorovaní užívatelia", "navigation_bar.pins": "Pripnuté toots", - "navigation_bar.preferences": "Možnosti", + "navigation_bar.preferences": "Voľby", "navigation_bar.public_timeline": "Federovaná časová os", "notification.favourite": "{name} sa páči tvoj status", "notification.follow": "{name} ťa začal/a následovať", @@ -254,9 +254,9 @@ "status.sensitive_warning": "Chúlostivý obsah", "status.share": "Zdieľať", "status.show_less": "Zobraz menej", - "status.show_less_all": "Show less for all", + "status.show_less_all": "Všetkým ukáž menej", "status.show_more": "Zobraz viac", - "status.show_more_all": "Show more for all", + "status.show_more_all": "Všetkým ukáž viac", "status.unmute_conversation": "Prestať ignorovať konverzáciu", "status.unpin": "Odopnúť z profilu", "tabs_bar.federated_timeline": "Federovaná", diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json index 3451212d0..4fa129173 100644 --- a/app/javascript/mastodon/locales/sv.json +++ b/app/javascript/mastodon/locales/sv.json @@ -60,10 +60,10 @@ "compose_form.placeholder": "Vad funderar du på?", "compose_form.publish": "Toot", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.marked": "Media is marked as sensitive", - "compose_form.sensitive.unmarked": "Media is not marked as sensitive", - "compose_form.spoiler.marked": "Text is hidden behind warning", - "compose_form.spoiler.unmarked": "Text is not hidden", + "compose_form.sensitive.marked": "Media har markerats som känsligt", + "compose_form.sensitive.unmarked": "Media har inte markerats som känsligt", + "compose_form.spoiler.marked": "Texten har dolts bakom en varning", + "compose_form.spoiler.unmarked": "Texten är inte dold", "compose_form.spoiler_placeholder": "Skriv din varning här", "confirmation_modal.cancel": "Ångra", "confirmations.block.confirm": "Blockera", @@ -254,9 +254,9 @@ "status.sensitive_warning": "Känsligt innehåll", "status.share": "Dela", "status.show_less": "Visa mindre", - "status.show_less_all": "Show less for all", + "status.show_less_all": "Visa mindre för alla", "status.show_more": "Visa mer", - "status.show_more_all": "Show more for all", + "status.show_more_all": "Visa mer för alla", "status.unmute_conversation": "Öppna konversation", "status.unpin": "Ångra fäst i profil", "tabs_bar.federated_timeline": "Förenad", diff --git a/config/locales/ar.yml b/config/locales/ar.yml index ad674a346..e6447cab3 100644 --- a/config/locales/ar.yml +++ b/config/locales/ar.yml @@ -513,6 +513,8 @@ ar: over_character_limit: تم تجاوز حد الـ %{max} حرف المسموح بها pin_errors: ownership: لا يمكن تدبيس تبويق نشره شخص آخر + private: لا يمكن تثبيت تبويق لم يُنشر للعامة + reblog: لا يمكن تثبيت ترقية show_more: أظهر المزيد title: '%{name} : "%{quote}"' visibilities: @@ -524,6 +526,7 @@ ar: unlisted_long: يُمكن لأيٍ كان رُؤيتَه و لكن لن يُعرَض على الخيوط العامة stream_entries: click_to_show: إضغط للعرض + pinned: تبويق مثبّت reblogged: رقى sensitive_content: محتوى حساس terms: diff --git a/config/locales/es.yml b/config/locales/es.yml index d5ba1777b..671f17d33 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -275,6 +275,7 @@ es: username: Nombre de usuario hero: desc_html: Mostrado en la página principal. Recomendable al menos 600x100px. Por defecto se establece a la miniatura de la instancia + title: Imagen de portada peers_api_enabled: desc_html: Nombres de dominio que esta instancia ha encontrado en el fediverso title: Publicar lista de instancias descubiertas diff --git a/config/locales/simple_form.fi.yml b/config/locales/simple_form.fi.yml index a5cded1ce..34605c4f6 100644 --- a/config/locales/simple_form.fi.yml +++ b/config/locales/simple_form.fi.yml @@ -4,13 +4,19 @@ fi: hints: defaults: avatar: PNG, GIF tai JPG. Korkeintaan 2MB. Skaalataan kokoon 400x400px - digest: Lähetetään vain pitkän poissaolon jälkeen, ja vain jos olet vastaanottanut yksityisviestejä poissaolosi aikana. + digest: Lähetetään vain pitkän poissaolon jälkeen, ja vain jos olet vastaanottanut yksityisviestejä poissaolosi aikana display_name: Korkeintaan 30 merkkiä header: PNG, GIF tai JPG. Korkeintaan 2MB. Skaalataan kokoon 700x335px - locked: Vaatii sinun manuaalisesti hyväksymään seuraajat, ja asettaa julkaisujen yksityisyyden vain seuraajille + locked: Vaatii sinua manuaalisesti hyväksymään seuraajat note: Korkeintaan 160 merkkiä + setting_noindex: Vaikuttaa julkiseen profiiliisi ja statuspäivityksiisi + setting_theme: Vaikuttaa siihen, miltä Mastodon näyttää kun olet kirjautuneena milllä tahansa laitteella. imports: - data: CSV tiedosto tuotu toiselta Mastodon palvelimelta + data: CSV tiedosto, joka on tuotu toiselta Mastodon-palvelimelta + sessions: + otp: Syötä kaksivaiheisen tunnistuksen koodi puhelimestasi tai käytä yhtä palautuskoodeistasi. + user: + filtered_languages: Valitut kielet suodatetaan julkisilta aikajanoilta labels: defaults: avatar: Profiilikuva @@ -18,22 +24,37 @@ fi: confirm_password: Varmista salasana current_password: Nykyinen salasana data: Data - display_name: Näykyvä nimi + display_name: Nimimerkki email: Sähköpostiosoite - header: Otsake + expires_in: Vanhentuu + filtered_languages: Suodatetut kielet + header: Otsakekuva locale: Kieli locked: Tee tilistä yksityinen max_uses: Max käyttökerrat new_password: Uusi salasana - note: Bio + note: Kuvaus otp_attempt: Kaksivaiheinen koodi password: Salasana + setting_auto_play_gif: Animoitujen GIFfien automaattitoisto + setting_boost_modal: Näytä vahvistusikkuna ennen boostausta setting_default_privacy: Julkaisun yksityisyys + setting_default_sensitive: Merkitse media aina arkaluontoiseksi + setting_delete_modal: Näytä vahvistusikkuna ennen töötin poistamista + setting_display_sensitive_media: Näytä aina arkaluontoiseksi merkitty media + setting_noindex: Jättäydy pois hakukoneindeksoinnista + setting_reduce_motion: Vähennä liikettä animaatioissa + setting_system_font_ui: Käytä käyttöjärjestelmän oletusfonttia + setting_theme: Sivuston teema + setting_unfollow_modal: Näytä vahvistusikkuna ennen seuraamisen lopettamista + severity: Vakavuusaste type: Tuontityyppi username: Käyttäjänimi + username_or_email: Käyttäjänimi tai sähköposti interactions: - must_be_follower: Estä ilmoitukset käyttäjiltä jotka eivät seuraa sinua - must_be_following: Estä ilmoitukset käyttäjiltä joita et seuraa + must_be_follower: Estä ilmoitukset käyttäjiltä, jotka eivät seuraa sinua + must_be_following: Estä ilmoitukset käyttäjiltä, joita et seuraa + must_be_following_dm: Estä suorat viestit ihmisiltä, joita et seuraa notification_emails: digest: Lähetä koosteviestejä sähköpostilla favourite: Lähetä sähköposti, kun joku tykkää statuksestasi @@ -44,5 +65,5 @@ fi: 'no': Ei required: mark: "*" - text: vaaditaan + text: pakollinen tieto 'yes': Kyllä diff --git a/config/locales/sk.yml b/config/locales/sk.yml index dd8120193..e391974c6 100644 --- a/config/locales/sk.yml +++ b/config/locales/sk.yml @@ -593,7 +593,7 @@ sk: title: Sezóna settings: authorized_apps: Autorizované aplikácie - back: Naspäť na stránku + back: Späť do Mastodonu delete: Zmazanie účtu development: Vývoj edit_profile: Upraviť profil @@ -630,8 +630,15 @@ sk: title: Podmienky užívania, a pravidlá o súkromí pre %{instance} two_factor_authentication: enable: Povoliť + enabled: Dvoj-faktorové overovanie je povolené + enabled_success: Dvoj-faktorové overovanie bolo úspešne povolené generate_recovery_codes: Vygeneruj zálohové kódy + lost_recovery_codes: Zálohové kódy ti umožnia dostať sa k svojmu účtu ak stratíš telefón. Pokiaľ si stratila svoje zálohové kódy, môžeš si ich tu znovu vygenerovať. Tvoje staré zálohové kódy budú zneplatnené. + manual_instructions: 'Pokiaľ nemôžeš oskenovať daný QR kód, a potrebuješ ho zadať ručne, tu je tajomstvo v textovom formáte:' + recovery_codes: Zálohuj kódy pre obnovu + recovery_codes_regenerated: Zálohové kódy boli úspešne zvova vygenerované setup: Nastavenie + wrong_code: Zadaný kód bol neplatný. Je serverový čas a čas na zariadení správny? user_mailer: backup_ready: explanation: Vyžiadal/a si si úplnú zálohu tvojho Mastodon účtu. Táto záloha je teraz pripravená na stiahnutie! @@ -639,12 +646,17 @@ sk: title: Odber archívu welcome: edit_profile_action: Nastav profil + edit_profile_step: Profil si môžeš prispôsobiť nahratím portrétu a hlavičky, môžeš upraviť svoje meno a viac. Pokiaľ chceš preverovať nových následovateľov predtým než ťa budú môcť sledovať, môžeš uzamknúť svoj účet. explanation: Tu nájdeš nejaké tipy do začiatku final_action: Začni prispievať final_step: 'Začnite písať! Aj bez následovníkov budú vaše verejné správy videné ostatnými, napríklad na lokálnej osi a pod haštagmi. Môžete sa ostatným predstaviť pod haštagom #introductions.' full_handle: Adresa tvojho profilu v celom formáte + full_handle_hint: Toto je čo musíš dať vedieť svojím priateľom aby ti mohli posielať správy, alebo ťa následovať z inej instancie. review_preferences_action: Zmeniť nastavenia subject: Vitaj na Mastodone + tip_bridge_html: Ak prichádzaš z Twitteru, môžeš svojích priateľov nájsť na Mastodone pomocou tzv. mostíkovej aplikácie. Ale tá funguje iba ak ju aj oni niekedy použili! + tip_federated_timeline: Federovaná os zobrazuje sieť Mastodonu až po jej hranice. Ale zahŕňa iba ľúdí ktorých ostatní okolo teba sledujú, takže predsa nieje úplne celistvá. + tip_following: Správcu servera následuješ automaticky. Môžeš ale nájsť mnoho iných zaujímavých ľudí ak prezrieš tak lokálnu, ako aj globálne federovanú os. tip_local_timeline: Lokálna os je celkový pohľad na aktivitu užívateľov %{instance}. Toto sú tvoji najbližší susedia! tip_mobile_webapp: Pokiaľ ti prehliadač ponúkne možnosť pridať Mastodon na tvoju obrazovku, môžeš potom dostávať notifikácie skoro ako z natívnej aplikácie! tips: Tipy From 357f9298bdb595f67b1f89292be9fa4268e1bffd Mon Sep 17 00:00:00 2001 From: ThibG Date: Mon, 19 Mar 2018 20:07:47 +0100 Subject: [PATCH 21/41] Fix e-mail changed notification (fixes #6778) (#6835) In Devise::Mailer#email_changed, the new email might be in the email attr. See: https://github.com/plataformatec/devise/blob/master/app/views/devise/mailer/email_changed.html.erb --- app/views/user_mailer/email_changed.html.haml | 2 +- app/views/user_mailer/email_changed.text.erb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/user_mailer/email_changed.html.haml b/app/views/user_mailer/email_changed.html.haml index 7e82f23e4..0802aaf96 100644 --- a/app/views/user_mailer/email_changed.html.haml +++ b/app/views/user_mailer/email_changed.html.haml @@ -38,7 +38,7 @@ %table.input{ align: 'center', cellspacing: 0, cellpadding: 0 } %tbody %tr - %td= @resource.unconfirmed_email + %td= @resource.try(:unconfirmed_email) ? @resource.unconfirmed_email : @resource.email %table.email-table{ cellspacing: 0, cellpadding: 0 } %tbody diff --git a/app/views/user_mailer/email_changed.text.erb b/app/views/user_mailer/email_changed.text.erb index 2b58415f5..345b16a2c 100644 --- a/app/views/user_mailer/email_changed.text.erb +++ b/app/views/user_mailer/email_changed.text.erb @@ -4,6 +4,6 @@ <%= t 'devise.mailer.email_changed.explanation' %> -<%= @resource.unconfirmed_email %> +<%= @resource.try(:unconfirmed_email) ? @resource.unconfirmed_email : @resource.email %> <%= t 'devise.mailer.email_changed.extra' %> From 0306e3e9bebe0b0d9ad7e5fe328dd3677717b7e5 Mon Sep 17 00:00:00 2001 From: Alexander Date: Mon, 19 Mar 2018 20:08:56 +0100 Subject: [PATCH 22/41] bugfixes and gem update (#6831) * update to new version of devise_pam_authenticatable2 * fix behaviour if suffix is nil, fix environment loading, fix user email creation * code cleanup/fix linter warning --- Gemfile | 4 +++- Gemfile.lock | 4 ++-- app/models/user.rb | 32 +++++++++++++++++--------------- config/application.rb | 2 ++ 4 files changed, 24 insertions(+), 18 deletions(-) diff --git a/Gemfile b/Gemfile index 3fce2ddc7..fe5bf572c 100644 --- a/Gemfile +++ b/Gemfile @@ -32,7 +32,9 @@ gem 'cld3', '~> 3.2.0' gem 'devise', '~> 4.4' gem 'devise-two-factor', '~> 3.0' -gem 'devise_pam_authenticatable2', '~> 8.0', install_if: -> { ENV['PAM_ENABLED'] == 'true' } +group :pam_authentication, optional: true do + gem 'devise_pam_authenticatable2', '~> 9.0' +end gem 'net-ldap', '~> 0.10' gem 'omniauth-cas', '~> 1.1' gem 'omniauth-saml', '~> 1.10' diff --git a/Gemfile.lock b/Gemfile.lock index 0640b140b..ca6365c74 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -141,7 +141,7 @@ GEM devise (~> 4.0) railties (< 5.2) rotp (~> 2.0) - devise_pam_authenticatable2 (8.0.1) + devise_pam_authenticatable2 (9.0.0) devise (>= 4.0.0) rpam2 (~> 3.0) diff-lcs (1.3) @@ -631,7 +631,7 @@ DEPENDENCIES climate_control (~> 0.2) devise (~> 4.4) devise-two-factor (~> 3.0) - devise_pam_authenticatable2 (~> 8.0) + devise_pam_authenticatable2 (~> 9.0) doorkeeper (~> 4.2) dotenv-rails (~> 2.2) fabrication (~> 2.18) diff --git a/app/models/user.rb b/app/models/user.rb index b716c13fd..2d5f145fa 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -52,6 +52,8 @@ class User < ApplicationRecord devise :registerable, :recoverable, :rememberable, :trackable, :validatable, :confirmable + devise :pam_authenticatable if ENV['PAM_ENABLED'] == 'true' + devise :omniauthable belongs_to :account, inverse_of: :user @@ -96,7 +98,7 @@ class User < ApplicationRecord def pam_conflict? return false unless Devise.pam_authentication - encrypted_password.present? && is_pam_account? + encrypted_password.present? && pam_managed_user? end def pam_get_name @@ -267,22 +269,22 @@ class User < ApplicationRecord end def self.pam_get_user(attributes = {}) - if attributes[:email] - resource = - if Devise.check_at_sign && !attributes[:email].index('@') - joins(:account).find_by(accounts: { username: attributes[:email] }) - else - find_by(email: attributes[:email]) - end - - if resource.blank? - resource = new(email: attributes[:email]) - if Devise.check_at_sign && !resource[:email].index('@') - resource[:email] = "#{attributes[:email]}@#{resource.find_pam_suffix}" - end + return nil unless attributes[:email] + resource = + if Devise.check_at_sign && !attributes[:email].index('@') + joins(:account).find_by(accounts: { username: attributes[:email] }) + else + find_by(email: attributes[:email]) + end + + if resource.blank? + resource = new(email: attributes[:email]) + if Devise.check_at_sign && !resource[:email].index('@') + resource[:email] = Rpam2.getenv(resource.find_pam_service, attributes[:email], attributes[:password], 'email', false) + resource[:email] = "#{attributes[:email]}@#{resource.find_pam_suffix}" unless resource[:email] end - resource end + resource end def self.ldap_get_user(attributes = {}) diff --git a/config/application.rb b/config/application.rb index 097cbf567..326a0ec8c 100644 --- a/config/application.rb +++ b/config/application.rb @@ -16,6 +16,8 @@ require_relative '../lib/devise/ldap_authenticatable' Dotenv::Railtie.load +Bundler.require(:pam_authentication) if ENV['PAM_ENABLED'] == 'true' + require_relative '../lib/mastodon/redis_config' module Mastodon From 33ee347c995515946e0a045394fe693875ee1cdf Mon Sep 17 00:00:00 2001 From: Alexander Date: Mon, 19 Mar 2018 20:09:26 +0100 Subject: [PATCH 23/41] rename pam email environment variable to something more understandable and default to LOCAL_DOMAIN (better fallback) (#6833) --- .env.production.sample | 4 ++-- config/initializers/devise.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.env.production.sample b/.env.production.sample index 579ad667b..1e5ed9f3d 100644 --- a/.env.production.sample +++ b/.env.production.sample @@ -155,8 +155,8 @@ STREAMING_CLUSTER_NUM=1 # The pam environment variable "email" is provided by: # https://github.com/devkral/pam_email_extractor # PAM_ENABLED=true -# Fallback Suffix for email address generation (nil by default) -# PAM_DEFAULT_SUFFIX=pam +# Fallback email domain for email address generation (LOCAL_DOMAIN by default) +# PAM_EMAIL_DOMAIN=example.com # Name of the pam service (pam "auth" section is evaluated) # PAM_DEFAULT_SERVICE=rpam # Name of the pam service used for checking if an user can register (pam "account" section is evaluated) (nil (disabled) by default) diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index df45dcd1f..97757d0fb 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -342,7 +342,7 @@ Devise.setup do |config| config.usernamefield = nil config.emailfield = 'email' config.check_at_sign = true - config.pam_default_suffix = ENV.fetch('PAM_DEFAULT_SUFFIX') { nil } + config.pam_default_suffix = ENV.fetch('PAM_EMAIL_DOMAIN') { ENV['LOCAL_DOMAIN'] } config.pam_default_service = ENV.fetch('PAM_DEFAULT_SERVICE') { 'rpam' } config.pam_controlled_service = ENV.fetch('PAM_CONTROLLED_SERVICE') { nil } end From 6b76a6212d8aa596379115b248ec145905946c42 Mon Sep 17 00:00:00 2001 From: ThibG Date: Mon, 19 Mar 2018 20:12:20 +0100 Subject: [PATCH 24/41] Display content warning in mail notification emails (#6832) --- app/views/notification_mailer/_status.html.haml | 5 +++++ app/views/notification_mailer/_status.text.erb | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/app/views/notification_mailer/_status.html.haml b/app/views/notification_mailer/_status.html.haml index f82ada146..57b5688bd 100644 --- a/app/views/notification_mailer/_status.html.haml +++ b/app/views/notification_mailer/_status.html.haml @@ -24,6 +24,11 @@ %bdi= display_name(status.account) = "@#{status.account.acct}" + - if status.spoiler_text? + %div{ dir: rtl_status?(status) ? 'rtl' : 'ltr' } + %p + = Formatter.instance.format_spoiler(status) + %div{ dir: rtl_status?(status) ? 'rtl' : 'ltr' } = Formatter.instance.format(status) diff --git a/app/views/notification_mailer/_status.text.erb b/app/views/notification_mailer/_status.text.erb index 85a0136b7..8999a1f8e 100644 --- a/app/views/notification_mailer/_status.text.erb +++ b/app/views/notification_mailer/_status.text.erb @@ -1,3 +1,8 @@ +<% if status.spoiler_text? %> +<%= raw status.spoiler_text %> +---- + +<% end %> <%= raw Formatter.instance.plaintext(status) %> <%= raw t('application_mailer.view')%> <%= web_url("statuses/#{status.id}") %> From ff6b8a6443c2c97d185927053bdc8816e0e03434 Mon Sep 17 00:00:00 2001 From: ThibG Date: Mon, 19 Mar 2018 20:19:35 +0100 Subject: [PATCH 25/41] Serialize mentions in the order they are added (#6836) Up until now, the order seemed to be in the *opposite* order, which caused the WebUI to populate mentions in reversed order when replying to toots local to one's instance. --- app/lib/ostatus/atom_serializer.rb | 2 +- app/serializers/activitypub/note_serializer.rb | 2 +- app/serializers/rest/status_serializer.rb | 6 +++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/lib/ostatus/atom_serializer.rb b/app/lib/ostatus/atom_serializer.rb index 656e45822..46d0a8b37 100644 --- a/app/lib/ostatus/atom_serializer.rb +++ b/app/lib/ostatus/atom_serializer.rb @@ -351,7 +351,7 @@ class OStatus::AtomSerializer append_element(entry, 'summary', status.spoiler_text, 'xml:lang': status.language) if status.spoiler_text? append_element(entry, 'content', Formatter.instance.format(status).to_str, type: 'html', 'xml:lang': status.language) - status.mentions.each do |mentioned| + status.mentions.order(:id).each do |mentioned| append_element(entry, 'link', nil, rel: :mentioned, 'ostatus:object-type': OStatus::TagManager::TYPES[:person], href: OStatus::TagManager.instance.uri_for(mentioned.account)) end diff --git a/app/serializers/activitypub/note_serializer.rb b/app/serializers/activitypub/note_serializer.rb index d0e6290c1..abaf29047 100644 --- a/app/serializers/activitypub/note_serializer.rb +++ b/app/serializers/activitypub/note_serializer.rb @@ -57,7 +57,7 @@ class ActivityPub::NoteSerializer < ActiveModel::Serializer end def virtual_tags - object.mentions + object.tags + object.emojis + object.mentions.order(:id) + object.tags + object.emojis end def atom_uri diff --git a/app/serializers/rest/status_serializer.rb b/app/serializers/rest/status_serializer.rb index e6270f902..67da92cd5 100644 --- a/app/serializers/rest/status_serializer.rb +++ b/app/serializers/rest/status_serializer.rb @@ -15,7 +15,7 @@ class REST::StatusSerializer < ActiveModel::Serializer belongs_to :account, serializer: REST::AccountSerializer has_many :media_attachments, serializer: REST::MediaAttachmentSerializer - has_many :mentions + has_many :ordered_mentions, key: :mentions has_many :tags has_many :emojis, serializer: REST::CustomEmojiSerializer @@ -86,6 +86,10 @@ class REST::StatusSerializer < ActiveModel::Serializer %w(public unlisted).include?(object.visibility) end + def ordered_mentions + object.mentions.order(:id) + end + class ApplicationSerializer < ActiveModel::Serializer attributes :name, :website end From 36b57037961383466b7f5c20b39ee68cd9f202a0 Mon Sep 17 00:00:00 2001 From: Rey Tucker Date: Tue, 20 Mar 2018 04:06:08 -0400 Subject: [PATCH 26/41] request: in the event of failure, try other IPs (#6761) (#6813) * request: in the event of failure, try other IPs (#6761) In the case where a name has multiple A/AAAA records, we should try subsequent records instead of immediately failing when we have a failure on the first IP address. This significantly improves delivery success when there are network connectivity problems affecting only IPv4 or IPv6. * fix method call style * request_spec: adjust test case to use Addrinfo * request: Request/open: move private addr check to within begin/rescue * request_spec: add case to test failover, fix exception check * Double Addrinfo.foreach so that it correctly yields instances --- app/lib/request.rb | 13 ++++++++++--- spec/lib/request_spec.rb | 11 ++++++++++- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/app/lib/request.rb b/app/lib/request.rb index 5776b3d78..298fb9528 100644 --- a/app/lib/request.rb +++ b/app/lib/request.rb @@ -94,9 +94,16 @@ class Request class Socket < TCPSocket class << self def open(host, *args) - address = IPSocket.getaddress(host) - raise Mastodon::HostValidationError if PrivateAddressCheck.private_address? IPAddr.new(address) - super address, *args + outer_e = nil + Addrinfo.foreach(host, nil, nil, :SOCK_STREAM) do |address| + begin + raise Mastodon::HostValidationError if PrivateAddressCheck.private_address? IPAddr.new(address.ip_address) + return super address.ip_address, *args + rescue => e + outer_e = e + end + end + raise outer_e if outer_e end alias new open diff --git a/spec/lib/request_spec.rb b/spec/lib/request_spec.rb index dc7daa52c..5da357c55 100644 --- a/spec/lib/request_spec.rb +++ b/spec/lib/request_spec.rb @@ -48,6 +48,13 @@ describe Request do expect(a_request(:get, 'http://example.com')).to have_been_made.once end + it 'executes a HTTP request when the first address is private' do + allow(Addrinfo).to receive(:foreach).with('example.com', nil, nil, :SOCK_STREAM) + .and_yield(Addrinfo.new(["AF_INET", 0, "example.com", "0.0.0.0"], :PF_INET, :SOCK_STREAM)) + .and_yield(Addrinfo.new(["AF_INET6", 0, "example.com", "2001:4860:4860::8844"], :PF_INET6, :SOCK_STREAM)) + expect(a_request(:get, 'http://example.com')).to have_been_made.once + end + it 'sets headers' do expect(a_request(:get, 'http://example.com').with(headers: subject.headers)).to have_been_made end @@ -61,7 +68,9 @@ describe Request do end it 'raises Mastodon::ValidationError' do - allow(IPSocket).to receive(:getaddress).with('example.com').and_return('0.0.0.0') + allow(Addrinfo).to receive(:foreach).with('example.com', nil, nil, :SOCK_STREAM) + .and_yield(Addrinfo.new(["AF_INET", 0, "example.com", "0.0.0.0"], :PF_INET, :SOCK_STREAM)) + .and_yield(Addrinfo.new(["AF_INET6", 0, "example.com", "2001:db8::face"], :PF_INET6, :SOCK_STREAM)) expect{ subject.perform }.to raise_error Mastodon::ValidationError end end From a5c6c748e096f61d00bbd778a263e22117e1ae9f Mon Sep 17 00:00:00 2001 From: ThibG Date: Tue, 20 Mar 2018 12:40:12 +0100 Subject: [PATCH 27/41] Cancel outdated pending compose suggestions (#6838) --- app/javascript/mastodon/actions/compose.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/javascript/mastodon/actions/compose.js b/app/javascript/mastodon/actions/compose.js index 130b4af23..1371f22b2 100644 --- a/app/javascript/mastodon/actions/compose.js +++ b/app/javascript/mastodon/actions/compose.js @@ -1,4 +1,5 @@ import api from '../api'; +import { CancelToken } from 'axios'; import { throttle } from 'lodash'; import { search as emojiSearch } from '../features/emoji/emoji_mart_search_light'; import { tagHistory } from '../settings'; @@ -11,6 +12,8 @@ import { refreshPublicTimeline, } from './timelines'; +let cancelFetchComposeSuggestionsAccounts; + export const COMPOSE_CHANGE = 'COMPOSE_CHANGE'; export const COMPOSE_SUBMIT_REQUEST = 'COMPOSE_SUBMIT_REQUEST'; export const COMPOSE_SUBMIT_SUCCESS = 'COMPOSE_SUBMIT_SUCCESS'; @@ -257,13 +260,22 @@ export function undoUploadCompose(media_id) { }; export function clearComposeSuggestions() { + if (cancelFetchComposeSuggestionsAccounts) { + cancelFetchComposeSuggestionsAccounts(); + } return { type: COMPOSE_SUGGESTIONS_CLEAR, }; }; const fetchComposeSuggestionsAccounts = throttle((dispatch, getState, token) => { + if (cancelFetchComposeSuggestionsAccounts) { + cancelFetchComposeSuggestionsAccounts(); + } api(getState).get('/api/v1/accounts/search', { + cancelToken: new CancelToken(cancel => { + cancelFetchComposeSuggestionsAccounts = cancel; + }), params: { q: token.slice(1), resolve: false, From 9381a7d9d55ea734d6c498a82d17d73fd02fbe87 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Tue, 20 Mar 2018 14:57:46 +0100 Subject: [PATCH 28/41] Use username/domain to match existing accounts in ActivityPub (#6842) See also: #6837, #6667 --- app/services/activitypub/process_account_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/activitypub/process_account_service.rb b/app/services/activitypub/process_account_service.rb index 68e9db766..7d8dc1369 100644 --- a/app/services/activitypub/process_account_service.rb +++ b/app/services/activitypub/process_account_service.rb @@ -16,7 +16,7 @@ class ActivityPub::ProcessAccountService < BaseService RedisLock.acquire(lock_options) do |lock| if lock.acquired? - @account = Account.find_by(uri: @uri) + @account = Account.find_remote(@username, @domain) @old_public_key = @account&.public_key @old_protocol = @account&.protocol From 61dcb686a8f0a3272e2948c9a072aa58593a7409 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Wed, 21 Mar 2018 00:36:20 +0900 Subject: [PATCH 29/41] Fix i18n fallback configuration conflicts with environment configurations (#6843) --- config/application.rb | 4 +--- config/environments/production.rb | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/config/application.rb b/config/application.rb index 326a0ec8c..385bd4704 100644 --- a/config/application.rb +++ b/config/application.rb @@ -76,9 +76,7 @@ module Mastodon ] config.i18n.default_locale = ENV['DEFAULT_LOCALE']&.to_sym - if config.i18n.available_locales.include?(config.i18n.default_locale) - config.i18n.fallbacks = [:en] - else + unless config.i18n.available_locales.include?(config.i18n.default_locale) config.i18n.default_locale = :en end diff --git a/config/environments/production.rb b/config/environments/production.rb index 3136a40fc..f372cd363 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -55,8 +55,8 @@ Rails.application.configure do # config.action_mailer.raise_delivery_errors = false # Enable locale fallbacks for I18n (makes lookups for any locale fall back to - # the I18n.default_locale when a translation cannot be found). - config.i18n.fallbacks = true + # English when a translation cannot be found). + config.i18n.fallbacks = [:en] # Send deprecation notices to registered listeners. config.active_support.deprecation = :notify From ac49c7932d848fbb946c37a69f42b7dbc774c56c Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Tue, 20 Mar 2018 19:41:51 +0100 Subject: [PATCH 30/41] Add LDAP_TLS_NO_VERIFY option, don't require LDAP_ENABLED outside .env (#6845) Fix #6816, fix #6790 --- config/initializers/devise.rb | 3 ++ lib/devise/ldap_authenticatable.rb | 76 ++++++++++++++++-------------- 2 files changed, 43 insertions(+), 36 deletions(-) diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 97757d0fb..e0d263f16 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -55,6 +55,8 @@ module Devise @@ldap_bind_dn = nil mattr_accessor :ldap_password @@ldap_password = nil + mattr_accessor :ldap_tls_no_verify + @@ldap_tls_no_verify = false class Strategies::PamAuthenticatable def valid? @@ -357,5 +359,6 @@ Devise.setup do |config| config.ldap_bind_dn = ENV.fetch('LDAP_BIND_DN') config.ldap_password = ENV.fetch('LDAP_PASSWORD') config.ldap_uid = ENV.fetch('LDAP_UID', 'cn') + config.ldap_tls_no_verify = ENV['LDAP_TLS_NO_VERIFY'] == 'true' end end diff --git a/lib/devise/ldap_authenticatable.rb b/lib/devise/ldap_authenticatable.rb index 531abdbbe..ef786fbb7 100644 --- a/lib/devise/ldap_authenticatable.rb +++ b/lib/devise/ldap_authenticatable.rb @@ -1,49 +1,53 @@ # frozen_string_literal: true -if ENV['LDAP_ENABLED'] == 'true' - require 'net/ldap' - require 'devise/strategies/authenticatable' +require 'net/ldap' +require 'devise/strategies/authenticatable' - module Devise - module Strategies - class LdapAuthenticatable < Authenticatable - def authenticate! - if params[:user] - ldap = Net::LDAP.new( - host: Devise.ldap_host, - port: Devise.ldap_port, - base: Devise.ldap_base, - encryption: { - method: Devise.ldap_method, - tls_options: OpenSSL::SSL::SSLContext::DEFAULT_PARAMS, - }, - auth: { - method: :simple, - username: Devise.ldap_bind_dn, - password: Devise.ldap_password, - }, - connect_timeout: 10 - ) +module Devise + module Strategies + class LdapAuthenticatable < Authenticatable + def authenticate! + if params[:user] + ldap = Net::LDAP.new( + host: Devise.ldap_host, + port: Devise.ldap_port, + base: Devise.ldap_base, + encryption: { + method: Devise.ldap_method, + tls_options: tls_options, + }, + auth: { + method: :simple, + username: Devise.ldap_bind_dn, + password: Devise.ldap_password, + }, + connect_timeout: 10 + ) - if (user_info = ldap.bind_as(base: Devise.ldap_base, filter: "(#{Devise.ldap_uid}=#{email})", password: password)) - user = User.ldap_get_user(user_info.first) - success!(user) - else - return fail(:invalid_login) - end + if (user_info = ldap.bind_as(base: Devise.ldap_base, filter: "(#{Devise.ldap_uid}=#{email})", password: password)) + user = User.ldap_get_user(user_info.first) + success!(user) + else + return fail(:invalid_login) end end + end - def email - params[:user][:email] - end + def email + params[:user][:email] + end - def password - params[:user][:password] + def password + params[:user][:password] + end + + def tls_options + OpenSSL::SSL::SSLContext::DEFAULT_PARAMS.tap do |options| + options[:verify_mode] = OpenSSL::SSL::VERIFY_NONE if Devise.ldap_tls_no_verify end end end end - - Warden::Strategies.add(:ldap_authenticatable, Devise::Strategies::LdapAuthenticatable) end + +Warden::Strategies.add(:ldap_authenticatable, Devise::Strategies::LdapAuthenticatable) From f64af6473fd1c61190ede960791efddc29806f92 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Tue, 20 Mar 2018 23:49:24 +0100 Subject: [PATCH 31/41] Bump version to 2.3.2rc4 --- lib/mastodon/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index 78a2dd901..80650761a 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -21,7 +21,7 @@ module Mastodon end def flags - 'rc3' + 'rc4' end def to_a From a6b59cd1a32ce2d9ac54fa7b5e04672a63692fdf Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Wed, 21 Mar 2018 18:26:15 +0900 Subject: [PATCH 32/41] Remove debug option from Babel preset env (#6852) --- .babelrc | 1 - 1 file changed, 1 deletion(-) diff --git a/.babelrc b/.babelrc index ed28aa500..190b5038c 100644 --- a/.babelrc +++ b/.babelrc @@ -4,7 +4,6 @@ [ "env", { - "debug": true, "exclude": ["transform-async-to-generator", "transform-regenerator"], "loose": true, "modules": false, From 93897134caf42f1b70620282cef04865af7026b1 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 21 Mar 2018 10:26:53 +0100 Subject: [PATCH 33/41] Permit dots in usernames with conditions (#6844) * Permit dots in usernames with conditions - Dot cannot be the start or end of username - a.lice and al.ice are considered the same during sign-up * Fix regex mixin flags --- app/models/account.rb | 6 ++++-- app/validators/unique_username_validator.rb | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 app/validators/unique_username_validator.rb diff --git a/app/models/account.rb b/app/models/account.rb index c1347fe65..14269860f 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -47,7 +47,8 @@ # class Account < ApplicationRecord - MENTION_RE = /(?<=^|[^\/[:word:]])@(([a-z0-9_]+)(?:@[a-z0-9\.\-]+[a-z0-9]+)?)/i + USERNAME_RE = /[a-z0-9_]+([a-z0-9_\.]+[a-z0-9_]+)?/i + MENTION_RE = /(?<=^|[^\/[:word:]])@((#{USERNAME_RE}?)(?:@[a-z0-9\.\-]+[a-z0-9]+)?)/i include AccountAvatar include AccountFinderConcern @@ -68,7 +69,8 @@ class Account < ApplicationRecord validates :username, uniqueness: { scope: :domain, case_sensitive: true }, if: -> { !local? && will_save_change_to_username? } # Local user validations - validates :username, format: { with: /\A[a-z0-9_]+\z/i }, uniqueness: { scope: :domain, case_sensitive: false }, length: { maximum: 30 }, if: -> { local? && will_save_change_to_username? } + validates :username, format: { with: /\A#{USERNAME_RE}\z/i }, length: { maximum: 30 }, if: -> { local? && will_save_change_to_username? } + validates_with UniqueUsernameValidator, if: -> { local? && will_save_change_to_username? } validates_with UnreservedUsernameValidator, if: -> { local? && will_save_change_to_username? } validates :display_name, length: { maximum: 30 }, if: -> { local? && will_save_change_to_display_name? } validates :note, length: { maximum: 160 }, if: -> { local? && will_save_change_to_note? } diff --git a/app/validators/unique_username_validator.rb b/app/validators/unique_username_validator.rb new file mode 100644 index 000000000..c76407b16 --- /dev/null +++ b/app/validators/unique_username_validator.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class UniqueUsernameValidator < ActiveModel::Validator + def validate(account) + return if account.username.nil? + + normalized_username = account.username.downcase.delete('.') + + scope = Account.where(domain: nil, username: normalized_username) + scope = scope.where.not(id: account.id) if account.persisted? + + account.errors.add(:username, :taken) if scope.exists? + end +end From d97903a3587e137316adbd8a9f0460552b5bfbcd Mon Sep 17 00:00:00 2001 From: Patrick Figel Date: Wed, 21 Mar 2018 17:43:28 +0100 Subject: [PATCH 34/41] Update sanitize and loofah (#6855) Fixes CVE-2018-8048 and CVE-2018-3740, two medium-severity XSS vulnerabilities present in these gems when built against libxml2 >= 2.9.2. --- Gemfile | 2 +- Gemfile.lock | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Gemfile b/Gemfile index fe5bf572c..8bc28b893 100644 --- a/Gemfile +++ b/Gemfile @@ -71,7 +71,7 @@ gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock' gem 'rqrcode', '~> 0.10' gem 'ruby-oembed', '~> 0.12', require: 'oembed' gem 'ruby-progressbar', '~> 1.4' -gem 'sanitize', '~> 4.4' +gem 'sanitize', '~> 4.6.4' gem 'sidekiq', '~> 5.0' gem 'sidekiq-scheduler', '~> 2.1' gem 'sidekiq-unique-jobs', '~> 5.0' diff --git a/Gemfile.lock b/Gemfile.lock index ca6365c74..7360ce7f6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -288,7 +288,7 @@ GEM activesupport (>= 4, < 5.2) railties (>= 4, < 5.2) request_store (~> 1.0) - loofah (2.1.1) + loofah (2.2.1) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.0) @@ -316,9 +316,9 @@ GEM net-ssh (>= 2.6.5) net-ssh (4.2.0) nio4r (2.1.0) - nokogiri (1.8.1) + nokogiri (1.8.2) mini_portile2 (~> 2.3.0) - nokogumbo (1.4.13) + nokogumbo (1.5.0) nokogiri nsa (0.2.4) activesupport (>= 4.2, < 6) @@ -496,10 +496,10 @@ GEM rufus-scheduler (3.4.2) et-orbi (~> 1.0) safe_yaml (1.0.4) - sanitize (4.5.0) + sanitize (4.6.4) crass (~> 1.0.2) nokogiri (>= 1.4.4) - nokogumbo (~> 1.4.1) + nokogumbo (~> 1.4) sass (3.5.3) sass-listen (~> 4.0.0) sass-listen (4.0.0) @@ -699,7 +699,7 @@ DEPENDENCIES rubocop ruby-oembed (~> 0.12) ruby-progressbar (~> 1.4) - sanitize (~> 4.4) + sanitize (~> 4.6.4) scss_lint (~> 0.55) sidekiq (~> 5.0) sidekiq-bulk (~> 0.1.1) From f66a7860291e6b2fef1844b580c22296dbad9202 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 22 Mar 2018 09:33:14 +0100 Subject: [PATCH 35/41] Hide floating action button on thread views (#6859) --- .../mastodon/features/ui/components/columns_area.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/javascript/mastodon/features/ui/components/columns_area.js b/app/javascript/mastodon/features/ui/components/columns_area.js index e82c46402..05cdb4e3b 100644 --- a/app/javascript/mastodon/features/ui/components/columns_area.js +++ b/app/javascript/mastodon/features/ui/components/columns_area.js @@ -28,6 +28,8 @@ const componentMap = { 'LIST': ListTimeline, }; +const shouldHideFAB = path => path.match(/^\/statuses\//); + @component => injectIntl(component, { withRef: true }) export default class ColumnsArea extends ImmutablePureComponent { @@ -153,7 +155,7 @@ export default class ColumnsArea extends ImmutablePureComponent { this.pendingIndex = null; if (singleColumn) { - const floatingActionButton = this.context.router.history.location.pathname === '/statuses/new' ? null : ; + const floatingActionButton = shouldHideFAB(this.context.router.history.location.pathname) ? null : ; return columnIndex !== -1 ? [ From 6f531d140b8398a4680567934fe66cb0ca465fbc Mon Sep 17 00:00:00 2001 From: ThibG Date: Thu, 22 Mar 2018 10:45:48 +0100 Subject: [PATCH 36/41] Fix MENTION_RE to not match nil usernames (#6862) --- app/models/account.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/account.rb b/app/models/account.rb index 14269860f..c88c6ec44 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -48,7 +48,7 @@ class Account < ApplicationRecord USERNAME_RE = /[a-z0-9_]+([a-z0-9_\.]+[a-z0-9_]+)?/i - MENTION_RE = /(?<=^|[^\/[:word:]])@((#{USERNAME_RE}?)(?:@[a-z0-9\.\-]+[a-z0-9]+)?)/i + MENTION_RE = /(?<=^|[^\/[:word:]])@((#{USERNAME_RE})(?:@[a-z0-9\.\-]+[a-z0-9]+)?)/i include AccountAvatar include AccountFinderConcern From da70aca28eaa68f21c450c8f7b6ecb6168d29941 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 22 Mar 2018 11:30:22 +0100 Subject: [PATCH 37/41] Restore username validation to disallow dots, for now (#6863) Usernames with dots in them do not work with routes, because the dot usually separates the desired page format (e.g. json). I don't want to mess with changing route constraints for this patch release. --- app/models/account.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/account.rb b/app/models/account.rb index c88c6ec44..9a83d979f 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -69,7 +69,7 @@ class Account < ApplicationRecord validates :username, uniqueness: { scope: :domain, case_sensitive: true }, if: -> { !local? && will_save_change_to_username? } # Local user validations - validates :username, format: { with: /\A#{USERNAME_RE}\z/i }, length: { maximum: 30 }, if: -> { local? && will_save_change_to_username? } + validates :username, format: { with: /\A[a-z0-9_]+\z/i }, length: { maximum: 30 }, if: -> { local? && will_save_change_to_username? } validates_with UniqueUsernameValidator, if: -> { local? && will_save_change_to_username? } validates_with UnreservedUsernameValidator, if: -> { local? && will_save_change_to_username? } validates :display_name, length: { maximum: 30 }, if: -> { local? && will_save_change_to_display_name? } From 9fe1619db94e3267b263633ecd4d05a840064215 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 22 Mar 2018 11:31:17 +0100 Subject: [PATCH 38/41] Do not re-query mentions from serializers (#6858) Fix performance regression from #6836 --- app/serializers/activitypub/note_serializer.rb | 2 +- app/serializers/rest/status_serializer.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/serializers/activitypub/note_serializer.rb b/app/serializers/activitypub/note_serializer.rb index abaf29047..ddafb540d 100644 --- a/app/serializers/activitypub/note_serializer.rb +++ b/app/serializers/activitypub/note_serializer.rb @@ -57,7 +57,7 @@ class ActivityPub::NoteSerializer < ActiveModel::Serializer end def virtual_tags - object.mentions.order(:id) + object.tags + object.emojis + object.mentions.to_a.sort_by(&:id) + object.tags + object.emojis end def atom_uri diff --git a/app/serializers/rest/status_serializer.rb b/app/serializers/rest/status_serializer.rb index 67da92cd5..fe3dc9bfc 100644 --- a/app/serializers/rest/status_serializer.rb +++ b/app/serializers/rest/status_serializer.rb @@ -87,7 +87,7 @@ class REST::StatusSerializer < ActiveModel::Serializer end def ordered_mentions - object.mentions.order(:id) + object.mentions.to_a.sort_by(&:id) end class ApplicationSerializer < ActiveModel::Serializer From dafae9818da27573fdd872cfdb8680fdbca3fdd8 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 22 Mar 2018 11:31:52 +0100 Subject: [PATCH 39/41] Bump version to 2.3.2rc5 --- lib/mastodon/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index 80650761a..035aafa9d 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -21,7 +21,7 @@ module Mastodon end def flags - 'rc4' + 'rc5' end def to_a From 6cc432bbc4b6ba64f71e559e7614144c2610eda1 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 22 Mar 2018 14:13:46 +0100 Subject: [PATCH 40/41] Bump version to 2.3.2 --- lib/mastodon/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index 035aafa9d..121c5c693 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -21,7 +21,7 @@ module Mastodon end def flags - 'rc5' + '' end def to_a From 9924ca88106fff34eb0ed105f394c20f9197a69c Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Tue, 27 Mar 2018 00:44:10 +0200 Subject: [PATCH 41/41] Fix UniqueUsernameValidator comparison Comparison was downcasing only one side, therefore if previously existing account had a non-lowercase spelling, it would be ignored when checking for duplicates. New rake task `mastodon:maintenance:find_duplicate_usernames` will help find constraint violations that might have occured from the presence of this bug. Bump version to 2.3.3 --- app/models/concerns/account_finder_concern.rb | 2 +- app/validators/unique_username_validator.rb | 2 +- lib/mastodon/version.rb | 2 +- lib/tasks/mastodon.rake | 18 ++++++++++++++++++ 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/app/models/concerns/account_finder_concern.rb b/app/models/concerns/account_finder_concern.rb index 2e8a7fb37..6b7237e89 100644 --- a/app/models/concerns/account_finder_concern.rb +++ b/app/models/concerns/account_finder_concern.rb @@ -30,7 +30,7 @@ module AccountFinderConcern end def account - scoped_accounts.take + scoped_accounts.order(id: :asc).take end private diff --git a/app/validators/unique_username_validator.rb b/app/validators/unique_username_validator.rb index c76407b16..fb67105dd 100644 --- a/app/validators/unique_username_validator.rb +++ b/app/validators/unique_username_validator.rb @@ -6,7 +6,7 @@ class UniqueUsernameValidator < ActiveModel::Validator normalized_username = account.username.downcase.delete('.') - scope = Account.where(domain: nil, username: normalized_username) + scope = Account.where(domain: nil).where('lower(username) = ?', normalized_username) scope = scope.where.not(id: account.id) if account.persisted? account.errors.add(:username, :taken) if scope.exists? diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index 121c5c693..a6927eec3 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -13,7 +13,7 @@ module Mastodon end def patch - 2 + 3 end def pre diff --git a/lib/tasks/mastodon.rake b/lib/tasks/mastodon.rake index cf32b1495..18bdc347f 100644 --- a/lib/tasks/mastodon.rake +++ b/lib/tasks/mastodon.rake @@ -740,6 +740,24 @@ namespace :mastodon do LinkCrawlWorker.push_bulk status_ids end + desc 'Find case-insensitive username duplicates of local users' + task find_duplicate_usernames: :environment do + include RoutingHelper + + disable_log_stdout! + + duplicate_masters = Account.find_by_sql('SELECT * FROM accounts WHERE id IN (SELECT min(id) FROM accounts WHERE domain IS NULL GROUP BY lower(username) HAVING count(*) > 1)') + pastel = Pastel.new + + duplicate_masters.each do |account| + puts pastel.yellow("First of their name: ") + pastel.bold(account.username) + " (#{admin_account_url(account.id)})" + + Account.where('lower(username) = ?', account.username.downcase).where.not(id: account.id).each do |duplicate| + puts " " + pastel.red("Duplicate: ") + admin_account_url(duplicate.id) + end + end + end + desc 'Remove all home feed regeneration markers' task remove_regeneration_markers: :environment do keys = Redis.current.keys('account:*:regeneration')