about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md31
-rw-r--r--Dockerfile21
-rw-r--r--Gemfile13
-rw-r--r--Gemfile.lock63
-rw-r--r--app/controllers/accounts_controller.rb2
-rw-r--r--app/controllers/api/v1/announcements_controller.rb2
-rw-r--r--app/controllers/api/v1/statuses/bookmarks_controller.rb27
-rw-r--r--app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb3
-rw-r--r--app/controllers/api/v1/statuses/favourites_controller.rb26
-rw-r--r--app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb3
-rw-r--r--app/controllers/api/v1/statuses/reblogs_controller.rb27
-rw-r--r--app/controllers/auth/registrations_controller.rb3
-rw-r--r--app/javascript/flavours/glitch/components/error_boundary.js22
-rw-r--r--app/javascript/flavours/glitch/features/compose/components/compose_form.js12
-rw-r--r--app/javascript/flavours/glitch/features/compose/components/publisher.js8
-rw-r--r--app/javascript/flavours/glitch/features/keyboard_shortcuts/index.js4
-rw-r--r--app/javascript/flavours/glitch/util/base_polyfills.js3
-rw-r--r--app/javascript/flavours/glitch/util/load_polyfills.js3
-rw-r--r--app/javascript/flavours/glitch/util/main.js2
-rw-r--r--app/javascript/mastodon/base_polyfills.js3
-rw-r--r--app/javascript/mastodon/components/error_boundary.js25
-rw-r--r--app/javascript/mastodon/load_polyfills.js3
-rw-r--r--app/javascript/mastodon/main.js2
-rw-r--r--app/models/account.rb11
-rw-r--r--app/services/activitypub/process_account_service.rb7
-rw-r--r--app/services/backup_service.rb2
-rw-r--r--app/services/follow_service.rb5
-rw-r--r--app/services/resolve_account_service.rb2
-rw-r--r--app/views/admin/accounts/show.html.haml6
-rw-r--r--app/views/auth/registrations/new.html.haml2
-rw-r--r--app/views/authorize_interactions/show.html.haml6
-rw-r--r--config/locales/en.yml1
-rw-r--r--lib/mastodon/accounts_cli.rb7
-rw-r--r--lib/mastodon/migration_helpers.rb8
-rw-r--r--lib/mastodon/redis_config.rb4
-rw-r--r--lib/mastodon/version.rb2
-rw-r--r--lib/tasks/mastodon.rake15
-rw-r--r--package.json34
-rw-r--r--spec/controllers/api/v1/statuses/bookmarks_controller_spec.rb67
-rw-r--r--spec/controllers/api/v1/statuses/favourites_controller_spec.rb86
-rw-r--r--spec/controllers/api/v1/statuses/reblogs_controller_spec.rb86
-rw-r--r--spec/controllers/auth/registrations_controller_spec.rb28
-rw-r--r--yarn.lock399
43 files changed, 660 insertions, 426 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 84e08341e..33663c2ad 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,37 @@ Changelog
 
 All notable changes to this project will be documented in this file.
 
+## [v3.1.2] - 2020-02-27
+### Added
+
+- Add `--reset-password` option to `tootctl accounts modify` ([ThibG](https://github.com/tootsuite/mastodon/pull/13126))
+- Add source-mapped stacktrace to error message in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/13082))
+
+### Fixed
+
+- Fix dismissing an announcement twice raising an obscure error ([ThibG](https://github.com/tootsuite/mastodon/pull/13124))
+- Fix misleading error when attempting to re-send a pending follow request ([ThibG](https://github.com/tootsuite/mastodon/pull/13133))
+- Fix backups failing when files are missing from media attachments ([ThibG](https://github.com/tootsuite/mastodon/pull/13146))
+- Fix duplicate accounts being created when fetching an account for its key only ([ThibG](https://github.com/tootsuite/mastodon/pull/13147))
+- Fix `/web` redirecting to `/web/web` in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/13128))
+- Fix previously OStatus-based accounts not being detected as ActivityPub ([ThibG](https://github.com/tootsuite/mastodon/pull/13129))
+- Fix account JSON/RSS not being cacheable due to wrong mime type comparison ([ThibG](https://github.com/tootsuite/mastodon/pull/13116))
+- Fix old browsers crashing because of missing `finally` polyfill in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/13115))
+- Fix account's bio not being shown if there are no proofs/fields in admin UI ([ThibG](https://github.com/tootsuite/mastodon/pull/13075))
+- Fix sign-ups without checked user agreement being accepted through the web form ([ThibG](https://github.com/tootsuite/mastodon/pull/13088))
+- Fix non-x64 architectures not being able to build Docker image because of hardcoded Node.js architecture ([SaraSmiseth](https://github.com/tootsuite/mastodon/pull/13081))
+- Fix invite request input not being shown on sign-up error if left empty ([ThibG](https://github.com/tootsuite/mastodon/pull/13089))
+- Fix some migration hints mentioning GitLab instead of Mastodon ([saper](https://github.com/tootsuite/mastodon/pull/13084))
+
+### Security
+
+- Fix leak of arbitrary statuses through unfavourite action in REST API ([Gargron](https://github.com/tootsuite/mastodon/pull/13161))
+
+## [3.1.1] - 2020-02-10
+### Fixed
+
+- Fix yanked dependency preventing installation ([mayaeh](https://github.com/tootsuite/mastodon/pull/13059))
+
 ## [3.1.0] - 2020-02-09
 ### Added
 
diff --git a/Dockerfile b/Dockerfile
index e36ed13ba..eeaad758f 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -5,14 +5,25 @@ SHELL ["bash", "-c"]
 
 # Install Node v12 (LTS)
 ENV NODE_VER="12.14.0"  
-RUN	echo "Etc/UTC" > /etc/localtime && \
+RUN	ARCH= && \
+    dpkgArch="$(dpkg --print-architecture)" && \
+  case "${dpkgArch##*-}" in \
+    amd64) ARCH='x64';; \
+    ppc64el) ARCH='ppc64le';; \
+    s390x) ARCH='s390x';; \
+    arm64) ARCH='arm64';; \
+    armhf) ARCH='armv7l';; \
+    i386) ARCH='x86';; \
+    *) echo "unsupported architecture"; exit 1 ;; \
+  esac && \
+    echo "Etc/UTC" > /etc/localtime && \
 	apt update && \
 	apt -y install wget python && \
 	cd ~ && \
-	wget https://nodejs.org/download/release/v$NODE_VER/node-v$NODE_VER-linux-x64.tar.gz && \
-	tar xf node-v$NODE_VER-linux-x64.tar.gz && \
-	rm node-v$NODE_VER-linux-x64.tar.gz && \
-	mv node-v$NODE_VER-linux-x64 /opt/node
+	wget https://nodejs.org/download/release/v$NODE_VER/node-v$NODE_VER-linux-$ARCH.tar.gz && \
+	tar xf node-v$NODE_VER-linux-$ARCH.tar.gz && \
+	rm node-v$NODE_VER-linux-$ARCH.tar.gz && \
+	mv node-v$NODE_VER-linux-$ARCH /opt/node
 
 # Install jemalloc
 ENV JE_VER="5.2.1"
diff --git a/Gemfile b/Gemfile
index 8a36db08d..852def278 100644
--- a/Gemfile
+++ b/Gemfile
@@ -9,7 +9,7 @@ gem 'puma', '~> 4.3'
 gem 'rails', '~> 5.2.4'
 gem 'sprockets', '~> 3.7.2'
 gem 'thor', '~> 0.20'
-gem 'rack', '~> 2.1.2'
+gem 'rack', '~> 2.2.2'
 
 gem 'thwait', '~> 0.1.0'
 gem 'e2mmap', '~> 0.1.0'
@@ -56,7 +56,6 @@ gem 'goldfinger', '~> 2.1'
 gem 'hiredis', '~> 0.6'
 gem 'redis-namespace', '~> 1.7'
 gem 'health_check', git: 'https://github.com/ianheggie/health_check', ref: '0b799ead604f900ed50685e9b2d469cd2befba5b'
-gem 'html2text'
 gem 'htmlentities', '~> 4.3'
 gem 'http', '~> 4.3'
 gem 'http_accept_language', '~> 2.1'
@@ -102,7 +101,7 @@ gem 'webpacker', '~> 4.2'
 gem 'webpush'
 
 gem 'json-ld'
-gem 'json-ld-preloaded', '~> 3.0'
+gem 'json-ld-preloaded', '~> 3.1'
 gem 'rdf-normalize', '~> 0.4'
 
 gem 'redcarpet', '~> 3.4'
@@ -111,7 +110,7 @@ group :development, :test do
   gem 'fabrication', '~> 2.21'
   gem 'fuubar', '~> 2.5'
   gem 'i18n-tasks', '~> 0.9', require: false
-  gem 'pry-byebug', '~> 3.7'
+  gem 'pry-byebug', '~> 3.8'
   gem 'pry-rails', '~> 0.3'
   gem 'rspec-rails', '~> 3.9'
 end
@@ -121,13 +120,13 @@ group :production, :test do
 end
 
 group :test do
-  gem 'capybara', '~> 3.30'
+  gem 'capybara', '~> 3.31'
   gem 'climate_control', '~> 0.2'
   gem 'faker', '~> 2.10'
   gem 'microformats', '~> 4.2'
   gem 'rails-controller-testing', '~> 1.0'
   gem 'rspec-sidekiq', '~> 3.0'
-  gem 'simplecov', '~> 0.17', require: false
+  gem 'simplecov', '~> 0.18', require: false
   gem 'webmock', '~> 3.8'
   gem 'parallel_tests', '~> 2.30'
 end
@@ -139,7 +138,7 @@ group :development do
   gem 'binding_of_caller', '~> 0.7'
   gem 'bullet', '~> 6.1'
   gem 'letter_opener', '~> 1.7'
-  gem 'letter_opener_web', '~> 1.3'
+  gem 'letter_opener_web', '~> 1.4'
   gem 'memory_profiler'
   gem 'rubocop', '~> 0.79', require: false
   gem 'rubocop-rails', '~> 2.4', require: false
diff --git a/Gemfile.lock b/Gemfile.lock
index e33748197..16871e8e3 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -127,7 +127,7 @@ GEM
     bundler-audit (0.6.1)
       bundler (>= 1.2.0, < 3)
       thor (~> 0.18)
-    byebug (11.0.0)
+    byebug (11.1.1)
     capistrano (3.11.2)
       airbrussh (>= 1.0.0)
       i18n
@@ -144,7 +144,7 @@ GEM
       sshkit (~> 1.3)
     capistrano-yarn (2.0.2)
       capistrano (~> 3.0)
-    capybara (3.30.0)
+    capybara (3.31.0)
       addressable
       mini_mime (>= 0.1.3)
       nokogiri (~> 1.8)
@@ -202,14 +202,14 @@ GEM
       dotenv (= 2.7.5)
       railties (>= 3.2, < 6.1)
     e2mmap (0.1.0)
-    elasticsearch (7.3.0)
-      elasticsearch-api (= 7.3.0)
-      elasticsearch-transport (= 7.3.0)
-    elasticsearch-api (7.3.0)
+    elasticsearch (7.5.0)
+      elasticsearch-api (= 7.5.0)
+      elasticsearch-transport (= 7.5.0)
+    elasticsearch-api (7.5.0)
       multi_json
     elasticsearch-dsl (0.1.8)
-    elasticsearch-transport (7.3.0)
-      faraday
+    elasticsearch-transport (7.5.0)
+      faraday (>= 0.14, < 1)
       multi_json
     encryptor (3.0.0)
     equatable (0.6.1)
@@ -220,7 +220,7 @@ GEM
     fabrication (2.21.0)
     faker (2.10.1)
       i18n (>= 1.6, < 2)
-    faraday (1.0.0)
+    faraday (0.17.3)
       multipart-post (>= 1.2, < 3)
     fast_blank (1.0.0)
     fastimage (2.1.7)
@@ -270,8 +270,6 @@ GEM
     highline (2.0.3)
     hiredis (0.6.3)
     hkdf (0.3.0)
-    html2text (0.2.1)
-      nokogiri (~> 1.6)
     htmlentities (4.3.4)
     http (4.3.0)
       addressable (~> 2.3)
@@ -313,10 +311,9 @@ GEM
       multi_json (~> 1.14)
       rack (~> 2.0)
       rdf (~> 3.1)
-    json-ld-preloaded (3.0.6)
-      json-ld (~> 3.0)
-      multi_json (~> 1.12)
-      rdf (~> 3.0)
+    json-ld-preloaded (3.1.0)
+      json-ld (~> 3.1)
+      rdf (~> 3.1)
     jsonapi-renderer (0.2.2)
     jwt (2.1.0)
     kaminari (1.1.1)
@@ -335,7 +332,7 @@ GEM
       addressable (~> 2.3)
     letter_opener (1.7.0)
       launchy (~> 2.2)
-    letter_opener_web (1.3.4)
+    letter_opener_web (1.4.0)
       actionmailer (>= 3.2)
       letter_opener (~> 1.0)
       railties (>= 3.2)
@@ -377,7 +374,7 @@ GEM
       net-ssh (>= 2.6.5, < 6.0.0)
     net-ssh (5.2.0)
     nio4r (2.5.2)
-    nokogiri (1.10.7)
+    nokogiri (1.10.8)
       mini_portile2 (~> 2.4.0)
     nokogumbo (2.0.1)
       nokogiri (~> 1.8, >= 1.8.4)
@@ -420,7 +417,7 @@ GEM
     pg (1.2.2)
     pghero (2.4.1)
       activerecord (>= 5)
-    pkg-config (1.4.0)
+    pkg-config (1.4.1)
     premailer (1.11.1)
       addressable
       css_parser (>= 1.6.0)
@@ -432,18 +429,18 @@ GEM
     pry (0.12.2)
       coderay (~> 1.1.0)
       method_source (~> 0.9.0)
-    pry-byebug (3.7.0)
+    pry-byebug (3.8.0)
       byebug (~> 11.0)
       pry (~> 0.10)
     pry-rails (0.3.9)
       pry (>= 0.10.4)
     public_suffix (4.0.3)
-    puma (4.3.1)
+    puma (4.3.2)
       nio4r (~> 2.0)
     pundit (2.1.0)
       activesupport (>= 3.0.0)
     raabro (1.1.6)
-    rack (2.1.2)
+    rack (2.2.2)
     rack-attack (6.2.2)
       rack (>= 1.0, < 3)
     rack-cors (1.1.1)
@@ -494,7 +491,7 @@ GEM
       link_header (~> 0.0, >= 0.0.8)
     rdf-normalize (0.4.0)
       rdf (~> 3.1)
-    redcarpet (3.4.0)
+    redcarpet (3.5.0)
     redis (4.1.3)
     redis-actionpack (5.0.2)
       actionpack (>= 4.0, < 6)
@@ -553,7 +550,7 @@ GEM
       rainbow (>= 2.2.2, < 4.0)
       ruby-progressbar (~> 1.7)
       unicode-display_width (>= 1.4.0, < 1.7)
-    rubocop-rails (2.4.1)
+    rubocop-rails (2.4.2)
       rack (>= 1.1)
       rubocop (>= 0.72.0)
     ruby-progressbar (1.10.1)
@@ -587,11 +584,10 @@ GEM
     simple_form (5.0.1)
       actionpack (>= 5.0)
       activemodel (>= 5.0)
-    simplecov (0.17.1)
+    simplecov (0.18.2)
       docile (~> 1.1)
-      json (>= 1.8, < 3)
-      simplecov-html (~> 0.10.0)
-    simplecov-html (0.10.2)
+      simplecov-html (~> 0.11)
+    simplecov-html (0.12.0)
     sprockets (3.7.2)
       concurrent-ruby (~> 1.0)
       rack (> 1, < 3)
@@ -683,7 +679,7 @@ DEPENDENCIES
   capistrano-rails (~> 1.4)
   capistrano-rbenv (~> 2.1)
   capistrano-yarn (~> 2.0)
-  capybara (~> 3.30)
+  capybara (~> 3.31)
   charlock_holmes (~> 0.7.7)
   chewy (~> 5.1)
   cld3 (~> 3.2.6)
@@ -708,7 +704,6 @@ DEPENDENCIES
   hamlit-rails (~> 0.2)
   health_check!
   hiredis (~> 0.6)
-  html2text
   htmlentities (~> 4.3)
   http (~> 4.3)
   http_accept_language (~> 2.1)
@@ -718,10 +713,10 @@ DEPENDENCIES
   idn-ruby
   iso-639
   json-ld
-  json-ld-preloaded (~> 3.0)
+  json-ld-preloaded (~> 3.1)
   kaminari (~> 1.1)
   letter_opener (~> 1.7)
-  letter_opener_web (~> 1.3)
+  letter_opener_web (~> 1.4)
   link_header (~> 0.0)
   lograge (~> 0.11)
   makara (~> 0.4)
@@ -749,11 +744,11 @@ DEPENDENCIES
   posix-spawn!
   premailer-rails
   private_address_check (~> 0.5)
-  pry-byebug (~> 3.7)
+  pry-byebug (~> 3.8)
   pry-rails (~> 0.3)
   puma (~> 4.3)
   pundit (~> 2.1)
-  rack (~> 2.1.2)
+  rack (~> 2.2.2)
   rack-attack (~> 6.2)
   rack-cors (~> 1.1)
   rails (~> 5.2.4)
@@ -778,7 +773,7 @@ DEPENDENCIES
   sidekiq-unique-jobs (~> 6.0)
   simple-navigation (~> 4.1)
   simple_form (~> 5.0)
-  simplecov (~> 0.17)
+  simplecov (~> 0.18)
   sprockets (~> 3.7.2)
   sprockets-rails (~> 3.2)
   stackprof
diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb
index c4ee22847..ee48da177 100644
--- a/app/controllers/accounts_controller.rb
+++ b/app/controllers/accounts_controller.rb
@@ -9,7 +9,7 @@ class AccountsController < ApplicationController
   before_action :set_cache_headers
   before_action :set_body_classes
 
-  skip_around_action :set_locale, if: -> { [:json, :rss].include?(request.format) }
+  skip_around_action :set_locale, if: -> { [:json, :rss].include?(request.format&.to_sym) }
   skip_before_action :require_functional!
 
   def show
diff --git a/app/controllers/api/v1/announcements_controller.rb b/app/controllers/api/v1/announcements_controller.rb
index 1e692ff75..ee79fc19f 100644
--- a/app/controllers/api/v1/announcements_controller.rb
+++ b/app/controllers/api/v1/announcements_controller.rb
@@ -11,7 +11,7 @@ class Api::V1::AnnouncementsController < Api::BaseController
   end
 
   def dismiss
-    AnnouncementMute.create!(account: current_account, announcement: @announcement)
+    AnnouncementMute.find_or_create_by!(account: current_account, announcement: @announcement)
     render_empty
   end
 
diff --git a/app/controllers/api/v1/statuses/bookmarks_controller.rb b/app/controllers/api/v1/statuses/bookmarks_controller.rb
index bb9729cf5..a7f1eed00 100644
--- a/app/controllers/api/v1/statuses/bookmarks_controller.rb
+++ b/app/controllers/api/v1/statuses/bookmarks_controller.rb
@@ -5,35 +5,28 @@ class Api::V1::Statuses::BookmarksController < Api::BaseController
 
   before_action -> { doorkeeper_authorize! :write, :'write:bookmarks' }
   before_action :require_user!
+  before_action :set_status
 
   respond_to :json
 
   def create
-    @status = bookmarked_status
+    current_account.bookmarks.find_or_create_by!(account: current_account, status: @status)
     render json: @status, serializer: REST::StatusSerializer
   end
 
   def destroy
-    @status = requested_status
-    @bookmarks_map = { @status.id => false }
+    bookmark = current_account.bookmarks.find_by(status: @status)
+    bookmark&.destroy!
 
-    bookmark = Bookmark.find_by!(account: current_user.account, status: @status)
-    bookmark.destroy!
-
-    render json: @status, serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new([@status], current_user&.account_id, bookmarks_map: @bookmarks_map)
+    render json: @status, serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new([@status], current_account.id, bookmarks_map: { @status.id => false })
   end
 
   private
 
-  def bookmarked_status
-    authorize_with current_user.account, requested_status, :show?
-
-    bookmark = Bookmark.find_or_create_by!(account: current_user.account, status: requested_status)
-
-    bookmark.status.reload
-  end
-
-  def requested_status
-    Status.find(params[:status_id])
+  def set_status
+    @status = Status.find(params[:status_id])
+    authorize @status, :show?
+  rescue Mastodon::NotPermittedError
+    not_found
   end
 end
diff --git a/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb b/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb
index 99eff360e..05f4acc33 100644
--- a/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb
+++ b/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb
@@ -69,8 +69,7 @@ class Api::V1::Statuses::FavouritedByAccountsController < Api::BaseController
     @status = Status.find(params[:status_id])
     authorize @status, :show?
   rescue Mastodon::NotPermittedError
-    # Reraise in order to get a 404 instead of a 403 error code
-    raise ActiveRecord::RecordNotFound
+    not_found
   end
 
   def pagination_params(core_params)
diff --git a/app/controllers/api/v1/statuses/favourites_controller.rb b/app/controllers/api/v1/statuses/favourites_controller.rb
index cceee9060..f18ace996 100644
--- a/app/controllers/api/v1/statuses/favourites_controller.rb
+++ b/app/controllers/api/v1/statuses/favourites_controller.rb
@@ -5,34 +5,26 @@ class Api::V1::Statuses::FavouritesController < Api::BaseController
 
   before_action -> { doorkeeper_authorize! :write, :'write:favourites' }
   before_action :require_user!
+  before_action :set_status
 
   respond_to :json
 
   def create
-    @status = favourited_status
+    FavouriteService.new.call(current_account, @status)
     render json: @status, serializer: REST::StatusSerializer
   end
 
   def destroy
-    @status = requested_status
-    @favourites_map = { @status.id => false }
-
-    UnfavouriteWorker.perform_async(current_user.account_id, @status.id)
-
-    render json: @status, serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new([@status], current_user&.account_id, favourites_map: @favourites_map)
+    UnfavouriteWorker.perform_async(current_account.id, @status.id)
+    render json: @status, serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new([@status], current_account.id, favourites_map: { @status.id => false })
   end
 
   private
 
-  def favourited_status
-    service_result.status.reload
-  end
-
-  def service_result
-    FavouriteService.new.call(current_user.account, requested_status)
-  end
-
-  def requested_status
-    Status.find(params[:status_id])
+  def set_status
+    @status = Status.find(params[:status_id])
+    authorize @status, :show?
+  rescue Mastodon::NotPermittedError
+    not_found
   end
 end
diff --git a/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb b/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb
index cc285ad23..fa60e7d84 100644
--- a/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb
+++ b/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb
@@ -66,8 +66,7 @@ class Api::V1::Statuses::RebloggedByAccountsController < Api::BaseController
     @status = Status.find(params[:status_id])
     authorize @status, :show?
   rescue Mastodon::NotPermittedError
-    # Reraise in order to get a 404 instead of a 403 error code
-    raise ActiveRecord::RecordNotFound
+    not_found
   end
 
   def pagination_params(core_params)
diff --git a/app/controllers/api/v1/statuses/reblogs_controller.rb b/app/controllers/api/v1/statuses/reblogs_controller.rb
index 42381a37f..67106ccbe 100644
--- a/app/controllers/api/v1/statuses/reblogs_controller.rb
+++ b/app/controllers/api/v1/statuses/reblogs_controller.rb
@@ -5,33 +5,34 @@ class Api::V1::Statuses::ReblogsController < Api::BaseController
 
   before_action -> { doorkeeper_authorize! :write, :'write:statuses' }
   before_action :require_user!
+  before_action :set_reblog
 
   respond_to :json
 
   def create
-    @status = ReblogService.new.call(current_user.account, status_for_reblog, reblog_params)
+    @status = ReblogService.new.call(current_account, @reblog, reblog_params)
     render json: @status, serializer: REST::StatusSerializer
   end
 
   def destroy
-    @status = status_for_destroy.reblog
-    @reblogs_map = { @status.id => false }
+    @status = current_account.statuses.find_by(reblog_of_id: @reblog.id)
 
-    authorize status_for_destroy, :unreblog?
-    status_for_destroy.discard
-    RemovalWorker.perform_async(status_for_destroy.id)
+    if @status
+      authorize @status, :unreblog?
+      @status.discard
+      RemovalWorker.perform_async(@status.id)
+    end
 
-    render json: @status, serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new([@status], current_user&.account_id, reblogs_map: @reblogs_map)
+    render json: @reblog, serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new([@status], current_account.id, reblogs_map: { @reblog.id => false })
   end
 
   private
 
-  def status_for_reblog
-    Status.find params[:status_id]
-  end
-
-  def status_for_destroy
-    @status_for_destroy ||= current_user.account.statuses.where(reblog_of_id: params[:status_id]).first!
+  def set_reblog
+    @reblog = Status.find(params[:status_id])
+    authorize @reblog, :show?
+  rescue Mastodon::NotPermittedError
+    not_found
   end
 
   def reblog_params
diff --git a/app/controllers/auth/registrations_controller.rb b/app/controllers/auth/registrations_controller.rb
index 531df7751..f6a85d87e 100644
--- a/app/controllers/auth/registrations_controller.rb
+++ b/app/controllers/auth/registrations_controller.rb
@@ -42,7 +42,6 @@ class Auth::RegistrationsController < Devise::RegistrationsController
 
     resource.locale             = I18n.locale
     resource.invite_code        = params[:invite_code] if resource.invite_code.blank?
-    resource.agreement          = true
     resource.current_sign_in_ip = request.remote_ip
 
     resource.build_account if resource.account.nil?
@@ -50,7 +49,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController
 
   def configure_sign_up_params
     devise_parameter_sanitizer.permit(:sign_up) do |u|
-      u.permit({ account_attributes: [:username], invite_request_attributes: [:text] }, :email, :password, :password_confirmation, :invite_code)
+      u.permit({ account_attributes: [:username], invite_request_attributes: [:text] }, :email, :password, :password_confirmation, :invite_code, :agreement)
     end
   end
 
diff --git a/app/javascript/flavours/glitch/components/error_boundary.js b/app/javascript/flavours/glitch/components/error_boundary.js
index 62950a7d3..8998802b1 100644
--- a/app/javascript/flavours/glitch/components/error_boundary.js
+++ b/app/javascript/flavours/glitch/components/error_boundary.js
@@ -2,6 +2,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import { FormattedMessage } from 'react-intl';
 import { preferencesLink } from 'flavours/glitch/util/backend_links';
+import StackTrace from 'stacktrace-js';
 
 export default class ErrorBoundary extends React.PureComponent {
 
@@ -11,15 +12,29 @@ export default class ErrorBoundary extends React.PureComponent {
 
   state = {
     hasError: false,
+    errorMessage: undefined,
     stackTrace: undefined,
+    mappedStackTrace: undefined,
     componentStack: undefined,
   }
 
   componentDidCatch(error, info) {
     this.setState({
       hasError: true,
+      errorMessage: error.toString(),
       stackTrace: error.stack,
       componentStack: info && info.componentStack,
+      mappedStackTrace: undefined,
+    });
+
+    StackTrace.fromError(error).then((stackframes) => {
+      this.setState({
+        mappedStackTrace: stackframes.map((sf) => sf.toString()).join('\n'),
+      });
+    }).catch(() => {
+      this.setState({
+        mappedStackTrace: undefined,
+      });
     });
   }
 
@@ -29,13 +44,16 @@ export default class ErrorBoundary extends React.PureComponent {
   }
 
   render() {
-    const { hasError, stackTrace, componentStack } = this.state;
+    const { hasError, errorMessage, stackTrace, mappedStackTrace, componentStack } = this.state;
 
     if (!hasError) return this.props.children;
 
     let debugInfo = '';
     if (stackTrace) {
-      debugInfo += 'Stack trace\n-----------\n\n```\n' + stackTrace.toString() + '\n```';
+      debugInfo += 'Stack trace\n-----------\n\n```\n' + errorMessage + '\n' + stackTrace.toString() + '\n```';
+    }
+    if (mappedStackTrace) {
+      debugInfo += 'Mapped stack trace\n-----------\n\n```\n' + errorMessage + '\n' + mappedStackTrace.toString() + '\n```';
     }
     if (componentStack) {
       if (debugInfo) {
diff --git a/app/javascript/flavours/glitch/features/compose/components/compose_form.js b/app/javascript/flavours/glitch/features/compose/components/compose_form.js
index 6e07998ec..daacbb73f 100644
--- a/app/javascript/flavours/glitch/features/compose/components/compose_form.js
+++ b/app/javascript/flavours/glitch/features/compose/components/compose_form.js
@@ -93,7 +93,7 @@ class ComposeForm extends ImmutablePureComponent {
     }
   }
 
-  handleSubmit = () => {
+  handleSubmit = (overriddenVisibility = null) => {
     const { textarea: { value }, uploadForm } = this;
     const {
       onChange,
@@ -106,6 +106,7 @@ class ComposeForm extends ImmutablePureComponent {
       text,
       mediaDescriptionConfirmation,
       onMediaDescriptionConfirm,
+      onChangeVisibility,
     } = this.props;
 
     //  If something changes inside the textarea, then we update the
@@ -124,6 +125,9 @@ class ComposeForm extends ImmutablePureComponent {
       const firstWithoutDescription = media.find(item => !item.get('description'));
       onMediaDescriptionConfirm(this.context.router ? this.context.router.history : null, firstWithoutDescription.get('id'));
     } else if (onSubmit) {
+      if (onChangeVisibility && overriddenVisibility) {
+        onChangeVisibility(overriddenVisibility);
+      }
       onSubmit(this.context.router ? this.context.router.history : null);
     }
   }
@@ -152,13 +156,9 @@ class ComposeForm extends ImmutablePureComponent {
   //  Handles the secondary submit button.
   handleSecondarySubmit = () => {
     const {
-      onChangeVisibility,
       sideArm,
     } = this.props;
-    if (sideArm !== 'none' && onChangeVisibility) {
-      onChangeVisibility(sideArm);
-    }
-    this.handleSubmit();
+    this.handleSubmit(sideArm === 'none' ? null : sideArm);
   }
 
   //  Selects a suggestion from the autofill.
diff --git a/app/javascript/flavours/glitch/features/compose/components/publisher.js b/app/javascript/flavours/glitch/features/compose/components/publisher.js
index b8d9d98bf..97890f40d 100644
--- a/app/javascript/flavours/glitch/features/compose/components/publisher.js
+++ b/app/javascript/flavours/glitch/features/compose/components/publisher.js
@@ -38,8 +38,12 @@ class Publisher extends ImmutablePureComponent {
     sideArm: PropTypes.oneOf(['none', 'direct', 'private', 'unlisted', 'public']),
   };
 
+  handleSubmit = () => {
+    this.props.onSubmit();
+  };
+
   render () {
-    const { countText, disabled, intl, onSecondarySubmit, onSubmit, privacy, sideArm } = this.props;
+    const { countText, disabled, intl, onSecondarySubmit, privacy, sideArm } = this.props;
 
     const diff = maxChars - length(countText || '');
     const computedClass = classNames('composer--publisher', {
@@ -105,7 +109,7 @@ class Publisher extends ImmutablePureComponent {
             }
           }()}
           title={`${intl.formatMessage(messages.publish)}: ${intl.formatMessage({ id: `privacy.${privacy}.short` })}`}
-          onClick={onSubmit}
+          onClick={this.handleSubmit}
           disabled={disabled || diff < 0}
         />
       </div>
diff --git a/app/javascript/flavours/glitch/features/keyboard_shortcuts/index.js b/app/javascript/flavours/glitch/features/keyboard_shortcuts/index.js
index bc7571200..0bb71e872 100644
--- a/app/javascript/flavours/glitch/features/keyboard_shortcuts/index.js
+++ b/app/javascript/flavours/glitch/features/keyboard_shortcuts/index.js
@@ -114,6 +114,10 @@ class KeyboardShortcuts extends ImmutablePureComponent {
                 <td><FormattedMessage id='keyboard_shortcuts.search' defaultMessage='to focus search' /></td>
               </tr>
               <tr>
+                <td><kbd>alt</kbd>+<kbd>enter</kbd></td>
+                <td><FormattedMessage id='keyboard_shortcuts.secondary_toot' defaultMessage='to send toot using secondary privacy setting' /></td>
+              </tr>
+              <tr>
                 <td><kbd>esc</kbd></td>
                 <td><FormattedMessage id='keyboard_shortcuts.unfocus' defaultMessage='to un-focus compose textarea/search' /></td>
               </tr>
diff --git a/app/javascript/flavours/glitch/util/base_polyfills.js b/app/javascript/flavours/glitch/util/base_polyfills.js
index ad023eb73..4b8123dba 100644
--- a/app/javascript/flavours/glitch/util/base_polyfills.js
+++ b/app/javascript/flavours/glitch/util/base_polyfills.js
@@ -6,6 +6,7 @@ import assign from 'object-assign';
 import values from 'object.values';
 import isNaN from 'is-nan';
 import { decode as decodeBase64 } from './base64';
+import promiseFinally from 'promise.prototype.finally';
 
 if (!Array.prototype.includes) {
   includes.shim();
@@ -23,6 +24,8 @@ if (!Number.isNaN) {
   Number.isNaN = isNaN;
 }
 
+promiseFinally.shim();
+
 if (!HTMLCanvasElement.prototype.toBlob) {
   const BASE64_MARKER = ';base64,';
 
diff --git a/app/javascript/flavours/glitch/util/load_polyfills.js b/app/javascript/flavours/glitch/util/load_polyfills.js
index 8cb81c1a6..73eedc9dc 100644
--- a/app/javascript/flavours/glitch/util/load_polyfills.js
+++ b/app/javascript/flavours/glitch/util/load_polyfills.js
@@ -18,7 +18,8 @@ function loadPolyfills() {
     Number.isNaN &&
     Object.assign &&
     Object.values &&
-    window.Symbol
+    window.Symbol &&
+    Promise.prototype.finally
   );
 
   // Latest version of Firefox and Safari do not have IntersectionObserver.
diff --git a/app/javascript/flavours/glitch/util/main.js b/app/javascript/flavours/glitch/util/main.js
index b76826481..1fdb9ff2b 100644
--- a/app/javascript/flavours/glitch/util/main.js
+++ b/app/javascript/flavours/glitch/util/main.js
@@ -12,7 +12,7 @@ function main() {
   if (window.history && history.replaceState) {
     const { pathname, search, hash } = window.location;
     const path = pathname + search + hash;
-    if (!(/^\/web[$/]/).test(path)) {
+    if (!(/^\/web($|\/)/).test(path)) {
       history.replaceState(null, document.title, `/web${path}`);
     }
   }
diff --git a/app/javascript/mastodon/base_polyfills.js b/app/javascript/mastodon/base_polyfills.js
index 997813a04..12096d902 100644
--- a/app/javascript/mastodon/base_polyfills.js
+++ b/app/javascript/mastodon/base_polyfills.js
@@ -6,6 +6,7 @@ import assign from 'object-assign';
 import values from 'object.values';
 import isNaN from 'is-nan';
 import { decode as decodeBase64 } from './utils/base64';
+import promiseFinally from 'promise.prototype.finally';
 
 if (!Array.prototype.includes) {
   includes.shim();
@@ -23,6 +24,8 @@ if (!Number.isNaN) {
   Number.isNaN = isNaN;
 }
 
+promiseFinally.shim();
+
 if (!HTMLCanvasElement.prototype.toBlob) {
   const BASE64_MARKER = ';base64,';
 
diff --git a/app/javascript/mastodon/components/error_boundary.js b/app/javascript/mastodon/components/error_boundary.js
index 4e1c882e2..ca3012276 100644
--- a/app/javascript/mastodon/components/error_boundary.js
+++ b/app/javascript/mastodon/components/error_boundary.js
@@ -2,6 +2,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import { FormattedMessage } from 'react-intl';
 import { version, source_url } from 'mastodon/initial_state';
+import StackTrace from 'stacktrace-js';
 
 export default class ErrorBoundary extends React.PureComponent {
 
@@ -11,24 +12,42 @@ export default class ErrorBoundary extends React.PureComponent {
 
   state = {
     hasError: false,
+    errorMessage: undefined,
     stackTrace: undefined,
+    mappedStackTrace: undefined,
     componentStack: undefined,
   };
 
   componentDidCatch (error, info) {
     this.setState({
       hasError: true,
+      errorMessage: error.toString(),
       stackTrace: error.stack,
       componentStack: info && info.componentStack,
-      copied: false,
+      mappedStackTrace: undefined,
+    });
+
+    StackTrace.fromError(error).then((stackframes) => {
+      this.setState({
+        mappedStackTrace: stackframes.map((sf) => sf.toString()).join('\n'),
+      });
+    }).catch(() => {
+      this.setState({
+        mappedStackTrace: undefined,
+      });
     });
   }
 
   handleCopyStackTrace = () => {
-    const { stackTrace } = this.state;
+    const { errorMessage, stackTrace, mappedStackTrace } = this.state;
     const textarea = document.createElement('textarea');
 
-    textarea.textContent    = stackTrace;
+    let contents = [errorMessage, stackTrace];
+    if (mappedStackTrace) {
+      contents.push(mappedStackTrace);
+    }
+
+    textarea.textContent    = contents.join('\n\n\n');
     textarea.style.position = 'fixed';
 
     document.body.appendChild(textarea);
diff --git a/app/javascript/mastodon/load_polyfills.js b/app/javascript/mastodon/load_polyfills.js
index 8cb81c1a6..73eedc9dc 100644
--- a/app/javascript/mastodon/load_polyfills.js
+++ b/app/javascript/mastodon/load_polyfills.js
@@ -18,7 +18,8 @@ function loadPolyfills() {
     Number.isNaN &&
     Object.assign &&
     Object.values &&
-    window.Symbol
+    window.Symbol &&
+    Promise.prototype.finally
   );
 
   // Latest version of Firefox and Safari do not have IntersectionObserver.
diff --git a/app/javascript/mastodon/main.js b/app/javascript/mastodon/main.js
index 5d73caa10..da4884fd3 100644
--- a/app/javascript/mastodon/main.js
+++ b/app/javascript/mastodon/main.js
@@ -12,7 +12,7 @@ function main() {
   if (window.history && history.replaceState) {
     const { pathname, search, hash } = window.location;
     const path = pathname + search + hash;
-    if (!(/^\/web[$/]/).test(path)) {
+    if (!(/^\/web($|\/)/).test(path)) {
       history.replaceState(null, document.title, `/web${path}`);
     }
   }
diff --git a/app/models/account.rb b/app/models/account.rb
index e46888415..0fcf897c9 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -480,7 +480,16 @@ class Account < ApplicationRecord
     def from_text(text)
       return [] if text.blank?
 
-      text.scan(MENTION_RE).map { |match| match.first.split('@', 2) }.uniq.map { |(username, domain)| EntityCache.instance.mention(username, domain) }
+      text.scan(MENTION_RE).map { |match| match.first.split('@', 2) }.uniq.map do |(username, domain)|
+        domain = begin
+          if TagManager.instance.local_domain?(domain)
+            nil
+          else
+            TagManager.instance.normalize_domain(domain)
+          end
+        end
+        EntityCache.instance.mention(username, domain)
+      end.compact
     end
 
     private
diff --git a/app/services/activitypub/process_account_service.rb b/app/services/activitypub/process_account_service.rb
index cef658e19..d5ede0388 100644
--- a/app/services/activitypub/process_account_service.rb
+++ b/app/services/activitypub/process_account_service.rb
@@ -18,9 +18,10 @@ class ActivityPub::ProcessAccountService < BaseService
 
     RedisLock.acquire(lock_options) do |lock|
       if lock.acquired?
-        @account        = Account.find_remote(@username, @domain)
-        @old_public_key = @account&.public_key
-        @old_protocol   = @account&.protocol
+        @account          = Account.remote.find_by(uri: @uri) if @options[:only_key]
+        @account        ||= Account.find_remote(@username, @domain)
+        @old_public_key   = @account&.public_key
+        @old_protocol     = @account&.protocol
 
         create_account if @account.nil?
         update_account
diff --git a/app/services/backup_service.rb b/app/services/backup_service.rb
index ab6d090a0..691d024e1 100644
--- a/app/services/backup_service.rb
+++ b/app/services/backup_service.rb
@@ -66,6 +66,8 @@ class BackupService < BaseService
   def dump_media_attachments!(tar)
     MediaAttachment.attached.where(account: account).reorder(nil).find_in_batches do |media_attachments|
       media_attachments.each do |m|
+        next unless m.file&.path
+
         download_to_tar(tar, m.file, m.file.path)
       end
 
diff --git a/app/services/follow_service.rb b/app/services/follow_service.rb
index dc47804c0..4d19002c4 100644
--- a/app/services/follow_service.rb
+++ b/app/services/follow_service.rb
@@ -18,14 +18,13 @@ class FollowService < BaseService
     if source_account.following?(target_account)
       # We're already following this account, but we'll call follow! again to
       # make sure the reblogs status is set correctly.
-      source_account.follow!(target_account, reblogs: reblogs)
-      return
+      return source_account.follow!(target_account, reblogs: reblogs)
     elsif source_account.requested?(target_account)
       # This isn't managed by a method in AccountInteractions, so we modify it
       # ourselves if necessary.
       req = source_account.follow_requests.find_by(target_account: target_account)
       req.update!(show_reblogs: reblogs)
-      return
+      return req
     end
 
     ActivityTracker.increment('activity:interactions')
diff --git a/app/services/resolve_account_service.rb b/app/services/resolve_account_service.rb
index 12e6544a0..1ad9ed407 100644
--- a/app/services/resolve_account_service.rb
+++ b/app/services/resolve_account_service.rb
@@ -99,7 +99,7 @@ class ResolveAccountService < BaseService
       if lock.acquired?
         @account = Account.find_remote(@username, @domain)
 
-        next if (@account.present? && !@account.activitypub?) || actor_json.nil?
+        next if actor_json.nil?
 
         @account = ActivityPub::ProcessAccountService.new.call(@username, @domain, actor_json)
       else
diff --git a/app/views/admin/accounts/show.html.haml b/app/views/admin/accounts/show.html.haml
index a83f77134..a30b78db2 100644
--- a/app/views/admin/accounts/show.html.haml
+++ b/app/views/admin/accounts/show.html.haml
@@ -27,9 +27,9 @@
                     = fa_icon 'check'
                 = Formatter.instance.format_field(account, field.value, custom_emojify: true)
 
-      - if account.note.present?
-        %div
-          .account__header__content.emojify= Formatter.instance.simplified_format(account, custom_emojify: true)
+    - if account.note.present?
+      %div
+        .account__header__content.emojify= Formatter.instance.simplified_format(account, custom_emojify: true)
 
 .dashboard__counters{ style: 'margin-top: 10px' }
   %div
diff --git a/app/views/auth/registrations/new.html.haml b/app/views/auth/registrations/new.html.haml
index e807c8d86..bcd66fb8a 100644
--- a/app/views/auth/registrations/new.html.haml
+++ b/app/views/auth/registrations/new.html.haml
@@ -27,7 +27,7 @@
 
   - if approved_registrations? && !@invite.present?
     .fields-group
-      = f.simple_fields_for :invite_request do |invite_request_fields|
+      = f.simple_fields_for :invite_request, resource.invite_request || resource.build_invite_request do |invite_request_fields|
         = invite_request_fields.input :text, as: :text, wrapper: :with_block_label, required: false
 
   = f.input :invite_code, as: :hidden
diff --git a/app/views/authorize_interactions/show.html.haml b/app/views/authorize_interactions/show.html.haml
index 7ca9b98c1..42c874134 100644
--- a/app/views/authorize_interactions/show.html.haml
+++ b/app/views/authorize_interactions/show.html.haml
@@ -11,6 +11,12 @@
         = t('authorize_follow.already_following')
 
     = render 'post_follow_actions'
+  - elsif current_account.requested?(@resource)
+    .flash-message
+      %strong
+        = t('authorize_follow.already_requested')
+
+    = render 'post_follow_actions'
   - else
     = form_tag authorize_interaction_path, method: :post, class: 'simple_form' do
       = hidden_field_tag :action, :follow
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 8e819b5b1..6d6f67f91 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -674,6 +674,7 @@ en:
     trouble_logging_in: Trouble logging in?
   authorize_follow:
     already_following: You are already following this account
+    already_requested: You have already sent a follow request to that account
     error: Unfortunately, there was an error looking up the remote account
     follow: Follow
     follow_request: 'You have sent a follow request to:'
diff --git a/lib/mastodon/accounts_cli.rb b/lib/mastodon/accounts_cli.rb
index 6dbb75689..8c91c3013 100644
--- a/lib/mastodon/accounts_cli.rb
+++ b/lib/mastodon/accounts_cli.rb
@@ -120,6 +120,7 @@ module Mastodon
     option :disable, type: :boolean
     option :disable_2fa, type: :boolean
     option :approve, type: :boolean
+    option :reset_password, type: :boolean
     desc 'modify USERNAME', 'Modify a user'
     long_desc <<-LONG_DESC
       Modify a user account.
@@ -138,6 +139,9 @@ module Mastodon
 
       With the --disable-2fa option, the two-factor authentication
       requirement for the user can be removed.
+
+      With the --reset-password option, the user's password is replaced by
+      a randomly-generated one, printed in the output.
     LONG_DESC
     def modify(username)
       user = Account.find_local(username)&.user
@@ -152,6 +156,8 @@ module Mastodon
         user.moderator = options[:role] == 'moderator'
       end
 
+      password = SecureRandom.hex if options[:reset_password]
+      user.password = password if options[:reset_password]
       user.email = options[:email] if options[:email]
       user.disabled = false if options[:enable]
       user.disabled = true if options[:disable]
@@ -161,6 +167,7 @@ module Mastodon
 
       if user.save
         say('OK', :green)
+        say("New password: #{password}") if options[:reset_password]
       else
         user.errors.to_h.each do |key, error|
           say('Failure/Error: ', :red)
diff --git a/lib/mastodon/migration_helpers.rb b/lib/mastodon/migration_helpers.rb
index 146eba8ec..bf2314ecb 100644
--- a/lib/mastodon/migration_helpers.rb
+++ b/lib/mastodon/migration_helpers.rb
@@ -886,16 +886,12 @@ module Mastodon
 Your database user is not allowed to create, drop, or execute triggers on the
 table #{table}.
 
-If you are using PostgreSQL you can solve this by logging in to the GitLab
+If you are using PostgreSQL you can solve this by logging in to the Mastodon
 database (#{dbname}) using a super user and running:
 
     ALTER USER #{user} WITH SUPERUSER
 
-For MySQL you instead need to run:
-
-    GRANT ALL PRIVILEGES ON *.* TO #{user}@'%'
-
-Both queries will grant the user super user permissions, ensuring you don't run
+The query will grant the user super user permissions, ensuring you don't run
 into similar problems in the future (e.g. when new tables are created).
         EOF
       end
diff --git a/lib/mastodon/redis_config.rb b/lib/mastodon/redis_config.rb
index f11d94a45..e9db9122f 100644
--- a/lib/mastodon/redis_config.rb
+++ b/lib/mastodon/redis_config.rb
@@ -14,7 +14,9 @@ def setup_redis_env_url(prefix = nil, defaults = true)
   ENV[prefix + 'REDIS_URL'] = if [password, host, port, db].all?(&:nil?)
                                 ENV['REDIS_URL']
                               else
-                                "redis://#{password.blank? ? '' : ":#{password}@"}#{host}:#{port}/#{db}"
+                                Addressable::URI.parse("redis://#{host}:#{port}/#{db}").tap do |uri|
+                                  uri.password = password if password.present?
+                                end.normalize.to_str
                               end
 end
 
diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb
index c3e288eee..49fe73043 100644
--- a/lib/mastodon/version.rb
+++ b/lib/mastodon/version.rb
@@ -13,7 +13,7 @@ module Mastodon
     end
 
     def patch
-      0
+      2
     end
 
     def flags
diff --git a/lib/tasks/mastodon.rake b/lib/tasks/mastodon.rake
index 2e92e8ded..a873335d4 100644
--- a/lib/tasks/mastodon.rake
+++ b/lib/tasks/mastodon.rake
@@ -336,7 +336,20 @@ namespace :mastodon do
       if prompt.yes?('Save configuration?')
         cmd = TTY::Command.new(printer: :quiet)
 
-        File.write(Rails.root.join('.env.production'), "# Generated with mastodon:setup on #{Time.now.utc}\n\n" + env.each_pair.map { |key, value| "#{key}=#{value}" }.join("\n") + "\n")
+        env_contents = env.each_pair.map do |key, value|
+          if value.is_a?(String) && value =~ /[\s\#\\"]/
+            if value =~ /[']/
+              value = value.to_s.gsub(/[\\"\$]/) { |x| "\\#{x}" }
+              "#{key}=\"#{value}\""
+            else
+              "#{key}='#{value}'"
+            end
+          else
+            "#{key}=#{value}"
+          end
+        end.join("\n")
+
+        File.write(Rails.root.join('.env.production'), "# Generated with mastodon:setup on #{Time.now.utc}\n\n" + env_contents + "\n")
 
         if using_docker
           prompt.ok 'Below is your configuration, save it to an .env.production file outside Docker:'
diff --git a/package.json b/package.json
index df2c40175..789baf842 100644
--- a/package.json
+++ b/package.json
@@ -60,21 +60,21 @@
   },
   "private": true,
   "dependencies": {
-    "@babel/core": "^7.8.3",
+    "@babel/core": "^7.8.4",
     "@babel/plugin-proposal-class-properties": "^7.8.3",
     "@babel/plugin-proposal-decorators": "^7.8.3",
-    "@babel/plugin-transform-react-inline-elements": "^7.8.0",
-    "@babel/plugin-transform-runtime": "^7.7.6",
+    "@babel/plugin-transform-react-inline-elements": "^7.8.3",
+    "@babel/plugin-transform-runtime": "^7.8.3",
     "@babel/preset-env": "^7.8.3",
     "@babel/preset-react": "^7.8.3",
     "@babel/runtime": "^7.8.3",
-    "@gamestdio/websocket": "^0.3.2",
     "@clusterws/cws": "^0.17.3",
+    "@gamestdio/websocket": "^0.3.2",
     "array-includes": "^3.1.1",
-    "atrament": "^0.2.3",
     "arrow-key-navigation": "^1.1.0",
+    "atrament": "0.2.4",
     "autoprefixer": "^9.7.4",
-    "axios": "^0.19.1",
+    "axios": "^0.19.2",
     "babel-loader": "^8.0.6",
     "babel-plugin-lodash": "^3.3.4",
     "babel-plugin-preval": "^4.0.0",
@@ -95,8 +95,8 @@
     "escape-html": "^1.0.3",
     "exif-js": "^2.3.0",
     "express": "^4.17.1",
-    "file-loader": "^5.0.2",
     "favico.js": "^0.3.10",
+    "file-loader": "^5.0.2",
     "font-awesome": "^4.7.0",
     "glob": "^7.1.6",
     "history": "^4.10.1",
@@ -123,6 +123,7 @@
     "pg": "^6.4.0",
     "postcss-loader": "^3.0.0",
     "postcss-object-fit-images": "^1.1.2",
+    "promise.prototype.finally": "^3.1.2",
     "prop-types": "^15.5.10",
     "punycode": "^2.1.0",
     "rails-ujs": "^5.2.4",
@@ -136,37 +137,38 @@
     "react-motion": "^0.5.2",
     "react-notification": "^6.8.5",
     "react-overlays": "^0.9.1",
-    "react-redux": "^7.1.3",
+    "react-redux": "^7.2.0",
     "react-redux-loading-bar": "^4.0.8",
     "react-router-dom": "^4.1.1",
     "react-router-scroll-4": "^1.0.0-beta.1",
     "react-select": "^3.0.8",
     "react-sparklines": "^1.7.0",
-    "react-swipeable-views": "^0.13.4",
+    "react-swipeable-views": "^0.13.9",
     "react-textarea-autosize": "^7.1.2",
     "react-toggle": "^4.1.1",
     "redis": "^2.7.1",
     "redux": "^4.0.5",
     "redux-immutable": "^4.0.0",
     "redux-thunk": "^2.2.0",
-    "rellax": "^1.10.0",
+    "rellax": "^1.12.1",
     "requestidlecallback": "^0.3.0",
     "reselect": "^4.0.0",
-    "rimraf": "^3.0.0",
-    "sass": "^1.24.2",
+    "rimraf": "^3.0.2",
+    "sass": "^1.25.0",
     "sass-loader": "^8.0.2",
+    "stacktrace-js": "^2.0.2",
     "stringz": "^2.0.0",
     "substring-trie": "^1.0.2",
-    "terser-webpack-plugin": "^2.3.2",
+    "terser-webpack-plugin": "^2.3.5",
     "tesseract.js": "^2.0.0-alpha.16",
     "throng": "^4.0.0",
     "tiny-queue": "^0.2.1",
-    "uuid": "^3.3.3",
+    "uuid": "^3.4.0",
     "wavesurfer.js": "^3.3.1",
     "webpack": "^4.41.5",
     "webpack-assets-manifest": "^3.1.1",
     "webpack-bundle-analyzer": "^3.6.0",
-    "webpack-cli": "^3.3.10",
+    "webpack-cli": "^3.3.11",
     "webpack-merge": "^4.2.1",
     "wicg-inert": "^3.0.0"
   },
@@ -176,7 +178,7 @@
     "enzyme": "^3.11.0",
     "enzyme-adapter-react-16": "^1.15.2",
     "eslint": "^6.8.0",
-    "eslint-plugin-import": "~2.20.0",
+    "eslint-plugin-import": "~2.20.1",
     "eslint-plugin-jsx-a11y": "~6.2.3",
     "eslint-plugin-promise": "~4.2.1",
     "eslint-plugin-react": "~7.17.0",
diff --git a/spec/controllers/api/v1/statuses/bookmarks_controller_spec.rb b/spec/controllers/api/v1/statuses/bookmarks_controller_spec.rb
index b79853718..aa5ca433f 100644
--- a/spec/controllers/api/v1/statuses/bookmarks_controller_spec.rb
+++ b/spec/controllers/api/v1/statuses/bookmarks_controller_spec.rb
@@ -21,36 +21,67 @@ describe Api::V1::Statuses::BookmarksController do
         post :create, params: { status_id: status.id }
       end
 
-      it 'returns http success' do
-        expect(response).to have_http_status(:success)
-      end
+      context 'with public status' do
+        it 'returns http success' do
+          expect(response).to have_http_status(:success)
+        end
+
+        it 'updates the bookmarked attribute' do
+          expect(user.account.bookmarked?(status)).to be true
+        end
+
+        it 'returns json with updated attributes' do
+          hash_body = body_as_json
 
-      it 'updates the bookmarked attribute' do
-        expect(user.account.bookmarked?(status)).to be true
+          expect(hash_body[:id]).to eq status.id.to_s
+          expect(hash_body[:bookmarked]).to be true
+        end
       end
 
-      it 'return json with updated attributes' do
-        hash_body = body_as_json
+      context 'with private status of not-followed account' do
+        let(:status) { Fabricate(:status, visibility: :private) }
 
-        expect(hash_body[:id]).to eq status.id.to_s
-        expect(hash_body[:bookmarked]).to be true
+        it 'returns http not found' do
+          expect(response).to have_http_status(404)
+        end
       end
     end
 
     describe 'POST #destroy' do
-      let(:status) { Fabricate(:status, account: user.account) }
+      context 'with public status' do
+        let(:status) { Fabricate(:status, account: user.account) }
 
-      before do
-        Bookmark.find_or_create_by!(account: user.account, status: status)
-        post :destroy, params: { status_id: status.id }
-      end
+        before do
+          Bookmark.find_or_create_by!(account: user.account, status: status)
+          post :destroy, params: { status_id: status.id }
+        end
 
-      it 'returns http success' do
-        expect(response).to have_http_status(:success)
+        it 'returns http success' do
+          expect(response).to have_http_status(:success)
+        end
+
+        it 'updates the bookmarked attribute' do
+          expect(user.account.bookmarked?(status)).to be false
+        end
+
+        it 'returns json with updated attributes' do
+          hash_body = body_as_json
+
+          expect(hash_body[:id]).to eq status.id.to_s
+          expect(hash_body[:bookmarked]).to be false
+        end
       end
 
-      it 'updates the bookmarked attribute' do
-        expect(user.account.bookmarked?(status)).to be false
+      context 'with private status that was not bookmarked' do
+        let(:status) { Fabricate(:status, visibility: :private) }
+
+        before do
+          post :destroy, params: { status_id: status.id }
+        end
+
+        it 'returns http not found' do
+          expect(response).to have_http_status(404)
+        end
       end
     end
   end
diff --git a/spec/controllers/api/v1/statuses/favourites_controller_spec.rb b/spec/controllers/api/v1/statuses/favourites_controller_spec.rb
index 24a760e20..6e947f5d2 100644
--- a/spec/controllers/api/v1/statuses/favourites_controller_spec.rb
+++ b/spec/controllers/api/v1/statuses/favourites_controller_spec.rb
@@ -21,45 +21,77 @@ describe Api::V1::Statuses::FavouritesController do
         post :create, params: { status_id: status.id }
       end
 
-      it 'returns http success' do
-        expect(response).to have_http_status(200)
+      context 'with public status' do
+        it 'returns http success' do
+          expect(response).to have_http_status(200)
+        end
+
+        it 'updates the favourites count' do
+          expect(status.favourites.count).to eq 1
+        end
+
+        it 'updates the favourited attribute' do
+          expect(user.account.favourited?(status)).to be true
+        end
+
+        it 'returns json with updated attributes' do
+          hash_body = body_as_json
+
+          expect(hash_body[:id]).to eq status.id.to_s
+          expect(hash_body[:favourites_count]).to eq 1
+          expect(hash_body[:favourited]).to be true
+        end
       end
 
-      it 'updates the favourites count' do
-        expect(status.favourites.count).to eq 1
-      end
-
-      it 'updates the favourited attribute' do
-        expect(user.account.favourited?(status)).to be true
-      end
-
-      it 'return json with updated attributes' do
-        hash_body = body_as_json
+      context 'with private status of not-followed account' do
+        let(:status) { Fabricate(:status, visibility: :private) }
 
-        expect(hash_body[:id]).to eq status.id.to_s
-        expect(hash_body[:favourites_count]).to eq 1
-        expect(hash_body[:favourited]).to be true
+        it 'returns http not found' do
+          expect(response).to have_http_status(404)
+        end
       end
     end
 
     describe 'POST #destroy' do
-      let(:status) { Fabricate(:status, account: user.account) }
+      context 'with public status' do
+        let(:status) { Fabricate(:status, account: user.account) }
 
-      before do
-        FavouriteService.new.call(user.account, status)
-        post :destroy, params: { status_id: status.id }
-      end
+        before do
+          FavouriteService.new.call(user.account, status)
+          post :destroy, params: { status_id: status.id }
+        end
 
-      it 'returns http success' do
-        expect(response).to have_http_status(200)
-      end
+        it 'returns http success' do
+          expect(response).to have_http_status(200)
+        end
+
+        it 'updates the favourites count' do
+          expect(status.favourites.count).to eq 0
+        end
+
+        it 'updates the favourited attribute' do
+          expect(user.account.favourited?(status)).to be false
+        end
 
-      it 'updates the favourites count' do
-        expect(status.favourites.count).to eq 0
+        it 'returns json with updated attributes' do
+          hash_body = body_as_json
+
+          expect(hash_body[:id]).to eq status.id.to_s
+          expect(hash_body[:favourites_count]).to eq 0
+          expect(hash_body[:favourited]).to be false
+        end
       end
 
-      it 'updates the favourited attribute' do
-        expect(user.account.favourited?(status)).to be false
+      context 'with private status that was not favourited' do
+        let(:status) { Fabricate(:status, visibility: :private) }
+
+        before do
+          post :destroy, params: { status_id: status.id }
+        end
+
+        it 'returns http not found' do
+          expect(response).to have_http_status(404)
+        end
       end
     end
   end
diff --git a/spec/controllers/api/v1/statuses/reblogs_controller_spec.rb b/spec/controllers/api/v1/statuses/reblogs_controller_spec.rb
index d14ca3e8b..93b244cc3 100644
--- a/spec/controllers/api/v1/statuses/reblogs_controller_spec.rb
+++ b/spec/controllers/api/v1/statuses/reblogs_controller_spec.rb
@@ -21,45 +21,77 @@ describe Api::V1::Statuses::ReblogsController do
         post :create, params: { status_id: status.id }
       end
 
-      it 'returns http success' do
-        expect(response).to have_http_status(200)
+      context 'with public status' do
+        it 'returns http success' do
+          expect(response).to have_http_status(200)
+        end
+
+        it 'updates the reblogs count' do
+          expect(status.reblogs.count).to eq 1
+        end
+
+        it 'updates the reblogged attribute' do
+          expect(user.account.reblogged?(status)).to be true
+        end
+
+        it 'returns json with updated attributes' do
+          hash_body = body_as_json
+
+          expect(hash_body[:reblog][:id]).to eq status.id.to_s
+          expect(hash_body[:reblog][:reblogs_count]).to eq 1
+          expect(hash_body[:reblog][:reblogged]).to be true
+        end
       end
 
-      it 'updates the reblogs count' do
-        expect(status.reblogs.count).to eq 1
-      end
-
-      it 'updates the reblogged attribute' do
-        expect(user.account.reblogged?(status)).to be true
-      end
-
-      it 'return json with updated attributes' do
-        hash_body = body_as_json
+      context 'with private status of not-followed account' do
+        let(:status) { Fabricate(:status, visibility: :private) }
 
-        expect(hash_body[:reblog][:id]).to eq status.id.to_s
-        expect(hash_body[:reblog][:reblogs_count]).to eq 1
-        expect(hash_body[:reblog][:reblogged]).to be true
+        it 'returns http not found' do
+          expect(response).to have_http_status(404)
+        end
       end
     end
 
     describe 'POST #destroy' do
-      let(:status) { Fabricate(:status, account: user.account) }
+      context 'with public status' do
+        let(:status) { Fabricate(:status, account: user.account) }
 
-      before do
-        ReblogService.new.call(user.account, status)
-        post :destroy, params: { status_id: status.id }
-      end
+        before do
+          ReblogService.new.call(user.account, status)
+          post :destroy, params: { status_id: status.id }
+        end
 
-      it 'returns http success' do
-        expect(response).to have_http_status(200)
-      end
+        it 'returns http success' do
+          expect(response).to have_http_status(200)
+        end
+
+        it 'updates the reblogs count' do
+          expect(status.reblogs.count).to eq 0
+        end
+
+        it 'updates the reblogged attribute' do
+          expect(user.account.reblogged?(status)).to be false
+        end
 
-      it 'updates the reblogs count' do
-        expect(status.reblogs.count).to eq 0
+        it 'returns json with updated attributes' do
+          hash_body = body_as_json
+
+          expect(hash_body[:id]).to eq status.id.to_s
+          expect(hash_body[:reblogs_count]).to eq 0
+          expect(hash_body[:reblogged]).to be false
+        end
       end
 
-      it 'updates the reblogged attribute' do
-        expect(user.account.reblogged?(status)).to be false
+      context 'with private status that was not reblogged' do
+        let(:status) { Fabricate(:status, visibility: :private) }
+
+        before do
+          post :destroy, params: { status_id: status.id }
+        end
+
+        it 'returns http not found' do
+          expect(response).to have_http_status(404)
+        end
       end
     end
   end
diff --git a/spec/controllers/auth/registrations_controller_spec.rb b/spec/controllers/auth/registrations_controller_spec.rb
index 3e11b34b5..c2e9f33a8 100644
--- a/spec/controllers/auth/registrations_controller_spec.rb
+++ b/spec/controllers/auth/registrations_controller_spec.rb
@@ -100,7 +100,7 @@ RSpec.describe Auth::RegistrationsController, type: :controller do
       subject do
         Setting.registrations_mode = 'open'
         request.headers["Accept-Language"] = accept_language
-        post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678' } }
+        post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', agreement: 'true' } }
       end
 
       it 'redirects to setup' do
@@ -116,6 +116,26 @@ RSpec.describe Auth::RegistrationsController, type: :controller do
       end
     end
 
+    context 'when user has not agreed to terms of service' do
+      around do |example|
+        registrations_mode = Setting.registrations_mode
+        example.run
+        Setting.registrations_mode = registrations_mode
+      end
+
+      subject do
+        Setting.registrations_mode = 'open'
+        request.headers["Accept-Language"] = accept_language
+        post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', agreement: 'false' } }
+      end
+
+      it 'does not create user' do
+        subject
+        user = User.find_by(email: 'test@example.com')
+        expect(user).to be_nil
+      end
+    end
+
     context 'approval-based registrations without invite' do
       around do |example|
         registrations_mode = Setting.registrations_mode
@@ -126,7 +146,7 @@ RSpec.describe Auth::RegistrationsController, type: :controller do
       subject do
         Setting.registrations_mode = 'approved'
         request.headers["Accept-Language"] = accept_language
-        post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678' } }
+        post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', agreement: 'true' } }
       end
 
       it 'redirects to setup' do
@@ -154,7 +174,7 @@ RSpec.describe Auth::RegistrationsController, type: :controller do
         Setting.registrations_mode = 'approved'
         request.headers["Accept-Language"] = accept_language
         invite = Fabricate(:invite, max_uses: nil, expires_at: 1.hour.ago)
-        post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', 'invite_code': invite.code } }
+        post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', 'invite_code': invite.code, agreement: 'true' } }
       end
 
       it 'redirects to setup' do
@@ -182,7 +202,7 @@ RSpec.describe Auth::RegistrationsController, type: :controller do
         Setting.registrations_mode = 'approved'
         request.headers["Accept-Language"] = accept_language
         invite = Fabricate(:invite, max_uses: nil, expires_at: 1.hour.from_now)
-        post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', 'invite_code': invite.code } }
+        post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', 'invite_code': invite.code, agreement: 'true' } }
       end
 
       it 'redirects to setup' do
diff --git a/yarn.lock b/yarn.lock
index 586423de5..ceea5e811 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -18,17 +18,17 @@
     invariant "^2.2.4"
     semver "^5.5.0"
 
-"@babel/core@^7.1.0", "@babel/core@^7.4.5", "@babel/core@^7.8.3":
-  version "7.8.3"
-  resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.3.tgz#30b0ebb4dd1585de6923a0b4d179e0b9f5d82941"
-  integrity sha512-4XFkf8AwyrEG7Ziu3L2L0Cv+WyY47Tcsp70JFmpftbAA1K7YL/sgE9jh9HyNj08Y/U50ItUchpN0w6HxAoX1rA==
+"@babel/core@^7.1.0", "@babel/core@^7.4.5", "@babel/core@^7.8.4":
+  version "7.8.4"
+  resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.4.tgz#d496799e5c12195b3602d0fddd77294e3e38e80e"
+  integrity sha512-0LiLrB2PwrVI+a2/IEskBopDYSd8BCb3rOvH7D5tzoWd696TBEduBvuLVm4Nx6rltrLZqvI3MCalB2K2aVzQjA==
   dependencies:
     "@babel/code-frame" "^7.8.3"
-    "@babel/generator" "^7.8.3"
-    "@babel/helpers" "^7.8.3"
-    "@babel/parser" "^7.8.3"
+    "@babel/generator" "^7.8.4"
+    "@babel/helpers" "^7.8.4"
+    "@babel/parser" "^7.8.4"
     "@babel/template" "^7.8.3"
-    "@babel/traverse" "^7.8.3"
+    "@babel/traverse" "^7.8.4"
     "@babel/types" "^7.8.3"
     convert-source-map "^1.7.0"
     debug "^4.1.0"
@@ -39,10 +39,10 @@
     semver "^5.4.1"
     source-map "^0.5.0"
 
-"@babel/generator@^7.0.0", "@babel/generator@^7.8.3":
-  version "7.8.3"
-  resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.3.tgz#0e22c005b0a94c1c74eafe19ef78ce53a4d45c03"
-  integrity sha512-WjoPk8hRpDRqqzRpvaR8/gDUPkrnOOeuT2m8cNICJtZH6mwaCo3v0OKMI7Y6SM1pBtyijnLtAL0HDi41pf41ug==
+"@babel/generator@^7.0.0", "@babel/generator@^7.8.4":
+  version "7.8.4"
+  resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.4.tgz#35bbc74486956fe4251829f9f6c48330e8d0985e"
+  integrity sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==
   dependencies:
     "@babel/types" "^7.8.3"
     jsesc "^2.5.1"
@@ -64,14 +64,6 @@
     "@babel/helper-explode-assignable-expression" "^7.8.3"
     "@babel/types" "^7.8.3"
 
-"@babel/helper-builder-react-jsx@^7.8.0":
-  version "7.8.0"
-  resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.8.0.tgz#4b9111eb862f5fd8840c37d200610fa95ab0aad8"
-  integrity sha512-Zg7VLtZzcAHoQ13S0pEIGKo8OAG3s5kjsk/4keGmUeNuc810T9fVp6izIaL8ZVeAErRFWJdvqFItY3QMTHMsSg==
-  dependencies:
-    "@babel/types" "^7.8.0"
-    esutils "^2.0.0"
-
 "@babel/helper-builder-react-jsx@^7.8.3":
   version "7.8.3"
   resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.8.3.tgz#dee98d7d79cc1f003d80b76fe01c7f8945665ff6"
@@ -167,7 +159,7 @@
   dependencies:
     "@babel/types" "^7.8.3"
 
-"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.0.0-beta.49", "@babel/helper-module-imports@^7.7.4", "@babel/helper-module-imports@^7.8.3":
+"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.0.0-beta.49", "@babel/helper-module-imports@^7.8.3":
   version "7.8.3"
   resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz#7fe39589b39c016331b6b8c3f441e8f0b1419498"
   integrity sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg==
@@ -251,13 +243,13 @@
     "@babel/traverse" "^7.8.3"
     "@babel/types" "^7.8.3"
 
-"@babel/helpers@^7.8.3":
-  version "7.8.3"
-  resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.8.3.tgz#382fbb0382ce7c4ce905945ab9641d688336ce85"
-  integrity sha512-LmU3q9Pah/XyZU89QvBgGt+BCsTPoQa+73RxAQh8fb8qkDyIfeQnmgs+hvzhTCKTzqOyk7JTkS3MS1S8Mq5yrQ==
+"@babel/helpers@^7.8.4":
+  version "7.8.4"
+  resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.8.4.tgz#754eb3ee727c165e0a240d6c207de7c455f36f73"
+  integrity sha512-VPbe7wcQ4chu4TDQjimHv/5tj73qz88o12EPkO2ValS2QiQS/1F2SsjyIGNnAD0vF/nZS6Cf9i+vW6HIlnaR8w==
   dependencies:
     "@babel/template" "^7.8.3"
-    "@babel/traverse" "^7.8.3"
+    "@babel/traverse" "^7.8.4"
     "@babel/types" "^7.8.3"
 
 "@babel/highlight@^7.8.3":
@@ -269,10 +261,10 @@
     esutils "^2.0.2"
     js-tokens "^4.0.0"
 
-"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.8.3":
-  version "7.8.3"
-  resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.3.tgz#790874091d2001c9be6ec426c2eed47bc7679081"
-  integrity sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ==
+"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.8.3", "@babel/parser@^7.8.4":
+  version "7.8.4"
+  resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.4.tgz#d1dbe64691d60358a974295fa53da074dd2ce8e8"
+  integrity sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==
 
 "@babel/plugin-proposal-async-generator-functions@^7.8.3":
   version "7.8.3"
@@ -619,13 +611,13 @@
   dependencies:
     "@babel/helper-plugin-utils" "^7.8.3"
 
-"@babel/plugin-transform-react-inline-elements@^7.8.0":
-  version "7.8.0"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-inline-elements/-/plugin-transform-react-inline-elements-7.8.0.tgz#851799e0f66708563b9ada01b175affa1085f0d5"
-  integrity sha512-LZCsQfeoF8qqc6IaxJfAe4iSgWlbsdKeEkdxDtb8uzvcDbtXxUYjgUcSsqWgbpC88PIEv65SNzlQZo9/mymgQw==
+"@babel/plugin-transform-react-inline-elements@^7.8.3":
+  version "7.8.3"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-inline-elements/-/plugin-transform-react-inline-elements-7.8.3.tgz#fc234d02a35bb188ee3f933d068824e067e42b23"
+  integrity sha512-CGKUlW3vtgk6YYrIMyfpohmmpILnaeFwszqwTIcem2LQkK1qWJj5w2yTZ7LJr2IR8F0XQ60AZoM8jgAB4zpxCg==
   dependencies:
-    "@babel/helper-builder-react-jsx" "^7.8.0"
-    "@babel/helper-plugin-utils" "^7.8.0"
+    "@babel/helper-builder-react-jsx" "^7.8.3"
+    "@babel/helper-plugin-utils" "^7.8.3"
 
 "@babel/plugin-transform-react-jsx-self@^7.8.3":
   version "7.8.3"
@@ -666,13 +658,13 @@
   dependencies:
     "@babel/helper-plugin-utils" "^7.8.3"
 
-"@babel/plugin-transform-runtime@^7.7.6":
-  version "7.7.6"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.7.6.tgz#4f2b548c88922fb98ec1c242afd4733ee3e12f61"
-  integrity sha512-tajQY+YmXR7JjTwRvwL4HePqoL3DYxpYXIHKVvrOIvJmeHe2y1w4tz5qz9ObUDC9m76rCzIMPyn4eERuwA4a4A==
+"@babel/plugin-transform-runtime@^7.8.3":
+  version "7.8.3"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.8.3.tgz#c0153bc0a5375ebc1f1591cb7eea223adea9f169"
+  integrity sha512-/vqUt5Yh+cgPZXXjmaG9NT8aVfThKk7G4OqkVhrXqwsC5soMn/qTCxs36rZ2QFhpfTJcjw4SNDIZ4RUb8OL4jQ==
   dependencies:
-    "@babel/helper-module-imports" "^7.7.4"
-    "@babel/helper-plugin-utils" "^7.0.0"
+    "@babel/helper-module-imports" "^7.8.3"
+    "@babel/helper-plugin-utils" "^7.8.3"
     resolve "^1.8.1"
     semver "^5.5.1"
 
@@ -825,22 +817,22 @@
     "@babel/parser" "^7.8.3"
     "@babel/types" "^7.8.3"
 
-"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.8.3":
-  version "7.8.3"
-  resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.3.tgz#a826215b011c9b4f73f3a893afbc05151358bf9a"
-  integrity sha512-we+a2lti+eEImHmEXp7bM9cTxGzxPmBiVJlLVD+FuuQMeeO7RaDbutbgeheDkw+Xe3mCfJHnGOWLswT74m2IPg==
+"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.4":
+  version "7.8.4"
+  resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.4.tgz#f0845822365f9d5b0e312ed3959d3f827f869e3c"
+  integrity sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==
   dependencies:
     "@babel/code-frame" "^7.8.3"
-    "@babel/generator" "^7.8.3"
+    "@babel/generator" "^7.8.4"
     "@babel/helper-function-name" "^7.8.3"
     "@babel/helper-split-export-declaration" "^7.8.3"
-    "@babel/parser" "^7.8.3"
+    "@babel/parser" "^7.8.4"
     "@babel/types" "^7.8.3"
     debug "^4.1.0"
     globals "^11.1.0"
     lodash "^4.17.13"
 
-"@babel/types@^7.0.0", "@babel/types@^7.0.0-beta.49", "@babel/types@^7.3.0", "@babel/types@^7.8.0", "@babel/types@^7.8.3":
+"@babel/types@^7.0.0", "@babel/types@^7.0.0-beta.49", "@babel/types@^7.3.0", "@babel/types@^7.8.3":
   version "7.8.3"
   resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.3.tgz#5a383dffa5416db1b73dedffd311ffd0788fb31c"
   integrity sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==
@@ -1710,11 +1702,6 @@ arrow-key-navigation@^1.1.0:
   resolved "https://registry.yarnpkg.com/arrow-key-navigation/-/arrow-key-navigation-1.1.0.tgz#c0f7021d006593e2e34e79aa1f032714877d3a76"
   integrity sha512-u73yfJRmKye5eZiMNrAUKaBIRt47/1NM8WEtVAPjjMDab/PVn0sKIuapvCxl7C+tI9nH0QOl1Tc2YL2aO9n9Zw==
 
-asap@~2.0.3:
-  version "2.0.6"
-  resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
-  integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
-
 asn1.js@^4.0.0:
   version "4.10.1"
   resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0"
@@ -1786,9 +1773,10 @@ atob@^2.1.1:
   resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
   integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
 
-atrament@^0.2.3:
-  version "0.2.3"
-  resolved "https://registry.yarnpkg.com/atrament/-/atrament-0.2.3.tgz#6ccbc0daa6d3f25e5aeaeb31befeb78e86980348"
+atrament@0.2.4:
+  version "0.2.4"
+  resolved "https://registry.yarnpkg.com/atrament/-/atrament-0.2.4.tgz#6f78196edfcd194e568b7c0b9c88201ec371ac66"
+  integrity sha512-hSA9VwW6COMwvRhSEO4uZweZ91YGOdHqwvslNyrJZG+8mzc4qx/qMsDZBuAeXFeWZO/QKtRjIXguOUy1aNMl3A==
 
 autoprefixer@^9.7.4:
   version "9.7.4"
@@ -1821,10 +1809,10 @@ axios@^0.18.0:
     follow-redirects "1.5.10"
     is-buffer "^2.0.2"
 
-axios@^0.19.1:
-  version "0.19.1"
-  resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.1.tgz#8a6a04eed23dfe72747e1dd43c604b8f1677b5aa"
-  integrity sha512-Yl+7nfreYKaLRvAvjNPkvfjnQHJM1yLBY3zhqAwcJSwR/6ETkanUgylgtIvkvz0xJ+p/vZuNw8X7Hnb7Whsbpw==
+axios@^0.19.2:
+  version "0.19.2"
+  resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27"
+  integrity sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==
   dependencies:
     follow-redirects "1.5.10"
 
@@ -2831,11 +2819,6 @@ core-js-compat@^3.6.2:
     browserslist "^4.8.3"
     semver "7.0.0"
 
-core-js@^1.0.0:
-  version "1.2.7"
-  resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
-  integrity sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=
-
 core-js@^2.4.0:
   version "2.6.1"
   resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.1.tgz#87416ae817de957a3f249b3b5ca475d4aaed6042"
@@ -3183,11 +3166,6 @@ csstype@^2.5.7:
   resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.6.tgz#c34f8226a94bbb10c32cc0d714afdf942291fc41"
   integrity sha512-RpFbQGUE74iyPgvr46U9t1xoQBM8T4BL8SxrN66Le2xYAPSaDJJKeztV3awugusb3g3G9iL8StmkBBXhcbbXhg==
 
-csstype@^2.6.7:
-  version "2.6.8"
-  resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.8.tgz#0fb6fc2417ffd2816a418c9336da74d7f07db431"
-  integrity sha512-msVS9qTuMT5zwAGCVm4mxfrZ18BNc6Csd0oJAtiFMZ1FAx1CCvy2+5MDmYoix63LM/6NDbNtodCiGYGmFgO0dA==
-
 cyclist@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
@@ -3470,14 +3448,6 @@ dom-helpers@^3.2.1, dom-helpers@^3.3.1:
   dependencies:
     "@babel/runtime" "^7.1.2"
 
-dom-helpers@^5.1.3:
-  version "5.1.3"
-  resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.1.3.tgz#7233248eb3a2d1f74aafca31e52c5299cc8ce821"
-  integrity sha512-nZD1OtwfWGRBWlpANxacBEZrEuLa16o1nh7YopFWeoF68Zt8GGEmzHu6Xv4F3XaFIC+YXtTLrzgqKxFgLEe4jw==
-  dependencies:
-    "@babel/runtime" "^7.6.3"
-    csstype "^2.6.7"
-
 dom-serializer@0:
   version "0.1.0"
   resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82"
@@ -3631,13 +3601,6 @@ encodeurl@~1.0.2:
   resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
   integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
 
-encoding@^0.1.11:
-  version "0.1.12"
-  resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
-  integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=
-  dependencies:
-    iconv-lite "~0.4.13"
-
 end-of-stream@^1.0.0, end-of-stream@^1.1.0:
   version "1.4.4"
   resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
@@ -3736,6 +3699,13 @@ error-ex@^1.2.0, error-ex@^1.3.1:
   dependencies:
     is-arrayish "^0.2.1"
 
+error-stack-parser@^2.0.6:
+  version "2.0.6"
+  resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.0.6.tgz#5a99a707bd7a4c58a797902d48d82803ede6aad8"
+  integrity sha512-d51brTeqC+BHlwF0BhPtcYgF5nlzf9ZZ0ZIUQNZpc9ZB9qw5IJ2diTrBY9jlCJkTLITYPjmiX6OWCwH+fuyNgQ==
+  dependencies:
+    stackframe "^1.1.1"
+
 es-abstract@^1.13.0, es-abstract@^1.15.0, es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.5.1:
   version "1.17.0"
   resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.0.tgz#f42a517d0036a5591dbb2c463591dc8bb50309b1"
@@ -3753,6 +3723,23 @@ es-abstract@^1.13.0, es-abstract@^1.15.0, es-abstract@^1.17.0, es-abstract@^1.17
     string.prototype.trimleft "^2.1.1"
     string.prototype.trimright "^2.1.1"
 
+es-abstract@^1.17.0-next.0:
+  version "1.17.4"
+  resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.4.tgz#e3aedf19706b20e7c2594c35fc0d57605a79e184"
+  integrity sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==
+  dependencies:
+    es-to-primitive "^1.2.1"
+    function-bind "^1.1.1"
+    has "^1.0.3"
+    has-symbols "^1.0.1"
+    is-callable "^1.1.5"
+    is-regex "^1.0.5"
+    object-inspect "^1.7.0"
+    object-keys "^1.1.1"
+    object.assign "^4.1.0"
+    string.prototype.trimleft "^2.1.1"
+    string.prototype.trimright "^2.1.1"
+
 es-to-primitive@^1.2.1:
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a"
@@ -3882,10 +3869,10 @@ eslint-plugin-eslint-plugin@^2.1.0:
   resolved "https://registry.yarnpkg.com/eslint-plugin-eslint-plugin/-/eslint-plugin-eslint-plugin-2.1.0.tgz#a7a00f15a886957d855feacaafee264f039e62d5"
   integrity sha512-kT3A/ZJftt28gbl/Cv04qezb/NQ1dwYIbi8lyf806XMxkus7DvOVCLIfTXMrorp322Pnoez7+zabXH29tADIDg==
 
-eslint-plugin-import@~2.20.0:
-  version "2.20.0"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.20.0.tgz#d749a7263fb6c29980def8e960d380a6aa6aecaa"
-  integrity sha512-NK42oA0mUc8Ngn4kONOPsPB1XhbUvNHqF+g307dPV28aknPoiNnKLFd9em4nkswwepdF5ouieqv5Th/63U7YJQ==
+eslint-plugin-import@~2.20.1:
+  version "2.20.1"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.20.1.tgz#802423196dcb11d9ce8435a5fc02a6d3b46939b3"
+  integrity sha512-qQHgFOTjguR+LnYRoToeZWT62XM55MBVXObHM6SKFd1VzDcX/vqT1kAz8ssqigh5eMj8qXcRoXXGZpPP6RfdCw==
   dependencies:
     array-includes "^3.0.3"
     array.prototype.flat "^1.2.1"
@@ -4314,6 +4301,7 @@ fast-levenshtein@~2.0.6:
 favico.js@^0.3.10:
   version "0.3.10"
   resolved "https://registry.yarnpkg.com/favico.js/-/favico.js-0.3.10.tgz#80586e27a117f24a8d51c18a99bdc714d4339301"
+  integrity sha1-gFhuJ6EX8kqNUcGKmb3HFNQzkwE=
 
 faye-websocket@^0.10.0:
   version "0.10.0"
@@ -4336,19 +4324,6 @@ fb-watchman@^2.0.0:
   dependencies:
     bser "^2.0.0"
 
-fbjs@^0.8.4:
-  version "0.8.17"
-  resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.17.tgz#c4d598ead6949112653d6588b01a5cdcd9f90fdd"
-  integrity sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=
-  dependencies:
-    core-js "^1.0.0"
-    isomorphic-fetch "^2.1.1"
-    loose-envify "^1.0.0"
-    object-assign "^4.1.0"
-    promise "^7.1.1"
-    setimmediate "^1.0.5"
-    ua-parser-js "^0.7.18"
-
 figgy-pudding@^3.5.1:
   version "3.5.1"
   resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790"
@@ -4933,6 +4908,11 @@ has-flag@^3.0.0:
   resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
   integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
 
+has-flag@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
+  integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
+
 has-symbols@^1.0.0, has-symbols@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8"
@@ -5199,7 +5179,7 @@ https-browserify@^1.0.0:
   resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
   integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=
 
-iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
+iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4:
   version "0.4.24"
   resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
   integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
@@ -5763,7 +5743,7 @@ is-resolvable@^1.0.0:
   resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88"
   integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==
 
-is-stream@^1.0.1, is-stream@^1.1.0:
+is-stream@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
   integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
@@ -5844,14 +5824,6 @@ isobject@^3.0.0, isobject@^3.0.1:
   resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
   integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=
 
-isomorphic-fetch@^2.1.1:
-  version "2.2.1"
-  resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
-  integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=
-  dependencies:
-    node-fetch "^1.0.1"
-    whatwg-fetch ">=0.10.0"
-
 isstream@~0.1.2:
   version "0.1.2"
   resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
@@ -6253,6 +6225,14 @@ jest-worker@^24.6.0, jest-worker@^24.9.0:
     merge-stream "^2.0.0"
     supports-color "^6.1.0"
 
+jest-worker@^25.1.0:
+  version "25.1.0"
+  resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-25.1.0.tgz#75d038bad6fdf58eba0d2ec1835856c497e3907a"
+  integrity sha512-ZHhHtlxOWSxCoNOKHGbiLzXnl42ga9CxDr27H36Qn+15pQZd3R/F24jrmjDelw9j/iHUIWMWs08/u2QN50HHOg==
+  dependencies:
+    merge-stream "^2.0.0"
+    supports-color "^7.0.0"
+
 jest@^24.9.0:
   version "24.9.0"
   resolved "https://registry.yarnpkg.com/jest/-/jest-24.9.0.tgz#987d290c05a08b52c56188c1002e368edb007171"
@@ -7114,14 +7094,6 @@ nice-try@^1.0.4:
   resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
   integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
 
-node-fetch@^1.0.1:
-  version "1.7.3"
-  resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
-  integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==
-  dependencies:
-    encoding "^0.1.11"
-    is-stream "^1.0.1"
-
 node-forge@0.9.0:
   version "0.9.0"
   resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579"
@@ -7570,10 +7542,10 @@ p-limit@^1.1.0:
   dependencies:
     p-try "^1.0.0"
 
-p-limit@^2.0.0, p-limit@^2.2.0, p-limit@^2.2.1:
-  version "2.2.1"
-  resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537"
-  integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==
+p-limit@^2.0.0, p-limit@^2.2.0, p-limit@^2.2.1, p-limit@^2.2.2:
+  version "2.2.2"
+  resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.2.tgz#61279b67721f5287aa1c13a9a7fbbc48c9291b1e"
+  integrity sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==
   dependencies:
     p-try "^2.0.0"
 
@@ -8409,12 +8381,14 @@ promise-inflight@^1.0.1:
   resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
   integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM=
 
-promise@^7.1.1:
-  version "7.3.1"
-  resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"
-  integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==
+promise.prototype.finally@^3.1.2:
+  version "3.1.2"
+  resolved "https://registry.yarnpkg.com/promise.prototype.finally/-/promise.prototype.finally-3.1.2.tgz#b8af89160c9c673cefe3b4c4435b53cfd0287067"
+  integrity sha512-A2HuJWl2opDH0EafgdjwEw7HysI8ff/n4lW4QEVBCUXFk9QeGecBWv0Deph0UmLe3tTNYegz8MOjsVuE6SMoJA==
   dependencies:
-    asap "~2.0.3"
+    define-properties "^1.1.3"
+    es-abstract "^1.17.0-next.0"
+    function-bind "^1.1.1"
 
 prompts@^2.0.1:
   version "2.0.3"
@@ -8760,14 +8734,13 @@ react-redux-loading-bar@^4.0.8:
     prop-types "^15.6.2"
     react-lifecycles-compat "^3.0.2"
 
-react-redux@^7.1.3:
-  version "7.1.3"
-  resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.1.3.tgz#717a3d7bbe3a1b2d535c94885ce04cdc5a33fc79"
-  integrity sha512-uI1wca+ECG9RoVkWQFF4jDMqmaw0/qnvaSvOoL/GA4dNxf6LoV8sUAcNDvE5NWKs4hFpn0t6wswNQnY3f7HT3w==
+react-redux@^7.2.0:
+  version "7.2.0"
+  resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.0.tgz#f970f62192b3981642fec46fd0db18a074fe879d"
+  integrity sha512-EvCAZYGfOLqwV7gh849xy9/pt55rJXPwmYvI4lilPM5rUT/1NxuuN59ipdBksRVSvz0KInbPnp4IfoXJXCqiDA==
   dependencies:
     "@babel/runtime" "^7.5.5"
     hoist-non-react-statics "^3.3.0"
-    invariant "^2.2.4"
     loose-envify "^1.4.0"
     prop-types "^15.7.2"
     react-is "^16.9.0"
@@ -8826,36 +8799,35 @@ react-sparklines@^1.7.0:
   dependencies:
     prop-types "^15.5.10"
 
-react-swipeable-views-core@^0.13.1:
-  version "0.13.1"
-  resolved "https://registry.yarnpkg.com/react-swipeable-views-core/-/react-swipeable-views-core-0.13.1.tgz#8829a922462a8bdd701709cd1b385393d38f1527"
-  integrity sha512-EP8sCvvD7VDiZLglPt9icMuMNu8qLRLk0ab/fB1HXv7lX8ClnwF3UMCM0ZrN3sguSY7CsX3LevducGGsT1VcDg==
+react-swipeable-views-core@^0.13.7:
+  version "0.13.7"
+  resolved "https://registry.yarnpkg.com/react-swipeable-views-core/-/react-swipeable-views-core-0.13.7.tgz#c082b553f26e83fd20fc17f934200eb717023c8a"
+  integrity sha512-ekn9oDYfBt0oqJSGGwLEhKvn+QaqMGTy//9dURTLf+vp7W5j6GvmKryYdnwJCDITaPFI2hujXV4CH9krhvaE5w==
   dependencies:
     "@babel/runtime" "7.0.0"
     warning "^4.0.1"
 
-react-swipeable-views-utils@^0.13.4:
-  version "0.13.4"
-  resolved "https://registry.yarnpkg.com/react-swipeable-views-utils/-/react-swipeable-views-utils-0.13.4.tgz#809fe408e55ed80f84eea508074387c23febf0ab"
-  integrity sha512-C6Ppq7Z5JIn4l8gKuRzzoGcm5Yiu57HBribjZ0T8DIeLisvIvk8A+Wysb1JhP0hsnJ9hIozlEZ8oJi4eBUTRXg==
+react-swipeable-views-utils@^0.13.9:
+  version "0.13.9"
+  resolved "https://registry.yarnpkg.com/react-swipeable-views-utils/-/react-swipeable-views-utils-0.13.9.tgz#a66e98f2f4502d8b00182901f80d13b2f903e10f"
+  integrity sha512-QLGxRKrbJCbWz94vkWLzb1Daaa2Y/TZKmsNKQ6WSNrS+chrlfZ3z9tqZ7YUJlW6pRWp3QZdLSY3UE3cN0TXXmw==
   dependencies:
     "@babel/runtime" "7.0.0"
-    fbjs "^0.8.4"
     keycode "^2.1.7"
     prop-types "^15.6.0"
     react-event-listener "^0.6.0"
-    react-swipeable-views-core "^0.13.1"
+    react-swipeable-views-core "^0.13.7"
+    shallow-equal "^1.2.1"
 
-react-swipeable-views@^0.13.4:
-  version "0.13.4"
-  resolved "https://registry.yarnpkg.com/react-swipeable-views/-/react-swipeable-views-0.13.4.tgz#ebbe50a8592b185dbedf9e0060eaee09cf6b2c67"
-  integrity sha512-Qwmaj8LASEgxp3i4FBEgs1LM/Yqk7mFRp0fRgXH515NIEePUcjrrkuwvvmvwNQLDbN6PNv4QAuosEaTRyjEOUA==
+react-swipeable-views@^0.13.9:
+  version "0.13.9"
+  resolved "https://registry.yarnpkg.com/react-swipeable-views/-/react-swipeable-views-0.13.9.tgz#d6a6c508bf5288ad55509f9c65916db5df0f2cec"
+  integrity sha512-WXC2FKYvZ9QdJ31v9LjEJEl1bA7E4AcaloTkbW0uU0dYf5uvv4aOpiyxubvOkVl1a5L2UAHmKSif4TmJ9usrSg==
   dependencies:
     "@babel/runtime" "7.0.0"
-    dom-helpers "^5.1.3"
     prop-types "^15.5.4"
-    react-swipeable-views-core "^0.13.1"
-    react-swipeable-views-utils "^0.13.4"
+    react-swipeable-views-core "^0.13.7"
+    react-swipeable-views-utils "^0.13.9"
     warning "^4.0.1"
 
 react-test-renderer@^16.0.0-0, react-test-renderer@^16.12.0:
@@ -9110,10 +9082,10 @@ regjsparser@^0.6.0:
   dependencies:
     jsesc "~0.5.0"
 
-rellax@^1.10.0:
-  version "1.10.0"
-  resolved "https://registry.yarnpkg.com/rellax/-/rellax-1.10.0.tgz#0308b813b458f9175d37ffb4272e1f616eab1341"
-  integrity sha512-BtxD9b8cAQcTs6iat1fqKvHMjIZ8CaxjsC5U/cIIVHC4LjkIsr0ZmeqxUm5ZvBvyjLwfPbU8Wcryp77sR5C8QA==
+rellax@^1.12.1:
+  version "1.12.1"
+  resolved "https://registry.yarnpkg.com/rellax/-/rellax-1.12.1.tgz#1b433ef7ac4aa3573449a33efab391c112f6b34d"
+  integrity sha512-XBIi0CDpW5FLTujYjYBn1CIbK2CJL6TsAg/w409KghP2LucjjzBjsujXDAjyBLWgsfupfUcL5WzdnIPcGfK7XA==
 
 remove-trailing-separator@^1.0.1:
   version "1.1.0"
@@ -9313,24 +9285,24 @@ rgba-regex@^1.0.0:
   resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3"
   integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=
 
-rimraf@2.6.3, rimraf@^2.6.2, rimraf@~2.6.2:
+rimraf@2.6.3, rimraf@~2.6.2:
   version "2.6.3"
   resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
   integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==
   dependencies:
     glob "^7.1.3"
 
-rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3, rimraf@^2.7.1:
+rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3, rimraf@^2.7.1:
   version "2.7.1"
   resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
   integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
   dependencies:
     glob "^7.1.3"
 
-rimraf@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.0.tgz#614176d4b3010b75e5c390eb0ee96f6dc0cebb9b"
-  integrity sha512-NDGVxTsjqfunkds7CqsOiEnxln4Bo7Nddl3XhS4pXg5OzwkLqJ971ZVAAnB+DDLnF76N+VnDEiBHaVV8I06SUg==
+rimraf@^3.0.2:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
+  integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
   dependencies:
     glob "^7.1.3"
 
@@ -9456,10 +9428,10 @@ sass-loader@^8.0.2:
     schema-utils "^2.6.1"
     semver "^6.3.0"
 
-sass@^1.24.2:
-  version "1.24.2"
-  resolved "https://registry.yarnpkg.com/sass/-/sass-1.24.2.tgz#0a0e0f00368be6808b2e94470172266ac45498fe"
-  integrity sha512-0JxdMMRd0fOmGFQFRI91vh4n0Ed766ib9JwPUa+1C37zn3VaqlHxbknUn/6LqP/MSfvNPxRYoCrYf5g8vu4OHw==
+sass@^1.25.0:
+  version "1.25.0"
+  resolved "https://registry.yarnpkg.com/sass/-/sass-1.25.0.tgz#f8bd7dfbb39d6b0305e27704a8ebe637820693f3"
+  integrity sha512-uQMjye0Y70SEDGO56n0j91tauqS9E1BmpKHtiYNQScXDHeaE9uHwNEqQNFf4Bes/3DHMNinB6u79JsG10XWNyw==
   dependencies:
     chokidar ">=2.0.0 <4.0.0"
 
@@ -9485,10 +9457,10 @@ schema-utils@^1.0.0:
     ajv-errors "^1.0.0"
     ajv-keywords "^3.1.0"
 
-schema-utils@^2.5.0, schema-utils@^2.6.0, schema-utils@^2.6.1:
-  version "2.6.1"
-  resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.1.tgz#eb78f0b945c7bcfa2082b3565e8db3548011dc4f"
-  integrity sha512-0WXHDs1VDJyo+Zqs9TKLKyD/h7yDpHUhEFsM2CzkICFdoX1av+GBq/J2xRTFfsQO5kBfhZzANf2VcIm84jqDbg==
+schema-utils@^2.5.0, schema-utils@^2.6.0, schema-utils@^2.6.1, schema-utils@^2.6.4:
+  version "2.6.4"
+  resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.4.tgz#a27efbf6e4e78689d91872ee3ccfa57d7bdd0f53"
+  integrity sha512-VNjcaUxVnEeun6B2fiiUDjXXBtD4ZSH7pdbfIu1pOFwgptDPLMo/z9jr4sUfsjFVPqDCEin/F7IYlq7/E6yDbQ==
   dependencies:
     ajv "^6.10.2"
     ajv-keywords "^3.4.1"
@@ -9595,7 +9567,7 @@ set-value@^2.0.0, set-value@^2.0.1:
     is-plain-object "^2.0.3"
     split-string "^3.0.1"
 
-setimmediate@^1.0.4, setimmediate@^1.0.5:
+setimmediate@^1.0.4:
   version "1.0.5"
   resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
   integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=
@@ -9625,6 +9597,11 @@ shallow-clone@^3.0.0:
   dependencies:
     kind-of "^6.0.2"
 
+shallow-equal@^1.2.1:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/shallow-equal/-/shallow-equal-1.2.1.tgz#4c16abfa56043aa20d050324efa68940b0da79da"
+  integrity sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==
+
 shebang-command@^1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
@@ -9794,6 +9771,11 @@ source-map-url@^0.4.0:
   resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3"
   integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=
 
+source-map@0.5.6:
+  version "0.5.6"
+  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
+  integrity sha1-dc449SvwczxafwwRjYEzSiu19BI=
+
 source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7:
   version "0.5.7"
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
@@ -9907,11 +9889,40 @@ stable@~0.1.6:
   resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf"
   integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==
 
+stack-generator@^2.0.5:
+  version "2.0.5"
+  resolved "https://registry.yarnpkg.com/stack-generator/-/stack-generator-2.0.5.tgz#fb00e5b4ee97de603e0773ea78ce944d81596c36"
+  integrity sha512-/t1ebrbHkrLrDuNMdeAcsvynWgoH/i4o8EGGfX7dEYDoTXOYVAkEpFdtshlvabzc6JlJ8Kf9YdFEoz7JkzGN9Q==
+  dependencies:
+    stackframe "^1.1.1"
+
 stack-utils@^1.0.1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8"
   integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==
 
+stackframe@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.1.1.tgz#ffef0a3318b1b60c3b58564989aca5660729ec71"
+  integrity sha512-0PlYhdKh6AfFxRyK/v+6/k+/mMfyiEBbTM5L94D0ZytQnJ166wuwoTYLHFWGbs2dpA8Rgq763KGWmN1EQEYHRQ==
+
+stacktrace-gps@^3.0.4:
+  version "3.0.4"
+  resolved "https://registry.yarnpkg.com/stacktrace-gps/-/stacktrace-gps-3.0.4.tgz#7688dc2fc09ffb3a13165ebe0dbcaf41bcf0c69a"
+  integrity sha512-qIr8x41yZVSldqdqe6jciXEaSCKw1U8XTXpjDuy0ki/apyTn/r3w9hDAAQOhZdxvsC93H+WwwEu5cq5VemzYeg==
+  dependencies:
+    source-map "0.5.6"
+    stackframe "^1.1.1"
+
+stacktrace-js@^2.0.2:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/stacktrace-js/-/stacktrace-js-2.0.2.tgz#4ca93ea9f494752d55709a081d400fdaebee897b"
+  integrity sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==
+  dependencies:
+    error-stack-parser "^2.0.6"
+    stack-generator "^2.0.5"
+    stacktrace-gps "^3.0.4"
+
 static-extend@^0.1.1:
   version "0.1.2"
   resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6"
@@ -10149,6 +10160,13 @@ supports-color@^5.3.0:
   dependencies:
     has-flag "^3.0.0"
 
+supports-color@^7.0.0:
+  version "7.1.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1"
+  integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==
+  dependencies:
+    has-flag "^4.0.0"
+
 svgo@^1.0.0:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.1.1.tgz#12384b03335bcecd85cfa5f4e3375fed671cb985"
@@ -10239,15 +10257,16 @@ terser-webpack-plugin@^1.4.3:
     webpack-sources "^1.4.0"
     worker-farm "^1.7.0"
 
-terser-webpack-plugin@^2.3.2:
-  version "2.3.2"
-  resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-2.3.2.tgz#6d3d1b0590c8f729bfbaeb7fb2528b8b62db4c74"
-  integrity sha512-SmvB/6gtEPv+CJ88MH5zDOsZdKXPS/Uzv2//e90+wM1IHFUhsguPKEILgzqrM1nQ4acRXN/SV4Obr55SXC+0oA==
+terser-webpack-plugin@^2.3.5:
+  version "2.3.5"
+  resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-2.3.5.tgz#5ad971acce5c517440ba873ea4f09687de2f4a81"
+  integrity sha512-WlWksUoq+E4+JlJ+h+U+QUzXpcsMSSNXkDy9lBVkSqDn1w23Gg29L/ary9GeJVYCGiNJJX7LnVc4bwL1N3/g1w==
   dependencies:
     cacache "^13.0.1"
     find-cache-dir "^3.2.0"
-    jest-worker "^24.9.0"
-    schema-utils "^2.6.1"
+    jest-worker "^25.1.0"
+    p-limit "^2.2.2"
+    schema-utils "^2.6.4"
     serialize-javascript "^2.1.2"
     source-map "^0.6.1"
     terser "^4.4.3"
@@ -10508,11 +10527,6 @@ typedarray@^0.0.6:
   resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
   integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
 
-ua-parser-js@^0.7.18:
-  version "0.7.19"
-  resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.19.tgz#94151be4c0a7fb1d001af7022fdaca4642659e4b"
-  integrity sha512-T3PVJ6uz8i0HzPxOF9SWzWAlfN/DavlpQqepn22xgve/5QecC+XMCAtmUNnY7C9StehaV6exjUCI801lOI7QlQ==
-
 uglify-js@^3.1.4:
   version "3.7.2"
   resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.2.tgz#cb1a601e67536e9ed094a92dd1e333459643d3f9"
@@ -10690,10 +10704,10 @@ utils-merge@1.0.1:
   resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
   integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
 
-uuid@^3.0.1, uuid@^3.3.2, uuid@^3.3.3:
-  version "3.3.3"
-  resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866"
-  integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==
+uuid@^3.0.1, uuid@^3.3.2, uuid@^3.4.0:
+  version "3.4.0"
+  resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
+  integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
 
 v8-compile-cache@2.0.3, v8-compile-cache@^2.0.3:
   version "2.0.3"
@@ -10828,10 +10842,10 @@ webpack-bundle-analyzer@^3.6.0:
     opener "^1.5.1"
     ws "^6.0.0"
 
-webpack-cli@^3.3.10:
-  version "3.3.10"
-  resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.10.tgz#17b279267e9b4fb549023fae170da8e6e766da13"
-  integrity sha512-u1dgND9+MXaEt74sJR4PR7qkPxXUSQ0RXYq8x1L6Jg1MYVEmGPrH6Ah6C4arD4r0J1P5HKjRqpab36k0eIzPqg==
+webpack-cli@^3.3.11:
+  version "3.3.11"
+  resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.11.tgz#3bf21889bf597b5d82c38f215135a411edfdc631"
+  integrity sha512-dXlfuml7xvAFwYUPsrtQAA9e4DOe58gnzSxhgrO/ZM/gyXTBowrsYeubyN4mqGhYdpXMFNyQ6emjJS9M7OBd4g==
   dependencies:
     chalk "2.4.2"
     cross-spawn "6.0.5"
@@ -10968,11 +10982,6 @@ whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3:
   dependencies:
     iconv-lite "0.4.24"
 
-whatwg-fetch@>=0.10.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb"
-  integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==
-
 whatwg-mimetype@^2.1.0, whatwg-mimetype@^2.2.0:
   version "2.3.0"
   resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf"