diff --git a/Gemfile b/Gemfile
index ec0284a0d..1cec0dcd5 100644
--- a/Gemfile
+++ b/Gemfile
@@ -17,7 +17,7 @@ gem 'makara', '~> 0.5'
gem 'pghero', '~> 2.8'
gem 'dotenv-rails', '~> 2.7'
-gem 'aws-sdk-s3', '~> 1.98', require: false
+gem 'aws-sdk-s3', '~> 1.99', require: false
gem 'fog-core', '<= 2.1.0'
gem 'fog-openstack', '~> 0.3', require: false
gem 'paperclip', '~> 6.0'
@@ -62,7 +62,7 @@ gem 'link_header', '~> 0.0'
gem 'mime-types', '~> 3.3.1', require: 'mime/types/columnar'
gem 'nokogiri', '~> 1.12'
gem 'nsa', '~> 0.2'
-gem 'oj', '~> 3.12'
+gem 'oj', '~> 3.13'
gem 'ox', '~> 2.14'
gem 'parslet'
gem 'parallel', '~> 1.20'
@@ -122,7 +122,7 @@ group :test do
gem 'rails-controller-testing', '~> 1.0'
gem 'rspec-sidekiq', '~> 3.1'
gem 'simplecov', '~> 0.21', require: false
- gem 'webmock', '~> 3.13'
+ gem 'webmock', '~> 3.14'
gem 'parallel_tests', '~> 3.7'
gem 'rspec_junit_formatter', '~> 0.4'
end
@@ -136,7 +136,7 @@ group :development do
gem 'letter_opener', '~> 1.7'
gem 'letter_opener_web', '~> 1.4'
gem 'memory_profiler'
- gem 'rubocop', '~> 1.18', require: false
+ gem 'rubocop', '~> 1.19', require: false
gem 'rubocop-rails', '~> 2.11', require: false
gem 'brakeman', '~> 5.1', require: false
gem 'bundler-audit', '~> 0.8', require: false
diff --git a/Gemfile.lock b/Gemfile.lock
index 0e1042c7c..92cb9b497 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -79,7 +79,7 @@ GEM
encryptor (~> 3.0.0)
awrence (1.1.1)
aws-eventstream (1.1.1)
- aws-partitions (1.482.0)
+ aws-partitions (1.488.0)
aws-sdk-core (3.119.0)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.239.0)
@@ -88,7 +88,7 @@ GEM
aws-sdk-kms (1.46.0)
aws-sdk-core (~> 3, >= 3.119.0)
aws-sigv4 (~> 1.1)
- aws-sdk-s3 (1.98.0)
+ aws-sdk-s3 (1.99.0)
aws-sdk-core (~> 3, >= 3.119.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.1)
@@ -112,7 +112,7 @@ GEM
concurrent-ruby (~> 1.0, >= 1.0.5)
redis (>= 1.0, <= 5.0)
builder (3.2.4)
- bullet (6.1.4)
+ bullet (6.1.5)
activesupport (>= 3.0.0)
uniform_notifier (~> 1.11)
bundler-audit (0.8.0)
@@ -218,8 +218,8 @@ GEM
multipart-post (>= 1.2, < 3)
ruby2_keywords
faraday-net_http (1.0.1)
- fast_blank (1.0.0)
- fastimage (2.2.4)
+ fast_blank (1.0.1)
+ fastimage (2.2.5)
ffi (1.15.0)
ffi-compiler (1.0.1)
ffi (>= 1.0.0)
@@ -332,7 +332,7 @@ GEM
activesupport (>= 4)
railties (>= 4)
request_store (~> 1.0)
- loofah (2.10.0)
+ loofah (2.12.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mail (2.7.1)
@@ -364,7 +364,7 @@ GEM
net-ssh (>= 2.6.5, < 7.0.0)
net-ssh (6.1.0)
nio4r (2.5.7)
- nokogiri (1.12.2)
+ nokogiri (1.12.3)
mini_portile2 (~> 2.6.1)
racc (~> 1.4)
nsa (0.2.8)
@@ -372,7 +372,7 @@ GEM
concurrent-ruby (~> 1.0, >= 1.0.2)
sidekiq (>= 3.5)
statsd-ruby (~> 1.4, >= 1.4.0)
- oj (3.12.2)
+ oj (3.13.2)
omniauth (1.9.1)
hashie (>= 3.4.6)
rack (>= 1.6.2, < 3)
@@ -397,7 +397,7 @@ GEM
mimemagic (~> 0.3.0)
terrapin (~> 0.6.0)
parallel (1.20.1)
- parallel_tests (3.7.0)
+ parallel_tests (3.7.1)
parallel
parser (3.0.2.0)
ast (~> 2.4.1)
@@ -428,7 +428,7 @@ GEM
public_suffix (4.0.6)
puma (5.4.0)
nio4r (~> 2.0)
- pundit (2.1.0)
+ pundit (2.1.1)
activesupport (>= 3.0.0)
raabro (1.4.0)
racc (1.5.2)
@@ -477,7 +477,7 @@ GEM
rake (>= 0.13)
thor (~> 1.0)
rainbow (3.0.0)
- rake (13.0.3)
+ rake (13.0.6)
rdf (3.1.15)
hamster (~> 3.0)
link_header (~> 0.0, >= 0.0.8)
@@ -508,7 +508,7 @@ GEM
rspec-mocks (3.10.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.10.0)
- rspec-rails (5.0.1)
+ rspec-rails (5.0.2)
actionpack (>= 5.2)
activesupport (>= 5.2)
railties (>= 5.2)
@@ -522,16 +522,16 @@ GEM
rspec-support (3.10.2)
rspec_junit_formatter (0.4.1)
rspec-core (>= 2, < 4, != 2.12.0)
- rubocop (1.18.4)
+ rubocop (1.19.0)
parallel (~> 1.10)
parser (>= 3.0.0.0)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml
- rubocop-ast (>= 1.8.0, < 2.0)
+ rubocop-ast (>= 1.9.1, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 3.0)
- rubocop-ast (1.8.0)
+ rubocop-ast (1.10.0)
parser (>= 3.0.1.1)
rubocop-rails (2.11.3)
activesupport (>= 4.2.0)
@@ -595,7 +595,7 @@ GEM
stackprof (0.2.17)
statsd-ruby (1.5.0)
stoplight (2.2.1)
- strong_migrations (0.7.7)
+ strong_migrations (0.7.8)
activerecord (>= 5)
temple (0.8.2)
terminal-table (3.0.0)
@@ -630,7 +630,7 @@ GEM
unf_ext
unf_ext (0.0.7.7)
unicode-display_width (1.7.0)
- uniform_notifier (1.14.1)
+ uniform_notifier (1.14.2)
warden (1.2.9)
rack (>= 2.0.9)
webauthn (3.0.0.alpha1)
@@ -643,8 +643,8 @@ GEM
safety_net_attestation (~> 0.4.0)
securecompare (~> 1.0)
tpm-key_attestation (~> 0.9.0)
- webmock (3.13.0)
- addressable (>= 2.3.6)
+ webmock (3.14.0)
+ addressable (>= 2.8.0)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
webpacker (5.4.0)
@@ -672,7 +672,7 @@ DEPENDENCIES
active_record_query_trace (~> 1.8)
addressable (~> 2.8)
annotate (~> 3.1)
- aws-sdk-s3 (~> 1.98)
+ aws-sdk-s3 (~> 1.99)
better_errors (~> 2.9)
binding_of_caller (~> 1.0)
blurhash (~> 0.1)
@@ -731,7 +731,7 @@ DEPENDENCIES
net-ldap (~> 0.17)
nokogiri (~> 1.12)
nsa (~> 0.2)
- oj (~> 3.12)
+ oj (~> 3.13)
omniauth (~> 1.9)
omniauth-cas (~> 2.0)
omniauth-rails_csrf_protection (~> 0.1)
@@ -766,7 +766,7 @@ DEPENDENCIES
rspec-rails (~> 5.0)
rspec-sidekiq (~> 3.1)
rspec_junit_formatter (~> 0.4)
- rubocop (~> 1.18)
+ rubocop (~> 1.19)
rubocop-rails (~> 2.11)
ruby-progressbar (~> 1.11)
sanitize (~> 6.0)
@@ -788,7 +788,7 @@ DEPENDENCIES
twitter-text (~> 3.1.0)
tzinfo-data (~> 1.2021)
webauthn (~> 3.0.0.alpha1)
- webmock (~> 3.13)
+ webmock (~> 3.14)
webpacker (~> 5.4)
webpush (~> 0.3)
xorcist (~> 1.1)
diff --git a/app/javascript/flavours/glitch/components/attachment_list.js b/app/javascript/flavours/glitch/components/attachment_list.js
index 68d8d29c7..68b80b19f 100644
--- a/app/javascript/flavours/glitch/components/attachment_list.js
+++ b/app/javascript/flavours/glitch/components/attachment_list.js
@@ -2,6 +2,8 @@ import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
import ImmutablePureComponent from 'react-immutable-pure-component';
+import { FormattedMessage } from 'react-intl';
+import classNames from 'classnames';
import Icon from 'flavours/glitch/components/icon';
const filename = url => url.split('/').pop().split('#')[0].split('?')[0];
@@ -16,29 +18,13 @@ export default class AttachmentList extends ImmutablePureComponent {
render () {
const { media, compact } = this.props;
- if (compact) {
- return (
-
-
- {media.map(attachment => {
- const displayUrl = attachment.get('remote_url') || attachment.get('url');
-
- return (
- -
- {filename(displayUrl)}
-
- );
- })}
-
-
- );
- }
-
return (
-
-
-
-
+
+ {!compact && (
+
+
+
+ )}
{media.map(attachment => {
@@ -46,7 +32,11 @@ export default class AttachmentList extends ImmutablePureComponent {
return (
-
- {filename(displayUrl)}
+
+ {compact && }
+ {compact && ' ' }
+ {displayUrl ? filename(displayUrl) : }
+
);
})}
diff --git a/app/javascript/flavours/glitch/styles/components/media.scss b/app/javascript/flavours/glitch/styles/components/media.scss
index 855cd07a9..8a551be73 100644
--- a/app/javascript/flavours/glitch/styles/components/media.scss
+++ b/app/javascript/flavours/glitch/styles/components/media.scss
@@ -400,7 +400,8 @@
opacity: 0.2;
}
- .video-player__buttons button {
+ .video-player__buttons button,
+ .video-player__buttons a {
color: currentColor;
opacity: 0.75;
diff --git a/app/javascript/mastodon/components/attachment_list.js b/app/javascript/mastodon/components/attachment_list.js
index ebd696583..0e23889de 100644
--- a/app/javascript/mastodon/components/attachment_list.js
+++ b/app/javascript/mastodon/components/attachment_list.js
@@ -2,6 +2,8 @@ import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
import ImmutablePureComponent from 'react-immutable-pure-component';
+import { FormattedMessage } from 'react-intl';
+import classNames from 'classnames';
import Icon from 'mastodon/components/icon';
const filename = url => url.split('/').pop().split('#')[0].split('?')[0];
@@ -16,29 +18,13 @@ export default class AttachmentList extends ImmutablePureComponent {
render () {
const { media, compact } = this.props;
- if (compact) {
- return (
-
-
- {media.map(attachment => {
- const displayUrl = attachment.get('remote_url') || attachment.get('url');
-
- return (
- -
- {filename(displayUrl)}
-
- );
- })}
-
-
- );
- }
-
return (
-
-
-
-
+
+ {!compact && (
+
+
+
+ )}
{media.map(attachment => {
@@ -46,7 +32,11 @@ export default class AttachmentList extends ImmutablePureComponent {
return (
-
- {filename(displayUrl)}
+
+ {compact && }
+ {compact && ' ' }
+ {displayUrl ? filename(displayUrl) : }
+
);
})}
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss
index 0a74eaa3d..30ac804ea 100644
--- a/app/javascript/styles/mastodon/components.scss
+++ b/app/javascript/styles/mastodon/components.scss
@@ -5542,7 +5542,8 @@ a.status-card.compact:hover {
opacity: 0.2;
}
- .video-player__buttons button {
+ .video-player__buttons button,
+ .video-player__buttons a {
color: currentColor;
opacity: 0.75;
diff --git a/app/models/account.rb b/app/models/account.rb
index ab3cac0d6..2cfa77615 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -58,8 +58,9 @@ class Account < ApplicationRecord
hub_url
)
- USERNAME_RE = /[a-z0-9_]+([a-z0-9_\.-]+[a-z0-9_]+)?/i
- MENTION_RE = /(?<=^|[^\/[:word:]])@((#{USERNAME_RE})(?:@[[:word:]\.\-]+[a-z0-9]+)?)/i
+ USERNAME_RE = /[a-z0-9_]+([a-z0-9_\.-]+[a-z0-9_]+)?/i
+ MENTION_RE = /(?<=^|[^\/[:word:]])@((#{USERNAME_RE})(?:@[[:word:]\.\-]+[a-z0-9]+)?)/i
+ URL_PREFIX_RE = /\Ahttp(s?):\/\/[^\/]+/
include AccountAssociations
include AccountAvatar
@@ -381,7 +382,7 @@ class Account < ApplicationRecord
def synchronization_uri_prefix
return 'local' if local?
- @synchronization_uri_prefix ||= uri[/http(s?):\/\/[^\/]+\//]
+ @synchronization_uri_prefix ||= "#{uri[URL_PREFIX_RE]}/"
end
class Field < ActiveModelSerializers::Model
diff --git a/app/models/concerns/account_interactions.rb b/app/models/concerns/account_interactions.rb
index 4bf62539c..8f19176a7 100644
--- a/app/models/concerns/account_interactions.rb
+++ b/app/models/concerns/account_interactions.rb
@@ -254,10 +254,13 @@ module AccountInteractions
.where('users.current_sign_in_at > ?', User::ACTIVE_DURATION.ago)
end
- def remote_followers_hash(url_prefix)
- Rails.cache.fetch("followers_hash:#{id}:#{url_prefix}") do
+ def remote_followers_hash(url)
+ url_prefix = url[Account::URL_PREFIX_RE]
+ return if url_prefix.blank?
+
+ Rails.cache.fetch("followers_hash:#{id}:#{url_prefix}/") do
digest = "\x00" * 32
- followers.where(Account.arel_table[:uri].matches(url_prefix + '%', false, true)).pluck_each(:uri) do |uri|
+ followers.where(Account.arel_table[:uri].matches("#{Account.sanitize_sql_like(url_prefix)}/%", false, true)).or(followers.where(uri: url_prefix)).pluck_each(:uri) do |uri|
Xorcist.xor!(digest, Digest::SHA256.digest(uri))
end
digest.unpack('H*')[0]
diff --git a/app/services/resolve_account_service.rb b/app/services/resolve_account_service.rb
index 5400612bf..b266c019e 100644
--- a/app/services/resolve_account_service.rb
+++ b/app/services/resolve_account_service.rb
@@ -142,6 +142,7 @@ class ResolveAccountService < BaseService
end
def queue_deletion!
+ @account.suspend!(origin: :remote)
AccountDeletionWorker.perform_async(@account.id, reserve_username: false, skip_activitypub: true)
end
diff --git a/app/services/unsuspend_account_service.rb b/app/services/unsuspend_account_service.rb
index 949c670aa..39d8a6ba7 100644
--- a/app/services/unsuspend_account_service.rb
+++ b/app/services/unsuspend_account_service.rb
@@ -1,13 +1,14 @@
# frozen_string_literal: true
class UnsuspendAccountService < BaseService
+ include Payloadable
def call(account)
@account = account
unsuspend!
refresh_remote_account!
- return if @account.nil?
+ return if @account.nil? || @account.suspended?
merge_into_home_timelines!
merge_into_list_timelines!
diff --git a/app/workers/activitypub/delivery_worker.rb b/app/workers/activitypub/delivery_worker.rb
index 6c5a576a7..788f2cf80 100644
--- a/app/workers/activitypub/delivery_worker.rb
+++ b/app/workers/activitypub/delivery_worker.rb
@@ -44,11 +44,7 @@ class ActivityPub::DeliveryWorker
end
def synchronization_header
- "collectionId=\"#{account_followers_url(@source_account)}\", digest=\"#{@source_account.remote_followers_hash(inbox_url_prefix)}\", url=\"#{account_followers_synchronization_url(@source_account)}\""
- end
-
- def inbox_url_prefix
- @inbox_url[/http(s?):\/\/[^\/]+\//]
+ "collectionId=\"#{account_followers_url(@source_account)}\", digest=\"#{@source_account.remote_followers_hash(@inbox_url)}\", url=\"#{account_followers_synchronization_url(@source_account)}\""
end
def perform_request
diff --git a/dist/nginx.conf b/dist/nginx.conf
index a0429d2aa..27ca868ab 100644
--- a/dist/nginx.conf
+++ b/dist/nginx.conf
@@ -31,6 +31,7 @@ server {
ssl_ciphers HIGH:!MEDIUM:!LOW:!aNULL:!NULL:!SHA;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
+ ssl_session_tickets off;
# Uncomment these lines once you acquire a certificate:
# ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
@@ -51,7 +52,7 @@ server {
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
- add_header Strict-Transport-Security "max-age=31536000";
+ add_header Strict-Transport-Security "max-age=31536000" always;
location / {
try_files $uri @proxy;
@@ -59,13 +60,13 @@ server {
location ~ ^/(emoji|packs|system/accounts/avatars|system/media_attachments/files) {
add_header Cache-Control "public, max-age=31536000, immutable";
- add_header Strict-Transport-Security "max-age=31536000";
+ add_header Strict-Transport-Security "max-age=31536000" always;
try_files $uri @proxy;
}
location /sw.js {
add_header Cache-Control "public, max-age=0";
- add_header Strict-Transport-Security "max-age=31536000";
+ add_header Strict-Transport-Security "max-age=31536000" always;
try_files $uri @proxy;
}
@@ -89,7 +90,7 @@ server {
proxy_cache_valid 410 24h;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
add_header X-Cached $upstream_cache_status;
- add_header Strict-Transport-Security "max-age=31536000";
+ add_header Strict-Transport-Security "max-age=31536000" always;
tcp_nodelay on;
}
diff --git a/package.json b/package.json
index e89187147..593f991f6 100644
--- a/package.json
+++ b/package.json
@@ -60,13 +60,13 @@
},
"private": true,
"dependencies": {
- "@babel/core": "^7.14.8",
+ "@babel/core": "^7.15.0",
"@babel/plugin-proposal-decorators": "^7.14.5",
"@babel/plugin-transform-react-inline-elements": "^7.14.5",
"@babel/plugin-transform-runtime": "^7.14.5",
"@babel/preset-env": "^7.15.0",
"@babel/preset-react": "^7.14.5",
- "@babel/runtime": "^7.14.8",
+ "@babel/runtime": "^7.15.3",
"@gamestdio/websocket": "^0.3.2",
"@github/webauthn-json": "^0.5.7",
"@rails/ujs": "^6.1.4",
@@ -81,7 +81,7 @@
"babel-plugin-react-intl": "^6.2.0",
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
"babel-runtime": "^6.26.0",
- "blurhash": "^1.1.3",
+ "blurhash": "^1.1.4",
"classnames": "^2.3.1",
"color-blend": "^3.0.1",
"compression-webpack-plugin": "^6.1.1",
@@ -146,7 +146,7 @@
"react-textarea-autosize": "^8.3.3",
"react-toggle": "^4.1.2",
"redis": "^3.1.2",
- "redux": "^4.1.0",
+ "redux": "^4.1.1",
"redux-immutable": "^4.0.0",
"redux-thunk": "^2.2.0",
"regenerator-runtime": "^0.13.9",
@@ -154,7 +154,7 @@
"requestidlecallback": "^0.3.0",
"reselect": "^4.0.0",
"rimraf": "^3.0.2",
- "sass": "^1.37.0",
+ "sass": "^1.38.0",
"sass-loader": "^10.2.0",
"stacktrace-js": "^2.0.2",
"stringz": "^2.1.0",
@@ -171,15 +171,15 @@
"webpack-cli": "^3.3.12",
"webpack-merge": "^5.8.0",
"wicg-inert": "^3.1.1",
- "ws": "^8.0.0"
+ "ws": "^8.1.0"
},
"devDependencies": {
"@testing-library/jest-dom": "^5.14.1",
- "@testing-library/react": "^11.2.7",
+ "@testing-library/react": "^12.0.0",
"babel-eslint": "^10.1.0",
"babel-jest": "^27.0.6",
"eslint": "^7.32.0",
- "eslint-plugin-import": "~2.23.4",
+ "eslint-plugin-import": "~2.24.0",
"eslint-plugin-jsx-a11y": "~6.4.1",
"eslint-plugin-promise": "~5.1.0",
"eslint-plugin-react": "~7.24.0",
@@ -189,7 +189,7 @@
"react-test-renderer": "^16.14.0",
"sass-lint": "^1.13.1",
"webpack-dev-server": "^3.11.2",
- "yargs": "^17.0.1"
+ "yargs": "^17.1.1"
},
"resolutions": {
"kind-of": "^6.0.3"
diff --git a/spec/models/concerns/account_interactions_spec.rb b/spec/models/concerns/account_interactions_spec.rb
index db959280c..fc653671e 100644
--- a/spec/models/concerns/account_interactions_spec.rb
+++ b/spec/models/concerns/account_interactions_spec.rb
@@ -546,46 +546,57 @@ describe AccountInteractions do
end
end
- describe '#followers_hash' do
+ describe '#remote_followers_hash' do
let(:me) { Fabricate(:account, username: 'Me') }
let(:remote_1) { Fabricate(:account, username: 'alice', domain: 'example.org', uri: 'https://example.org/users/alice') }
let(:remote_2) { Fabricate(:account, username: 'bob', domain: 'example.org', uri: 'https://example.org/users/bob') }
- let(:remote_3) { Fabricate(:account, username: 'eve', domain: 'foo.org', uri: 'https://foo.org/users/eve') }
+ let(:remote_3) { Fabricate(:account, username: 'instance-actor', domain: 'example.org', uri: 'https://example.org') }
+ let(:remote_4) { Fabricate(:account, username: 'eve', domain: 'foo.org', uri: 'https://foo.org/users/eve') }
before do
remote_1.follow!(me)
remote_2.follow!(me)
remote_3.follow!(me)
+ remote_4.follow!(me)
me.follow!(remote_1)
end
- context 'on a local user' do
- it 'returns correct hash for remote domains' do
- expect(me.remote_followers_hash('https://example.org/')).to eq '707962e297b7bd94468a21bc8e506a1bcea607a9142cd64e27c9b106b2a5f6ec'
- expect(me.remote_followers_hash('https://foo.org/')).to eq 'ccb9c18a67134cfff9d62c7f7e7eb88e6b803446c244b84265565f4eba29df0e'
- end
-
- it 'invalidates cache as needed when removing or adding followers' do
- expect(me.remote_followers_hash('https://example.org/')).to eq '707962e297b7bd94468a21bc8e506a1bcea607a9142cd64e27c9b106b2a5f6ec'
- remote_1.unfollow!(me)
- expect(me.remote_followers_hash('https://example.org/')).to eq '241b00794ce9b46aa864f3220afadef128318da2659782985bac5ed5bd436bff'
- remote_1.follow!(me)
- expect(me.remote_followers_hash('https://example.org/')).to eq '707962e297b7bd94468a21bc8e506a1bcea607a9142cd64e27c9b106b2a5f6ec'
- end
+ it 'returns correct hash for remote domains' do
+ expect(me.remote_followers_hash('https://example.org/')).to eq '20aecbe774b3d61c25094370baf370012b9271c5b172ecedb05caff8d79ef0c7'
+ expect(me.remote_followers_hash('https://foo.org/')).to eq 'ccb9c18a67134cfff9d62c7f7e7eb88e6b803446c244b84265565f4eba29df0e'
+ expect(me.remote_followers_hash('https://foo.org.evil.com/')).to eq '0000000000000000000000000000000000000000000000000000000000000000'
+ expect(me.remote_followers_hash('https://foo')).to eq '0000000000000000000000000000000000000000000000000000000000000000'
end
- context 'on a remote user' do
- it 'returns correct hash for remote domains' do
- expect(remote_1.local_followers_hash).to eq Digest::SHA256.hexdigest(ActivityPub::TagManager.instance.uri_for(me))
- end
+ it 'invalidates cache as needed when removing or adding followers' do
+ expect(me.remote_followers_hash('https://example.org/')).to eq '20aecbe774b3d61c25094370baf370012b9271c5b172ecedb05caff8d79ef0c7'
+ remote_3.unfollow!(me)
+ expect(me.remote_followers_hash('https://example.org/')).to eq '707962e297b7bd94468a21bc8e506a1bcea607a9142cd64e27c9b106b2a5f6ec'
+ remote_1.unfollow!(me)
+ expect(me.remote_followers_hash('https://example.org/')).to eq '241b00794ce9b46aa864f3220afadef128318da2659782985bac5ed5bd436bff'
+ remote_1.follow!(me)
+ expect(me.remote_followers_hash('https://example.org/')).to eq '707962e297b7bd94468a21bc8e506a1bcea607a9142cd64e27c9b106b2a5f6ec'
+ end
+ end
- it 'invalidates cache as needed when removing or adding followers' do
- expect(remote_1.local_followers_hash).to eq Digest::SHA256.hexdigest(ActivityPub::TagManager.instance.uri_for(me))
- me.unfollow!(remote_1)
- expect(remote_1.local_followers_hash).to eq '0000000000000000000000000000000000000000000000000000000000000000'
- me.follow!(remote_1)
- expect(remote_1.local_followers_hash).to eq Digest::SHA256.hexdigest(ActivityPub::TagManager.instance.uri_for(me))
- end
+ describe '#local_followers_hash' do
+ let(:me) { Fabricate(:account, username: 'Me') }
+ let(:remote_1) { Fabricate(:account, username: 'alice', domain: 'example.org', uri: 'https://example.org/users/alice') }
+
+ before do
+ me.follow!(remote_1)
+ end
+
+ it 'returns correct hash for local users' do
+ expect(remote_1.local_followers_hash).to eq Digest::SHA256.hexdigest(ActivityPub::TagManager.instance.uri_for(me))
+ end
+
+ it 'invalidates cache as needed when removing or adding followers' do
+ expect(remote_1.local_followers_hash).to eq Digest::SHA256.hexdigest(ActivityPub::TagManager.instance.uri_for(me))
+ me.unfollow!(remote_1)
+ expect(remote_1.local_followers_hash).to eq '0000000000000000000000000000000000000000000000000000000000000000'
+ me.follow!(remote_1)
+ expect(remote_1.local_followers_hash).to eq Digest::SHA256.hexdigest(ActivityPub::TagManager.instance.uri_for(me))
end
end
diff --git a/spec/services/suspend_account_service_spec.rb b/spec/services/suspend_account_service_spec.rb
new file mode 100644
index 000000000..cf7eb257a
--- /dev/null
+++ b/spec/services/suspend_account_service_spec.rb
@@ -0,0 +1,85 @@
+require 'rails_helper'
+
+RSpec.describe SuspendAccountService, type: :service do
+ shared_examples 'common behavior' do
+ let!(:local_follower) { Fabricate(:user, current_sign_in_at: 1.hour.ago).account }
+ let!(:list) { Fabricate(:list, account: local_follower) }
+
+ subject do
+ -> { described_class.new.call(account) }
+ end
+
+ before do
+ allow(FeedManager.instance).to receive(:unmerge_from_home).and_return(nil)
+ allow(FeedManager.instance).to receive(:unmerge_from_list).and_return(nil)
+
+ local_follower.follow!(account)
+ list.accounts << account
+ end
+
+ it "unmerges from local followers' feeds" do
+ subject.call
+ expect(FeedManager.instance).to have_received(:unmerge_from_home).with(account, local_follower)
+ expect(FeedManager.instance).to have_received(:unmerge_from_list).with(account, list)
+ end
+
+ it 'marks account as suspended' do
+ is_expected.to change { account.suspended? }.from(false).to(true)
+ end
+ end
+
+ describe 'suspending a local account' do
+ def match_update_actor_request(req, account)
+ json = JSON.parse(req.body)
+ actor_id = ActivityPub::TagManager.instance.uri_for(account)
+ json['type'] == 'Update' && json['actor'] == actor_id && json['object']['id'] == actor_id && json['object']['suspended']
+ end
+
+ before do
+ stub_request(:post, 'https://alice.com/inbox').to_return(status: 201)
+ stub_request(:post, 'https://bob.com/inbox').to_return(status: 201)
+ end
+
+ include_examples 'common behavior' do
+ let!(:account) { Fabricate(:account) }
+ let!(:remote_follower) { Fabricate(:account, uri: 'https://alice.com', inbox_url: 'https://alice.com/inbox', protocol: :activitypub) }
+ let!(:remote_reporter) { Fabricate(:account, uri: 'https://bob.com', inbox_url: 'https://bob.com/inbox', protocol: :activitypub) }
+ let!(:report) { Fabricate(:report, account: remote_reporter, target_account: account) }
+
+ before do
+ remote_follower.follow!(account)
+ end
+
+ it 'sends an update actor to followers and reporters' do
+ subject.call
+ expect(a_request(:post, remote_follower.inbox_url).with { |req| match_update_actor_request(req, account) }).to have_been_made.once
+ expect(a_request(:post, remote_reporter.inbox_url).with { |req| match_update_actor_request(req, account) }).to have_been_made.once
+ end
+ end
+ end
+
+ describe 'suspending a remote account' do
+ def match_reject_follow_request(req, account, followee)
+ json = JSON.parse(req.body)
+ json['type'] == 'Reject' && json['actor'] == ActivityPub::TagManager.instance.uri_for(followee) && json['object']['actor'] == account.uri
+ end
+
+ before do
+ stub_request(:post, 'https://bob.com/inbox').to_return(status: 201)
+ end
+
+ include_examples 'common behavior' do
+ let!(:account) { Fabricate(:account, domain: 'bob.com', uri: 'https://bob.com', inbox_url: 'https://bob.com/inbox', protocol: :activitypub) }
+ let!(:local_followee) { Fabricate(:account) }
+
+ before do
+ account.follow!(local_followee)
+ end
+
+ it 'sends a reject follow' do
+ subject.call
+ expect(a_request(:post, account.inbox_url).with { |req| match_reject_follow_request(req, account, local_followee) }).to have_been_made.once
+ end
+ end
+ end
+end
diff --git a/spec/services/unsuspend_account_service_spec.rb b/spec/services/unsuspend_account_service_spec.rb
new file mode 100644
index 000000000..d52cb6cc0
--- /dev/null
+++ b/spec/services/unsuspend_account_service_spec.rb
@@ -0,0 +1,135 @@
+require 'rails_helper'
+
+RSpec.describe UnsuspendAccountService, type: :service do
+ shared_examples 'common behavior' do
+ let!(:local_follower) { Fabricate(:user, current_sign_in_at: 1.hour.ago).account }
+ let!(:list) { Fabricate(:list, account: local_follower) }
+
+ subject do
+ -> { described_class.new.call(account) }
+ end
+
+ before do
+ allow(FeedManager.instance).to receive(:merge_into_home).and_return(nil)
+ allow(FeedManager.instance).to receive(:merge_into_list).and_return(nil)
+
+ local_follower.follow!(account)
+ list.accounts << account
+
+ account.suspend!(origin: :local)
+ end
+ end
+
+ describe 'unsuspending a local account' do
+ def match_update_actor_request(req, account)
+ json = JSON.parse(req.body)
+ actor_id = ActivityPub::TagManager.instance.uri_for(account)
+ json['type'] == 'Update' && json['actor'] == actor_id && json['object']['id'] == actor_id && !json['object']['suspended']
+ end
+
+ before do
+ stub_request(:post, 'https://alice.com/inbox').to_return(status: 201)
+ stub_request(:post, 'https://bob.com/inbox').to_return(status: 201)
+ end
+
+ it 'marks account as unsuspended' do
+ is_expected.to change { account.suspended? }.from(true).to(false)
+ end
+
+ include_examples 'common behavior' do
+ let!(:account) { Fabricate(:account) }
+ let!(:remote_follower) { Fabricate(:account, uri: 'https://alice.com', inbox_url: 'https://alice.com/inbox', protocol: :activitypub) }
+ let!(:remote_reporter) { Fabricate(:account, uri: 'https://bob.com', inbox_url: 'https://bob.com/inbox', protocol: :activitypub) }
+ let!(:report) { Fabricate(:report, account: remote_reporter, target_account: account) }
+
+ before do
+ remote_follower.follow!(account)
+ end
+
+ it "merges back into local followers' feeds" do
+ subject.call
+ expect(FeedManager.instance).to have_received(:merge_into_home).with(account, local_follower)
+ expect(FeedManager.instance).to have_received(:merge_into_list).with(account, list)
+ end
+
+ it 'sends an update actor to followers and reporters' do
+ subject.call
+ expect(a_request(:post, remote_follower.inbox_url).with { |req| match_update_actor_request(req, account) }).to have_been_made.once
+ expect(a_request(:post, remote_reporter.inbox_url).with { |req| match_update_actor_request(req, account) }).to have_been_made.once
+ end
+ end
+ end
+
+ describe 'unsuspending a remote account' do
+ include_examples 'common behavior' do
+ let!(:account) { Fabricate(:account, domain: 'bob.com', uri: 'https://bob.com', inbox_url: 'https://bob.com/inbox', protocol: :activitypub) }
+ let!(:reslove_account_service) { double }
+
+ before do
+ allow(ResolveAccountService).to receive(:new).and_return(reslove_account_service)
+ end
+
+ context 'when the account is not remotely suspended' do
+ before do
+ allow(reslove_account_service).to receive(:call).with(account).and_return(account)
+ end
+
+ it 're-fetches the account' do
+ subject.call
+ expect(reslove_account_service).to have_received(:call).with(account)
+ end
+
+ it "merges back into local followers' feeds" do
+ subject.call
+ expect(FeedManager.instance).to have_received(:merge_into_home).with(account, local_follower)
+ expect(FeedManager.instance).to have_received(:merge_into_list).with(account, list)
+ end
+
+ it 'marks account as unsuspended' do
+ is_expected.to change { account.suspended? }.from(true).to(false)
+ end
+ end
+
+ context 'when the account is remotely suspended' do
+ before do
+ allow(reslove_account_service).to receive(:call).with(account) do |account|
+ account.suspend!(origin: :remote)
+ account
+ end
+ end
+
+ it 're-fetches the account' do
+ subject.call
+ expect(reslove_account_service).to have_received(:call).with(account)
+ end
+
+ it "does not merge back into local followers' feeds" do
+ subject.call
+ expect(FeedManager.instance).to_not have_received(:merge_into_home).with(account, local_follower)
+ expect(FeedManager.instance).to_not have_received(:merge_into_list).with(account, list)
+ end
+
+ it 'does not mark the account as unsuspended' do
+ is_expected.not_to change { account.suspended? }
+ end
+ end
+
+ context 'when the account is remotely deleted' do
+ before do
+ allow(reslove_account_service).to receive(:call).with(account).and_return(nil)
+ end
+
+ it 're-fetches the account' do
+ subject.call
+ expect(reslove_account_service).to have_received(:call).with(account)
+ end
+
+ it "does not merge back into local followers' feeds" do
+ subject.call
+ expect(FeedManager.instance).to_not have_received(:merge_into_home).with(account, local_follower)
+ expect(FeedManager.instance).to_not have_received(:merge_into_list).with(account, list)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/workers/activitypub/delivery_worker_spec.rb b/spec/workers/activitypub/delivery_worker_spec.rb
index f4633731e..d39393d50 100644
--- a/spec/workers/activitypub/delivery_worker_spec.rb
+++ b/spec/workers/activitypub/delivery_worker_spec.rb
@@ -11,7 +11,7 @@ describe ActivityPub::DeliveryWorker do
let(:payload) { 'test' }
before do
- allow_any_instance_of(Account).to receive(:remote_followers_hash).with('https://example.com/').and_return('somehash')
+ allow_any_instance_of(Account).to receive(:remote_followers_hash).with('https://example.com/api').and_return('somehash')
end
describe 'perform' do
diff --git a/yarn.lock b/yarn.lock
index e9c26d056..53ffb4528 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -21,20 +21,20 @@
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.15.0.tgz#2dbaf8b85334796cafbb0f5793a90a2fc010b176"
integrity sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==
-"@babel/core@^7.1.0", "@babel/core@^7.14.8", "@babel/core@^7.7.2", "@babel/core@^7.7.5":
- version "7.14.8"
- resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.14.8.tgz#20cdf7c84b5d86d83fac8710a8bc605a7ba3f010"
- integrity sha512-/AtaeEhT6ErpDhInbXmjHcUQXH0L0TEgscfcxk1qbOvLuKCa5aZT0SOOtDKFY96/CLROwbLSKyFor6idgNaU4Q==
+"@babel/core@^7.1.0", "@babel/core@^7.15.0", "@babel/core@^7.7.2", "@babel/core@^7.7.5":
+ version "7.15.0"
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.15.0.tgz#749e57c68778b73ad8082775561f67f5196aafa8"
+ integrity sha512-tXtmTminrze5HEUPn/a0JtOzzfp0nk+UEXQ/tqIJo3WDGypl/2OFQEMll/zSFU8f/lfmfLXvTaORHF3cfXIQMw==
dependencies:
"@babel/code-frame" "^7.14.5"
- "@babel/generator" "^7.14.8"
- "@babel/helper-compilation-targets" "^7.14.5"
- "@babel/helper-module-transforms" "^7.14.8"
+ "@babel/generator" "^7.15.0"
+ "@babel/helper-compilation-targets" "^7.15.0"
+ "@babel/helper-module-transforms" "^7.15.0"
"@babel/helpers" "^7.14.8"
- "@babel/parser" "^7.14.8"
+ "@babel/parser" "^7.15.0"
"@babel/template" "^7.14.5"
- "@babel/traverse" "^7.14.8"
- "@babel/types" "^7.14.8"
+ "@babel/traverse" "^7.15.0"
+ "@babel/types" "^7.15.0"
convert-source-map "^1.7.0"
debug "^4.1.0"
gensync "^1.0.0-beta.2"
@@ -42,15 +42,6 @@
semver "^6.3.0"
source-map "^0.5.0"
-"@babel/generator@^7.14.8":
- version "7.14.8"
- resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.14.8.tgz#bf86fd6af96cf3b74395a8ca409515f89423e070"
- integrity sha512-cYDUpvIzhBVnMzRoY1fkSEhK/HmwEVwlyULYgn/tMQYd6Obag3ylCjONle3gdErfXBW61SVTlR9QR7uWlgeIkg==
- dependencies:
- "@babel/types" "^7.14.8"
- jsesc "^2.5.1"
- source-map "^0.5.0"
-
"@babel/generator@^7.15.0":
version "7.15.0"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.15.0.tgz#a7d0c172e0d814974bad5aa77ace543b97917f15"
@@ -178,21 +169,7 @@
dependencies:
"@babel/types" "^7.14.5"
-"@babel/helper-module-transforms@^7.14.5", "@babel/helper-module-transforms@^7.14.8":
- version "7.14.8"
- resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.14.8.tgz#d4279f7e3fd5f4d5d342d833af36d4dd87d7dc49"
- integrity sha512-RyE+NFOjXn5A9YU1dkpeBaduagTlZ0+fccnIcAGbv1KGUlReBj7utF7oEth8IdIBQPcux0DDgW5MFBH2xu9KcA==
- dependencies:
- "@babel/helper-module-imports" "^7.14.5"
- "@babel/helper-replace-supers" "^7.14.5"
- "@babel/helper-simple-access" "^7.14.8"
- "@babel/helper-split-export-declaration" "^7.14.5"
- "@babel/helper-validator-identifier" "^7.14.8"
- "@babel/template" "^7.14.5"
- "@babel/traverse" "^7.14.8"
- "@babel/types" "^7.14.8"
-
-"@babel/helper-module-transforms@^7.15.0":
+"@babel/helper-module-transforms@^7.14.5", "@babel/helper-module-transforms@^7.15.0":
version "7.15.0"
resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.15.0.tgz#679275581ea056373eddbe360e1419ef23783b08"
integrity sha512-RkGiW5Rer7fpXv9m1B3iHIFDZdItnO2/BLfWVW/9q7+KqQSDY5kUfQEbzdXM1MVhJGcugKV7kRrNVzNxmk7NBg==
@@ -278,11 +255,6 @@
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz#d0f0e277c512e0c938277faa85a3968c9a44c0e8"
integrity sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==
-"@babel/helper-validator-identifier@^7.14.8":
- version "7.14.8"
- resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.8.tgz#32be33a756f29e278a0d644fa08a2c9e0f88a34c"
- integrity sha512-ZGy6/XQjllhYQrNw/3zfWRwZCTVSiBLZ9DHVZxn9n2gip/7ab8mv2TWlKPIBk26RwedCBoWdjLmn+t9na2Gcow==
-
"@babel/helper-validator-identifier@^7.14.9":
version "7.14.9"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz#6654d171b2024f6d8ee151bf2509699919131d48"
@@ -330,12 +302,7 @@
chalk "^2.0.0"
js-tokens "^4.0.0"
-"@babel/parser@^7.1.0", "@babel/parser@^7.14.5", "@babel/parser@^7.14.8", "@babel/parser@^7.7.0":
- version "7.14.8"
- resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.14.8.tgz#66fd41666b2d7b840bd5ace7f7416d5ac60208d4"
- integrity sha512-syoCQFOoo/fzkWDeM0dLEZi5xqurb5vuyzwIMNZRNun+N/9A4cUZeQaE7dTrB8jGaKuJRBtEOajtnmw0I5hvvA==
-
-"@babel/parser@^7.15.0":
+"@babel/parser@^7.1.0", "@babel/parser@^7.14.5", "@babel/parser@^7.15.0", "@babel/parser@^7.7.0":
version "7.15.0"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.0.tgz#b6d6e29058ca369127b0eeca2a1c4b5794f1b6b9"
integrity sha512-0v7oNOjr6YT9Z2RAOTv4T9aP+ubfx4Q/OhVtAet7PFDt0t9Oy6Jn+/rfC6b8HJ5zEqrQCiMxJfgtHpmIminmJQ==
@@ -1030,10 +997,10 @@
dependencies:
regenerator-runtime "^0.12.0"
-"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.8", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
- version "7.14.8"
- resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.8.tgz#7119a56f421018852694290b9f9148097391b446"
- integrity sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg==
+"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.3", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
+ version "7.15.3"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.3.tgz#2e1c2880ca118e5b2f9988322bd8a7656a32502b"
+ integrity sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==
dependencies:
regenerator-runtime "^0.13.4"
@@ -1046,22 +1013,7 @@
"@babel/parser" "^7.14.5"
"@babel/types" "^7.14.5"
-"@babel/traverse@^7.1.0", "@babel/traverse@^7.13.0", "@babel/traverse@^7.14.5", "@babel/traverse@^7.14.8", "@babel/traverse@^7.7.0":
- version "7.14.8"
- resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.14.8.tgz#c0253f02677c5de1a8ff9df6b0aacbec7da1a8ce"
- integrity sha512-kexHhzCljJcFNn1KYAQ6A5wxMRzq9ebYpEDV4+WdNyr3i7O44tanbDOR/xjiG2F3sllan+LgwK+7OMk0EmydHg==
- dependencies:
- "@babel/code-frame" "^7.14.5"
- "@babel/generator" "^7.14.8"
- "@babel/helper-function-name" "^7.14.5"
- "@babel/helper-hoist-variables" "^7.14.5"
- "@babel/helper-split-export-declaration" "^7.14.5"
- "@babel/parser" "^7.14.8"
- "@babel/types" "^7.14.8"
- debug "^4.1.0"
- globals "^11.1.0"
-
-"@babel/traverse@^7.15.0":
+"@babel/traverse@^7.1.0", "@babel/traverse@^7.13.0", "@babel/traverse@^7.14.5", "@babel/traverse@^7.14.8", "@babel/traverse@^7.15.0", "@babel/traverse@^7.7.0":
version "7.15.0"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.15.0.tgz#4cca838fd1b2a03283c1f38e141f639d60b3fc98"
integrity sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw==
@@ -1473,19 +1425,19 @@
dependencies:
"@sinonjs/commons" "^1.7.0"
-"@testing-library/dom@^7.28.1":
- version "7.28.1"
- resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.28.1.tgz#dea78be6e1e6db32ddcb29a449e94d9700c79eb9"
- integrity sha512-acv3l6kDwZkQif/YqJjstT3ks5aaI33uxGNVIQmdKzbZ2eMKgg3EV2tB84GDdc72k3Kjhl6mO8yUt6StVIdRDg==
+"@testing-library/dom@^8.0.0":
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.1.0.tgz#f8358b1883844ea569ba76b7e94582168df5370d"
+ integrity sha512-kmW9alndr19qd6DABzQ978zKQ+J65gU2Rzkl8hriIetPnwpesRaK4//jEQyYh8fEALmGhomD/LBQqt+o+DL95Q==
dependencies:
"@babel/code-frame" "^7.10.4"
"@babel/runtime" "^7.12.5"
"@types/aria-query" "^4.2.0"
aria-query "^4.2.2"
chalk "^4.1.0"
- dom-accessibility-api "^0.5.4"
+ dom-accessibility-api "^0.5.6"
lz-string "^1.4.4"
- pretty-format "^26.6.2"
+ pretty-format "^27.0.2"
"@testing-library/jest-dom@^5.14.1":
version "5.14.1"
@@ -1502,13 +1454,13 @@
lodash "^4.17.15"
redent "^3.0.0"
-"@testing-library/react@^11.2.7":
- version "11.2.7"
- resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-11.2.7.tgz#b29e2e95c6765c815786c0bc1d5aed9cb2bf7818"
- integrity sha512-tzRNp7pzd5QmbtXNG/mhdcl7Awfu/Iz1RaVHY75zTdOkmHCuzMhRL83gWHSgOAcjS3CCbyfwUHMZgRJb4kAfpA==
+"@testing-library/react@^12.0.0":
+ version "12.0.0"
+ resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-12.0.0.tgz#9aeb2264521522ab9b68f519eaf15136148f164a"
+ integrity sha512-sh3jhFgEshFyJ/0IxGltRhwZv2kFKfJ3fN1vTZ6hhMXzz9ZbbcTgmDYM4e+zJv+oiVKKEWZPyqPAh4MQBI65gA==
dependencies:
"@babel/runtime" "^7.12.5"
- "@testing-library/dom" "^7.28.1"
+ "@testing-library/dom" "^8.0.0"
"@types/aria-query@^4.2.0":
version "4.2.0"
@@ -2075,6 +2027,11 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
"@types/color-name" "^1.1.1"
color-convert "^2.0.1"
+ansi-styles@^5.0.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b"
+ integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==
+
anymatch@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb"
@@ -2591,10 +2548,10 @@ bluebird@^3.5.5:
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
-blurhash@^1.1.3:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/blurhash/-/blurhash-1.1.3.tgz#dc325af7da836d07a0861d830bdd63694382483e"
- integrity sha512-yUhPJvXexbqbyijCIE/T2NCXcj9iNPhWmOKbPTuR/cm7Q5snXYIfnVnz6m7MWOXxODMz/Cr3UcVkRdHiuDVRDw==
+blurhash@^1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/blurhash/-/blurhash-1.1.4.tgz#a7010ceb3019cd2c9809b17c910ebf6175d29244"
+ integrity sha512-MXIPz6zwYUKayju+Uidf83KhH0vodZfeRl6Ich8Gu+KGl0JgKiFq9LsfqV7cVU5fKD/AotmduZqvOfrGKOfTaA==
bmp-js@^0.1.0:
version "0.1.0"
@@ -3991,7 +3948,7 @@ doctrine@^3.0.0:
dependencies:
esutils "^2.0.2"
-dom-accessibility-api@^0.5.4, dom-accessibility-api@^0.5.6:
+dom-accessibility-api@^0.5.6:
version "0.5.6"
resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.6.tgz#3f5d43b52c7a3bd68b5fb63fa47b4e4c1fdf65a9"
integrity sha512-DplGLZd8L1lN64jlT27N9TVSESFR5STaEJvX+thCby7fuCHonfPpAlodYc3vuUYbDuDec5w8AMP7oCM5TWFsqw==
@@ -4386,33 +4343,33 @@ escope@^3.6.0:
esrecurse "^4.1.0"
estraverse "^4.1.1"
-eslint-import-resolver-node@^0.3.4:
- version "0.3.4"
- resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz#85ffa81942c25012d8231096ddf679c03042c717"
- integrity sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==
+eslint-import-resolver-node@^0.3.5:
+ version "0.3.5"
+ resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.5.tgz#939bbb0f74e179e757ca87f7a4a890dabed18ac4"
+ integrity sha512-XMoPKjSpXbkeJ7ZZ9icLnJMTY5Mc1kZbCakHquaFsXPpyWOwK0TK6CODO+0ca54UoM9LKOxyUNnoVZRl8TeaAg==
dependencies:
- debug "^2.6.9"
- resolve "^1.13.1"
+ debug "^3.2.7"
+ resolve "^1.20.0"
-eslint-module-utils@^2.6.1:
- version "2.6.1"
- resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.1.tgz#b51be1e473dd0de1c5ea638e22429c2490ea8233"
- integrity sha512-ZXI9B8cxAJIH4nfkhTwcRTEAnrVfobYqwjWy/QMCZ8rHkZHFjf9yO4BzpiF9kCSfNlMG54eKigISHpX0+AaT4A==
+eslint-module-utils@^2.6.2:
+ version "2.6.2"
+ resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.2.tgz#94e5540dd15fe1522e8ffa3ec8db3b7fa7e7a534"
+ integrity sha512-QG8pcgThYOuqxupd06oYTZoNOGaUdTY1PqK+oS6ElF6vs4pBdk/aYxFVQQXzcrAqp9m7cl7lb2ubazX+g16k2Q==
dependencies:
debug "^3.2.7"
pkg-dir "^2.0.0"
-eslint-plugin-import@~2.23.4:
- version "2.23.4"
- resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.23.4.tgz#8dceb1ed6b73e46e50ec9a5bb2411b645e7d3d97"
- integrity sha512-6/wP8zZRsnQFiR3iaPFgh5ImVRM1WN5NUWfTIRqwOdeiGJlBcSk82o1FEVq8yXmy4lkIzTo7YhHCIxlU/2HyEQ==
+eslint-plugin-import@~2.24.0:
+ version "2.24.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.24.0.tgz#697ffd263e24da5e84e03b282f5fb62251777177"
+ integrity sha512-Kc6xqT9hiYi2cgybOc0I2vC9OgAYga5o/rAFinam/yF/t5uBqxQbauNPMC6fgb640T/89P0gFoO27FOilJ/Cqg==
dependencies:
array-includes "^3.1.3"
array.prototype.flat "^1.2.4"
debug "^2.6.9"
doctrine "^2.1.0"
- eslint-import-resolver-node "^0.3.4"
- eslint-module-utils "^2.6.1"
+ eslint-import-resolver-node "^0.3.5"
+ eslint-module-utils "^2.6.2"
find-up "^2.0.0"
has "^1.0.3"
is-core-module "^2.4.0"
@@ -8254,9 +8211,9 @@ path-key@^3.0.0, path-key@^3.1.0:
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
path-parse@^1.0.6:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
- integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
+ integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
path-to-regexp@0.1.7:
version "0.1.7"
@@ -8864,6 +8821,16 @@ pretty-format@^26.6.2:
ansi-styles "^4.0.0"
react-is "^17.0.1"
+pretty-format@^27.0.2:
+ version "27.0.6"
+ resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.0.6.tgz#ab770c47b2c6f893a21aefc57b75da63ef49a11f"
+ integrity sha512-8tGD7gBIENgzqA+UBzObyWqQ5B778VIFZA/S66cclyd5YkFLYs2Js7gxDKf0MXtTc9zcS7t1xhdfcElJ3YIvkQ==
+ dependencies:
+ "@jest/types" "^27.0.6"
+ ansi-regex "^5.0.0"
+ ansi-styles "^5.0.0"
+ react-is "^17.0.1"
+
process-nextick-args@~2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
@@ -9481,10 +9448,10 @@ redux-thunk@^2.2.0:
resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.3.0.tgz#51c2c19a185ed5187aaa9a2d08b666d0d6467622"
integrity sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw==
-redux@^4.0.0, redux@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/redux/-/redux-4.1.0.tgz#eb049679f2f523c379f1aff345c8612f294c88d4"
- integrity sha512-uI2dQN43zqLWCt6B/BMGRMY6db7TTY4qeHHfGeKb3EOhmOKjU3KdWvNLJyqaHRksv/ErdNH7cFZWg9jXtewy4g==
+redux@^4.0.0, redux@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/redux/-/redux-4.1.1.tgz#76f1c439bb42043f985fbd9bf21990e60bd67f47"
+ integrity sha512-hZQZdDEM25UY2P493kPYuKqviVwZ58lEmGQNeQ+gXa+U0gYPUBf7NKYazbe3m+bs/DzM/ahN12DbF+NG8i0CWw==
dependencies:
"@babel/runtime" "^7.9.2"
@@ -9737,7 +9704,7 @@ resolve-url@^0.2.1:
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
-resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.14.2, resolve@^1.18.1, resolve@^1.20.0:
+resolve@^1.10.0, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.18.1, resolve@^1.20.0:
version "1.20.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
@@ -9902,10 +9869,10 @@ sass-loader@^10.2.0:
schema-utils "^3.0.0"
semver "^7.3.2"
-sass@^1.37.0:
- version "1.37.0"
- resolved "https://registry.yarnpkg.com/sass/-/sass-1.37.0.tgz#f1b03a9d072ee9053a29d125c8130c78e92827c2"
- integrity sha512-B+Tu6cSAG8ffs/cqsZl/bgSH2pCmavDaPTYAoW8QA1qNHh/RqndNfVKuABKYkLjUQ5aq/BnCENVpE80cqdSM1w==
+sass@^1.38.0:
+ version "1.38.0"
+ resolved "https://registry.yarnpkg.com/sass/-/sass-1.38.0.tgz#2f3e60a1efdcdc910586fa79dc89d3399a145b4f"
+ integrity sha512-WBccZeMigAGKoI+NgD7Adh0ab1HUq+6BmyBUEaGxtErbUtWUevEbdgo5EZiJQofLUGcKtlNaO2IdN73AHEua5g==
dependencies:
chokidar ">=3.0.0 <4.0.0"
@@ -11816,10 +11783,10 @@ ws@^7.2.3, ws@^7.3.1:
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.3.tgz#160835b63c7d97bfab418fc1b8a9fced2ac01a74"
integrity sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==
-ws@^8.0.0:
- version "8.0.0"
- resolved "https://registry.yarnpkg.com/ws/-/ws-8.0.0.tgz#550605d13dfc1437c9ec1396975709c6d7ffc57d"
- integrity sha512-6AcSIXpBlS0QvCVKk+3cWnWElLsA6SzC0lkQ43ciEglgXJXiCWK3/CGFEJ+Ybgp006CMibamAsqOlxE9s4AvYA==
+ws@^8.1.0:
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-8.1.0.tgz#75e5ec608f66d3d3934ec6dbc4ebc8a34a68638c"
+ integrity sha512-0UWlCD2s3RSclw8FN+D0zDTUyMO+1kHwJQQJzkgUh16S8d3NYON0AKCEQPffE0ez4JyRFu76QDA9KR5bOG/7jw==
xml-name-validator@^3.0.0:
version "3.0.0"
@@ -11915,10 +11882,10 @@ yargs@^15.4.1:
y18n "^4.0.0"
yargs-parser "^18.1.2"
-yargs@^17.0.1:
- version "17.0.1"
- resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.0.1.tgz#6a1ced4ed5ee0b388010ba9fd67af83b9362e0bb"
- integrity sha512-xBBulfCc8Y6gLFcrPvtqKz9hz8SO0l1Ni8GgDekvBX2ro0HRQImDGnikfc33cgzcYUSncapnNcZDjVFIH3f6KQ==
+yargs@^17.1.1:
+ version "17.1.1"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.1.1.tgz#c2a8091564bdb196f7c0a67c1d12e5b85b8067ba"
+ integrity sha512-c2k48R0PwKIqKhPMWjeiF6y2xY/gPMUlro0sgxqXpbOIohWiLNXWslsootttv7E1e73QPAMQSg5FeySbVcpsPQ==
dependencies:
cliui "^7.0.2"
escalade "^3.1.1"