Merge branch 'master' into glitch-soc/merge-upstream

Conflicts:
	db/migrate/20170716191202_add_hide_notifications_to_mute.rb
	spec/controllers/application_controller_spec.rb

Took our version, upstream changes were only minor style linting.
This commit is contained in:
Thibaut Girka 2018-10-05 15:23:57 +02:00
commit 00fcdebed7
93 changed files with 406 additions and 324 deletions

View File

@ -1,5 +1,5 @@
FROM node:8.11.3-alpine as node FROM node:8.12.0-alpine as node
FROM ruby:2.4.4-alpine3.6 FROM ruby:2.4.4-alpine3.7
LABEL maintainer="https://github.com/tootsuite/mastodon" \ LABEL maintainer="https://github.com/tootsuite/mastodon" \
description="Your self-hosted, globally interconnected microblogging community" description="Your self-hosted, globally interconnected microblogging community"

27
Gemfile
View File

@ -10,14 +10,14 @@ gem 'rails', '~> 5.2.1'
gem 'thor', '~> 0.20' gem 'thor', '~> 0.20'
gem 'hamlit-rails', '~> 0.2' gem 'hamlit-rails', '~> 0.2'
gem 'pg', '~> 1.0' gem 'pg', '~> 1.1'
gem 'makara', '~> 0.4' gem 'makara', '~> 0.4'
gem 'pghero', '~> 2.2' gem 'pghero', '~> 2.2'
gem 'dotenv-rails', '~> 2.2', '< 2.3' gem 'dotenv-rails', '~> 2.2', '< 2.3'
gem 'aws-sdk-s3', '~> 1.9', require: false gem 'aws-sdk-s3', '~> 1.20', require: false
gem 'fog-core', '~> 1.45' gem 'fog-core', '~> 2.1'
gem 'fog-openstack', '~> 0.1', require: false gem 'fog-openstack', '~> 1.0', require: false
gem 'paperclip', '~> 6.0' gem 'paperclip', '~> 6.0'
gem 'paperclip-av-transcoder', '~> 0.6' gem 'paperclip-av-transcoder', '~> 0.6'
gem 'streamio-ffmpeg', '~> 3.0' gem 'streamio-ffmpeg', '~> 3.0'
@ -27,6 +27,7 @@ gem 'addressable', '~> 2.5'
gem 'bootsnap', '~> 1.3', require: false gem 'bootsnap', '~> 1.3', require: false
gem 'browser' gem 'browser'
gem 'charlock_holmes', '~> 0.7.6' gem 'charlock_holmes', '~> 0.7.6'
gem 'colorize'
gem 'iso-639' gem 'iso-639'
gem 'chewy', '~> 5.0' gem 'chewy', '~> 5.0'
gem 'cld3', '~> 3.2.0' gem 'cld3', '~> 3.2.0'
@ -50,10 +51,10 @@ gem 'hiredis', '~> 0.6'
gem 'redis-namespace', '~> 1.5' gem 'redis-namespace', '~> 1.5'
gem 'html2text' gem 'html2text'
gem 'htmlentities', '~> 4.3' gem 'htmlentities', '~> 4.3'
gem 'http', '~> 3.2' gem 'http', '~> 3.3'
gem 'http_accept_language', '~> 2.1' gem 'http_accept_language', '~> 2.1'
gem 'http_parser.rb', '~> 0.6', git: 'https://github.com/tmm1/http_parser.rb', ref: '54b17ba8c7d8d20a16dfc65d1775241833219cf2' gem 'http_parser.rb', '~> 0.6', git: 'https://github.com/tmm1/http_parser.rb', ref: '54b17ba8c7d8d20a16dfc65d1775241833219cf2'
gem 'httplog', '~> 1.0' gem 'httplog', '~> 1.1'
gem 'idn-ruby', require: 'idn' gem 'idn-ruby', require: 'idn'
gem 'kaminari', '~> 1.1' gem 'kaminari', '~> 1.1'
gem 'link_header', '~> 0.0' gem 'link_header', '~> 0.0'
@ -66,7 +67,7 @@ gem 'ox', '~> 2.10'
gem 'posix-spawn', git: 'https://github.com/rtomayko/posix-spawn', ref: '58465d2e213991f8afb13b984854a49fcdcc980c' gem 'posix-spawn', git: 'https://github.com/rtomayko/posix-spawn', ref: '58465d2e213991f8afb13b984854a49fcdcc980c'
gem 'pundit', '~> 1.1' gem 'pundit', '~> 1.1'
gem 'premailer-rails' gem 'premailer-rails'
gem 'rack-attack', '~> 5.2' gem 'rack-attack', '~> 5.4'
gem 'rack-cors', '~> 1.0', require: 'rack/cors' gem 'rack-cors', '~> 1.0', require: 'rack/cors'
gem 'rails-i18n', '~> 5.1' gem 'rails-i18n', '~> 5.1'
gem 'rails-settings-cached', '~> 0.6' gem 'rails-settings-cached', '~> 0.6'
@ -96,11 +97,11 @@ gem 'rdf-normalize', '~> 0.3'
group :development, :test do group :development, :test do
gem 'fabrication', '~> 2.20' gem 'fabrication', '~> 2.20'
gem 'fuubar', '~> 2.2' gem 'fuubar', '~> 2.3'
gem 'i18n-tasks', '~> 0.9', require: false gem 'i18n-tasks', '~> 0.9', require: false
gem 'pry-byebug', '~> 3.6' gem 'pry-byebug', '~> 3.6'
gem 'pry-rails', '~> 0.3' gem 'pry-rails', '~> 0.3'
gem 'rspec-rails', '~> 3.7' gem 'rspec-rails', '~> 3.8'
end end
group :production, :test do group :production, :test do
@ -108,14 +109,14 @@ group :production, :test do
end end
group :test do group :test do
gem 'capybara', '~> 2.18' gem 'capybara', '~> 3.8'
gem 'climate_control', '~> 0.2' gem 'climate_control', '~> 0.2'
gem 'faker', '~> 1.8' gem 'faker', '~> 1.8'
gem 'microformats', '~> 4.0' gem 'microformats', '~> 4.0'
gem 'rails-controller-testing', '~> 1.0' gem 'rails-controller-testing', '~> 1.0'
gem 'rspec-sidekiq', '~> 3.0' gem 'rspec-sidekiq', '~> 3.0'
gem 'simplecov', '~> 0.16', require: false gem 'simplecov', '~> 0.16', require: false
gem 'webmock', '~> 3.3' gem 'webmock', '~> 3.4'
gem 'parallel_tests', '~> 2.21' gem 'parallel_tests', '~> 2.21'
end end
@ -128,8 +129,8 @@ group :development do
gem 'letter_opener', '~> 1.4' gem 'letter_opener', '~> 1.4'
gem 'letter_opener_web', '~> 1.3' gem 'letter_opener_web', '~> 1.3'
gem 'memory_profiler' gem 'memory_profiler'
gem 'rubocop', '~> 0.55', require: false gem 'rubocop', '~> 0.59', require: false
gem 'brakeman', '~> 4.2', require: false gem 'brakeman', '~> 4.3', require: false
gem 'bundler-audit', '~> 0.6', require: false gem 'bundler-audit', '~> 0.6', require: false
gem 'scss_lint', '~> 0.57', require: false gem 'scss_lint', '~> 0.57', require: false

View File

@ -75,19 +75,21 @@ GEM
encryptor (~> 3.0.0) encryptor (~> 3.0.0)
av (0.9.0) av (0.9.0)
cocaine (~> 0.5.3) cocaine (~> 0.5.3)
aws-partitions (1.80.0) aws-eventstream (1.0.1)
aws-sdk-core (3.19.0) aws-partitions (1.105.0)
aws-sdk-core (3.29.0)
aws-eventstream (~> 1.0)
aws-partitions (~> 1.0) aws-partitions (~> 1.0)
aws-sigv4 (~> 1.0) aws-sigv4 (~> 1.0)
jmespath (~> 1.0) jmespath (~> 1.0)
aws-sdk-kms (1.5.0) aws-sdk-kms (1.9.0)
aws-sdk-core (~> 3) aws-sdk-core (~> 3, >= 3.26.0)
aws-sigv4 (~> 1.0) aws-sigv4 (~> 1.0)
aws-sdk-s3 (1.9.1) aws-sdk-s3 (1.20.0)
aws-sdk-core (~> 3) aws-sdk-core (~> 3, >= 3.26.0)
aws-sdk-kms (~> 1) aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.0) aws-sigv4 (~> 1.0)
aws-sigv4 (1.0.2) aws-sigv4 (1.0.3)
bcrypt (3.1.12) bcrypt (3.1.12)
benchmark-ips (2.7.2) benchmark-ips (2.7.2)
better_errors (2.4.0) better_errors (2.4.0)
@ -98,7 +100,7 @@ GEM
debug_inspector (>= 0.0.1) debug_inspector (>= 0.0.1)
bootsnap (1.3.2) bootsnap (1.3.2)
msgpack (~> 1.0) msgpack (~> 1.0)
brakeman (4.2.1) brakeman (4.3.1)
browser (2.5.3) browser (2.5.3)
builder (3.2.3) builder (3.2.3)
bullet (5.7.5) bullet (5.7.5)
@ -119,18 +121,18 @@ GEM
capistrano-rails (1.3.1) capistrano-rails (1.3.1)
capistrano (~> 3.1) capistrano (~> 3.1)
capistrano-bundler (~> 1.1) capistrano-bundler (~> 1.1)
capistrano-rbenv (2.1.3) capistrano-rbenv (2.1.4)
capistrano (~> 3.1) capistrano (~> 3.1)
sshkit (~> 1.3) sshkit (~> 1.3)
capistrano-yarn (2.0.2) capistrano-yarn (2.0.2)
capistrano (~> 3.0) capistrano (~> 3.0)
capybara (2.18.0) capybara (3.8.2)
addressable addressable
mini_mime (>= 0.1.3) mini_mime (>= 0.1.3)
nokogiri (>= 1.3.3) nokogiri (~> 1.8)
rack (>= 1.0.0) rack (>= 1.6.0)
rack-test (>= 0.5.4) rack-test (>= 0.6.3)
xpath (>= 2.0, < 4.0) xpath (~> 3.1)
case_transform (0.2) case_transform (0.2)
activesupport activesupport
charlock_holmes (0.7.6) charlock_holmes (0.7.6)
@ -154,7 +156,7 @@ GEM
css_parser (1.6.0) css_parser (1.6.0)
addressable addressable
debug_inspector (0.0.3) debug_inspector (0.0.3)
derailed_benchmarks (1.3.4) derailed_benchmarks (1.3.5)
benchmark-ips (~> 2) benchmark-ips (~> 2)
get_process_mem (~> 0) get_process_mem (~> 0)
heapy (~> 0) heapy (~> 0)
@ -211,27 +213,28 @@ GEM
faraday (0.15.0) faraday (0.15.0)
multipart-post (>= 1.2, < 3) multipart-post (>= 1.2, < 3)
fast_blank (1.0.0) fast_blank (1.0.0)
fastimage (2.1.1) fastimage (2.1.4)
ffi (1.9.25) ffi (1.9.25)
fog-core (1.45.0) fog-core (2.1.2)
builder builder
excon (~> 0.58) excon (~> 0.58)
formatador (~> 0.2) formatador (~> 0.2)
fog-json (1.0.2) mime-types
fog-core (~> 1.0) fog-json (1.2.0)
fog-core
multi_json (~> 1.10) multi_json (~> 1.10)
fog-openstack (0.1.25) fog-openstack (1.0.3)
fog-core (~> 1.40) fog-core (~> 2.1)
fog-json (>= 1.0) fog-json (>= 1.0)
ipaddress (>= 0.8) ipaddress (>= 0.8)
formatador (0.2.5) formatador (0.2.5)
fugit (1.1.6) fugit (1.1.6)
et-orbi (~> 1.1, >= 1.1.6) et-orbi (~> 1.1, >= 1.1.6)
raabro (~> 1.1) raabro (~> 1.1)
fuubar (2.3.1) fuubar (2.3.2)
rspec-core (~> 3.0) rspec-core (~> 3.0)
ruby-progressbar (~> 1.4) ruby-progressbar (~> 1.4)
get_process_mem (0.2.1) get_process_mem (0.2.2)
globalid (0.4.1) globalid (0.4.1)
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
goldfinger (2.1.0) goldfinger (2.1.0)
@ -252,7 +255,7 @@ GEM
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
hashdiff (0.3.7) hashdiff (0.3.7)
hashie (3.5.7) hashie (3.5.7)
heapy (0.1.3) heapy (0.1.4)
highline (1.7.10) highline (1.7.10)
hiredis (0.6.1) hiredis (0.6.1)
hitimes (1.3.0) hitimes (1.3.0)
@ -260,18 +263,18 @@ GEM
html2text (0.2.1) html2text (0.2.1)
nokogiri (~> 1.6) nokogiri (~> 1.6)
htmlentities (4.3.4) htmlentities (4.3.4)
http (3.2.0) http (3.3.0)
addressable (~> 2.3) addressable (~> 2.3)
http-cookie (~> 1.0) http-cookie (~> 1.0)
http-form_data (~> 2.0) http-form_data (~> 2.0)
http_parser.rb (~> 0.6.0) http_parser.rb (~> 0.6.0)
http-cookie (1.0.3) http-cookie (1.0.3)
domain_name (~> 0.5) domain_name (~> 0.5)
http-form_data (2.1.0) http-form_data (2.1.1)
http_accept_language (2.1.1) http_accept_language (2.1.1)
httplog (1.0.2) httplog (1.1.1)
colorize (~> 0.8)
rack (>= 1.0) rack (>= 1.0)
rainbow (>= 2.0.0)
i18n (1.1.0) i18n (1.1.0)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
i18n-tasks (0.9.21) i18n-tasks (0.9.21)
@ -287,6 +290,7 @@ GEM
idn-ruby (0.1.0) idn-ruby (0.1.0)
ipaddress (0.8.3) ipaddress (0.8.3)
iso-639 (0.2.8) iso-639 (0.2.8)
jaro_winkler (1.5.1)
jmespath (1.4.0) jmespath (1.4.0)
json (2.1.0) json (2.1.0)
json-ld (2.2.1) json-ld (2.2.1)
@ -340,7 +344,7 @@ GEM
mime-types-data (~> 3.2015) mime-types-data (~> 3.2015)
mime-types-data (3.2018.0812) mime-types-data (3.2018.0812)
mimemagic (0.3.2) mimemagic (0.3.2)
mini_mime (1.0.0) mini_mime (1.0.1)
mini_portile2 (2.3.0) mini_portile2 (2.3.0)
minitest (5.11.3) minitest (5.11.3)
msgpack (1.2.4) msgpack (1.2.4)
@ -352,7 +356,7 @@ GEM
net-ssh (>= 2.6.5) net-ssh (>= 2.6.5)
net-ssh (5.0.2) net-ssh (5.0.2)
nio4r (2.3.1) nio4r (2.3.1)
nokogiri (1.8.4) nokogiri (1.8.5)
mini_portile2 (~> 2.3.0) mini_portile2 (~> 2.3.0)
nokogumbo (1.5.0) nokogumbo (1.5.0)
nokogiri nokogiri
@ -390,16 +394,16 @@ GEM
parallel (1.12.1) parallel (1.12.1)
parallel_tests (2.21.3) parallel_tests (2.21.3)
parallel parallel
parser (2.5.1.0) parser (2.5.1.2)
ast (~> 2.4.0) ast (~> 2.4.0)
pastel (0.7.2) pastel (0.7.2)
equatable (~> 0.5.0) equatable (~> 0.5.0)
tty-color (~> 0.4.0) tty-color (~> 0.4.0)
pg (1.0.0) pg (1.1.3)
pghero (2.2.0) pghero (2.2.0)
activerecord activerecord
pkg-config (1.3.1) pkg-config (1.3.1)
powerpack (0.1.1) powerpack (0.1.2)
premailer (1.11.1) premailer (1.11.1)
addressable addressable
css_parser (>= 1.6.0) css_parser (>= 1.6.0)
@ -416,14 +420,14 @@ GEM
pry (~> 0.10) pry (~> 0.10)
pry-rails (0.3.6) pry-rails (0.3.6)
pry (>= 0.10.4) pry (>= 0.10.4)
public_suffix (3.0.2) public_suffix (3.0.3)
puma (3.11.4) puma (3.11.4)
pundit (1.1.0) pundit (1.1.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
raabro (1.1.6) raabro (1.1.6)
rack (2.0.5) rack (2.0.5)
rack-attack (5.2.0) rack-attack (5.4.1)
rack rack (>= 1.0, < 3)
rack-cors (1.0.2) rack-cors (1.0.2)
rack-protection (2.0.4) rack-protection (2.0.4)
rack rack
@ -474,7 +478,7 @@ GEM
link_header (~> 0.0, >= 0.0.8) link_header (~> 0.0, >= 0.0.8)
rdf-normalize (0.3.3) rdf-normalize (0.3.3)
rdf (>= 2.2, < 4.0) rdf (>= 2.2, < 4.0)
redis (4.0.1) redis (4.0.2)
redis-actionpack (5.0.2) redis-actionpack (5.0.2)
actionpack (>= 4.0, < 6) actionpack (>= 4.0, < 6)
redis-rack (>= 1, < 3) redis-rack (>= 1, < 3)
@ -502,29 +506,30 @@ GEM
rpam2 (4.0.2) rpam2 (4.0.2)
rqrcode (0.10.1) rqrcode (0.10.1)
chunky_png (~> 1.0) chunky_png (~> 1.0)
rspec-core (3.7.1) rspec-core (3.8.0)
rspec-support (~> 3.7.0) rspec-support (~> 3.8.0)
rspec-expectations (3.7.0) rspec-expectations (3.8.1)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.7.0) rspec-support (~> 3.8.0)
rspec-mocks (3.7.0) rspec-mocks (3.8.0)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.7.0) rspec-support (~> 3.8.0)
rspec-rails (3.7.2) rspec-rails (3.8.0)
actionpack (>= 3.0) actionpack (>= 3.0)
activesupport (>= 3.0) activesupport (>= 3.0)
railties (>= 3.0) railties (>= 3.0)
rspec-core (~> 3.7.0) rspec-core (~> 3.8.0)
rspec-expectations (~> 3.7.0) rspec-expectations (~> 3.8.0)
rspec-mocks (~> 3.7.0) rspec-mocks (~> 3.8.0)
rspec-support (~> 3.7.0) rspec-support (~> 3.8.0)
rspec-sidekiq (3.0.3) rspec-sidekiq (3.0.3)
rspec-core (~> 3.0, >= 3.0.0) rspec-core (~> 3.0, >= 3.0.0)
sidekiq (>= 2.4.0) sidekiq (>= 2.4.0)
rspec-support (3.7.1) rspec-support (3.8.0)
rubocop (0.55.0) rubocop (0.59.2)
jaro_winkler (~> 1.5.1)
parallel (~> 1.10) parallel (~> 1.10)
parser (>= 2.5) parser (>= 2.5, != 2.5.1.1)
powerpack (~> 0.1) powerpack (~> 0.1)
rainbow (>= 2.2.2, < 4.0) rainbow (>= 2.2.2, < 4.0)
ruby-progressbar (~> 1.7) ruby-progressbar (~> 1.7)
@ -624,11 +629,11 @@ GEM
unf (0.1.4) unf (0.1.4)
unf_ext unf_ext
unf_ext (0.0.7.5) unf_ext (0.0.7.5)
unicode-display_width (1.3.2) unicode-display_width (1.4.0)
uniform_notifier (1.11.0) uniform_notifier (1.11.0)
warden (1.2.7) warden (1.2.7)
rack (>= 1.0) rack (>= 1.0)
webmock (3.3.0) webmock (3.4.2)
addressable (>= 2.3.6) addressable (>= 2.3.6)
crack (>= 0.3.2) crack (>= 0.3.2)
hashdiff hashdiff
@ -636,14 +641,14 @@ GEM
activesupport (>= 4.2) activesupport (>= 4.2)
rack-proxy (>= 0.6.1) rack-proxy (>= 0.6.1)
railties (>= 4.2) railties (>= 4.2)
webpush (0.3.3) webpush (0.3.4)
hkdf (~> 0.2) hkdf (~> 0.2)
jwt (~> 2.0) jwt (~> 2.0)
websocket-driver (0.7.0) websocket-driver (0.7.0)
websocket-extensions (>= 0.1.0) websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.3) websocket-extensions (0.1.3)
wisper (2.0.0) wisper (2.0.0)
xpath (3.0.0) xpath (3.1.0)
nokogiri (~> 1.8) nokogiri (~> 1.8)
PLATFORMS PLATFORMS
@ -654,11 +659,11 @@ DEPENDENCIES
active_record_query_trace (~> 1.5) active_record_query_trace (~> 1.5)
addressable (~> 2.5) addressable (~> 2.5)
annotate (~> 2.7) annotate (~> 2.7)
aws-sdk-s3 (~> 1.9) aws-sdk-s3 (~> 1.20)
better_errors (~> 2.4) better_errors (~> 2.4)
binding_of_caller (~> 0.7) binding_of_caller (~> 0.7)
bootsnap (~> 1.3) bootsnap (~> 1.3)
brakeman (~> 4.2) brakeman (~> 4.3)
browser browser
bullet (~> 5.7) bullet (~> 5.7)
bundler-audit (~> 0.6) bundler-audit (~> 0.6)
@ -666,11 +671,12 @@ DEPENDENCIES
capistrano-rails (~> 1.3) capistrano-rails (~> 1.3)
capistrano-rbenv (~> 2.1) capistrano-rbenv (~> 2.1)
capistrano-yarn (~> 2.0) capistrano-yarn (~> 2.0)
capybara (~> 2.18) capybara (~> 3.8)
charlock_holmes (~> 0.7.6) charlock_holmes (~> 0.7.6)
chewy (~> 5.0) chewy (~> 5.0)
cld3 (~> 3.2.0) cld3 (~> 3.2.0)
climate_control (~> 0.2) climate_control (~> 0.2)
colorize
derailed_benchmarks derailed_benchmarks
devise (~> 4.5) devise (~> 4.5)
devise-two-factor (~> 3.0) devise-two-factor (~> 3.0)
@ -681,18 +687,18 @@ DEPENDENCIES
faker (~> 1.8) faker (~> 1.8)
fast_blank (~> 1.0) fast_blank (~> 1.0)
fastimage fastimage
fog-core (~> 1.45) fog-core (~> 2.1)
fog-openstack (~> 0.1) fog-openstack (~> 1.0)
fuubar (~> 2.2) fuubar (~> 2.3)
goldfinger (~> 2.1) goldfinger (~> 2.1)
hamlit-rails (~> 0.2) hamlit-rails (~> 0.2)
hiredis (~> 0.6) hiredis (~> 0.6)
html2text html2text
htmlentities (~> 4.3) htmlentities (~> 4.3)
http (~> 3.2) http (~> 3.3)
http_accept_language (~> 2.1) http_accept_language (~> 2.1)
http_parser.rb (~> 0.6)! http_parser.rb (~> 0.6)!
httplog (~> 1.0) httplog (~> 1.1)
i18n-tasks (~> 0.9) i18n-tasks (~> 0.9)
idn-ruby idn-ruby
iso-639 iso-639
@ -719,7 +725,7 @@ DEPENDENCIES
paperclip (~> 6.0) paperclip (~> 6.0)
paperclip-av-transcoder (~> 0.6) paperclip-av-transcoder (~> 0.6)
parallel_tests (~> 2.21) parallel_tests (~> 2.21)
pg (~> 1.0) pg (~> 1.1)
pghero (~> 2.2) pghero (~> 2.2)
pkg-config (~> 1.3) pkg-config (~> 1.3)
posix-spawn! posix-spawn!
@ -729,7 +735,7 @@ DEPENDENCIES
pry-rails (~> 0.3) pry-rails (~> 0.3)
puma (~> 3.11) puma (~> 3.11)
pundit (~> 1.1) pundit (~> 1.1)
rack-attack (~> 5.2) rack-attack (~> 5.4)
rack-cors (~> 1.0) rack-cors (~> 1.0)
rails (~> 5.2.1) rails (~> 5.2.1)
rails-controller-testing (~> 1.0) rails-controller-testing (~> 1.0)
@ -740,9 +746,9 @@ DEPENDENCIES
redis-namespace (~> 1.5) redis-namespace (~> 1.5)
redis-rails (~> 5.0) redis-rails (~> 5.0)
rqrcode (~> 0.10) rqrcode (~> 0.10)
rspec-rails (~> 3.7) rspec-rails (~> 3.8)
rspec-sidekiq (~> 3.0) rspec-sidekiq (~> 3.0)
rubocop (~> 0.55) rubocop (~> 0.59)
ruby-progressbar (~> 1.4) ruby-progressbar (~> 1.4)
sanitize (~> 4.6) sanitize (~> 4.6)
scss_lint (~> 0.57) scss_lint (~> 0.57)
@ -763,7 +769,7 @@ DEPENDENCIES
tty-prompt (~> 0.17) tty-prompt (~> 0.17)
twitter-text (~> 1.14) twitter-text (~> 1.14)
tzinfo-data (~> 1.2018) tzinfo-data (~> 1.2018)
webmock (~> 3.3) webmock (~> 3.4)
webpacker (~> 3.5) webpacker (~> 3.5)
webpush webpush
@ -771,4 +777,4 @@ RUBY VERSION
ruby 2.5.0p0 ruby 2.5.0p0
BUNDLED WITH BUNDLED WITH
1.16.3 1.16.5

View File

@ -95,7 +95,7 @@ module Admin
:remote, :remote,
:by_domain, :by_domain,
:silenced, :silenced,
:recent, :alphabetic,
:suspended, :suspended,
:username, :username,
:display_name, :display_name,

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
module Admin::FilterHelper module Admin::FilterHelper
ACCOUNT_FILTERS = %i(local remote by_domain silenced suspended recent username display_name email ip staff).freeze ACCOUNT_FILTERS = %i(local remote by_domain silenced suspended alphabetic username display_name email ip staff).freeze
REPORT_FILTERS = %i(resolved account_id target_account_id).freeze REPORT_FILTERS = %i(resolved account_id target_account_id).freeze
INVITE_FILTER = %i(available expired).freeze INVITE_FILTER = %i(available expired).freeze
CUSTOM_EMOJI_FILTERS = %i(local remote by_domain shortcode).freeze CUSTOM_EMOJI_FILTERS = %i(local remote by_domain shortcode).freeze

View File

@ -26,7 +26,7 @@ class ActivityPub::Activity::Accept < ActivityPub::Activity
end end
def relay def relay
@relay ||= Relay.find_by(follow_activity_id: object_uri) @relay ||= Relay.find_by(follow_activity_id: object_uri) unless object_uri.nil?
end end
def relay_follow? def relay_follow?

View File

@ -17,6 +17,8 @@ class ActivityPub::Activity::Delete < ActivityPub::Activity
end end
def delete_note def delete_note
return if object_uri.nil?
@status = Status.find_by(uri: object_uri, account: @account) @status = Status.find_by(uri: object_uri, account: @account)
@status ||= Status.find_by(uri: @object['atomUri'], account: @account) if @object.is_a?(Hash) && @object['atomUri'].present? @status ||= Status.find_by(uri: @object['atomUri'], account: @account) if @object.is_a?(Hash) && @object['atomUri'].present?

View File

@ -28,7 +28,7 @@ class ActivityPub::Activity::Reject < ActivityPub::Activity
end end
def relay def relay
@relay ||= Relay.find_by(follow_activity_id: object_uri) @relay ||= Relay.find_by(follow_activity_id: object_uri) unless object_uri.nil?
end end
def relay_follow? def relay_follow?

View File

@ -19,6 +19,8 @@ class ActivityPub::Activity::Undo < ActivityPub::Activity
private private
def undo_announce def undo_announce
return if object_uri.nil?
status = Status.find_by(uri: object_uri, account: @account) status = Status.find_by(uri: object_uri, account: @account)
status ||= Status.find_by(uri: @object['atomUri'], account: @account) if @object.is_a?(Hash) && @object['atomUri'].present? status ||= Status.find_by(uri: @object['atomUri'], account: @account) if @object.is_a?(Hash) && @object['atomUri'].present?

View File

@ -315,8 +315,8 @@ class Account < ApplicationRecord
def initialize(account, attributes) def initialize(account, attributes)
@account = account @account = account
@attributes = attributes @attributes = attributes
@name = attributes['name'].strip[0, 255] @name = attributes['name'].strip[0, string_limit]
@value = attributes['value'].strip[0, 255] @value = attributes['value'].strip[0, string_limit]
@verified_at = attributes['verified_at']&.to_datetime @verified_at = attributes['verified_at']&.to_datetime
@errors = {} @errors = {}
end end
@ -325,8 +325,18 @@ class Account < ApplicationRecord
verified_at.present? verified_at.present?
end end
def value_for_verification
@value_for_verification ||= begin
if account.local?
value
else
ActionController::Base.helpers.strip_tags(value)
end
end
end
def verifiable? def verifiable?
value.present? && value.start_with?('http://', 'https://') value_for_verification.present? && value_for_verification.start_with?('http://', 'https://')
end end
def mark_verified! def mark_verified!
@ -337,6 +347,16 @@ class Account < ApplicationRecord
def to_h def to_h
{ name: @name, value: @value, verified_at: @verified_at } { name: @name, value: @value, verified_at: @verified_at }
end end
private
def string_limit
if account.local?
255
else
2047
end
end
end end
class << self class << self

View File

@ -8,7 +8,7 @@ class AccountFilter
end end
def results def results
scope = Account.alphabetic scope = Account.recent
params.each do |key, value| params.each do |key, value|
scope.merge!(scope_for(key, value)) if value.present? scope.merge!(scope_for(key, value)) if value.present?
@ -29,8 +29,8 @@ class AccountFilter
Account.where(domain: value) Account.where(domain: value)
when 'silenced' when 'silenced'
Account.silenced Account.silenced
when 'recent' when 'alphabetic'
Account.recent Account.reorder(nil).alphabetic
when 'suspended' when 'suspended'
Account.suspended Account.suspended
when 'username' when 'username'

View File

@ -25,6 +25,7 @@ class Follow < ApplicationRecord
has_one :notification, as: :activity, dependent: :destroy has_one :notification, as: :activity, dependent: :destroy
validates :account_id, uniqueness: { scope: :target_account_id } validates :account_id, uniqueness: { scope: :target_account_id }
validates_with FollowLimitValidator, on: :create
scope :recent, -> { reorder(id: :desc) } scope :recent, -> { reorder(id: :desc) }

View File

@ -22,6 +22,7 @@ class FollowRequest < ApplicationRecord
has_one :notification, as: :activity, dependent: :destroy has_one :notification, as: :activity, dependent: :destroy
validates :account_id, uniqueness: { scope: :target_account_id } validates :account_id, uniqueness: { scope: :target_account_id }
validates_with FollowLimitValidator, on: :create
def authorize! def authorize!
account.follow!(target_account, reblogs: show_reblogs, uri: uri) account.follow!(target_account, reblogs: show_reblogs, uri: uri)

View File

@ -11,11 +11,7 @@ class REST::AccountSerializer < ActiveModel::Serializer
has_many :emojis, serializer: REST::CustomEmojiSerializer has_many :emojis, serializer: REST::CustomEmojiSerializer
class FieldSerializer < ActiveModel::Serializer class FieldSerializer < ActiveModel::Serializer
attributes :name, :value attributes :name, :value, :verified_at
attribute :verified_at, if: :verifiable?
delegate :verifiable?, to: :object
def value def value
Formatter.instance.format_field(object.account, object.value) Formatter.instance.format_field(object.account, object.value)

View File

@ -3,7 +3,7 @@
class VerifyLinkService < BaseService class VerifyLinkService < BaseService
def call(field) def call(field)
@link_back = ActivityPub::TagManager.instance.url_for(field.account) @link_back = ActivityPub::TagManager.instance.url_for(field.account)
@url = field.value @url = field.value_for_verification
perform_request! perform_request!

View File

@ -0,0 +1,27 @@
# frozen_string_literal: true
class FollowLimitValidator < ActiveModel::Validator
LIMIT = ENV.fetch('MAX_FOLLOWS_THRESHOLD', 7_500).to_i
RATIO = ENV.fetch('MAX_FOLLOWS_RATIO', 1.1).to_f
def validate(follow)
return if follow.account.nil? || !follow.account.local?
follow.errors.add(:base, I18n.t('users.follow_limit_reached', limit: self.class.limit_for_account(follow.account))) if limit_reached?(follow.account)
end
class << self
def limit_for_account(account)
if account.following_count < LIMIT
LIMIT
else
account.followers_count * RATIO
end
end
end
private
def limit_reached?(account)
account.following_count >= self.class.limit_for_account(account)
end
end

View File

@ -38,8 +38,8 @@
.filter-subset .filter-subset
%strong= t('admin.accounts.order.title') %strong= t('admin.accounts.order.title')
%ul %ul
%li= filter_link_to t('admin.accounts.order.alphabetic'), recent: nil %li= filter_link_to t('admin.accounts.order.most_recent'), alphabetic: nil
%li= filter_link_to t('admin.accounts.order.most_recent'), recent: '1' %li= filter_link_to t('admin.accounts.order.alphabetic'), alphabetic: '1'
= form_tag admin_accounts_url, method: 'GET', class: 'simple_form' do = form_tag admin_accounts_url, method: 'GET', class: 'simple_form' do
.fields-group .fields-group

View File

@ -37,6 +37,8 @@ class ImportWorker
end end
def import_rows def import_rows
CSV.new(import_contents).reject(&:blank?) rows = CSV.new(import_contents).reject(&:blank?)
rows = rows.take(FollowLimitValidator.limit_for_account(@import.account)) if @import.type == 'following'
rows
end end
end end

View File

@ -1,6 +1,6 @@
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
require 'bundler/setup' # Set up gems listed in the Gemfile. require 'bundler/setup' # Set up gems listed in the Gemfile.
require 'bootsnap' # Speed up boot time by caching expensive operations. require 'bootsnap' # Speed up boot time by caching expensive operations.
Bootsnap.setup( Bootsnap.setup(

View File

@ -42,7 +42,7 @@ Rails.application.configure do
config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
# Allow to specify public IP of reverse proxy if it's needed # Allow to specify public IP of reverse proxy if it's needed
config.action_dispatch.trusted_proxies = ENV['TRUSTED_PROXY_IP'].split.map { |item| IPAddr.new(item) } unless ENV['TRUSTED_PROXY_IP'].blank? config.action_dispatch.trusted_proxies = ENV['TRUSTED_PROXY_IP'].split.map { |item| IPAddr.new(item) } if ENV['TRUSTED_PROXY_IP'].present?
# Use the lowest log level to ensure availability of diagnostic information # Use the lowest log level to ensure availability of diagnostic information
# when problems arise. # when problems arise.

View File

@ -7,7 +7,7 @@ web_host = ENV.fetch('WEB_DOMAIN') { host }
alternate_domains = ENV.fetch('ALTERNATE_DOMAINS') { '' } alternate_domains = ENV.fetch('ALTERNATE_DOMAINS') { '' }
Rails.application.configure do Rails.application.configure do
https = Rails.env.production? || ENV['LOCAL_HTTPS'] == 'true' https = Rails.env.production? || ENV['LOCAL_HTTPS'] == 'true'
config.x.local_domain = host config.x.local_domain = host
config.x.web_domain = web_host config.x.web_domain = web_host

View File

@ -6,7 +6,7 @@ Rails.application.configure do
raise "No proxy host" unless proxy.host raise "No proxy host" unless proxy.host
host = proxy.host host = proxy.host
host = host[1...-1] if host[0] == '[' #for IPv6 address host = host[1...-1] if host[0] == '[' # for IPv6 address
config.x.http_client_proxy[:proxy] = { proxy_address: host, proxy_port: proxy.port, proxy_username: proxy.user, proxy_password: proxy.password }.compact config.x.http_client_proxy[:proxy] = { proxy_address: host, proxy_port: proxy.port, proxy_username: proxy.user, proxy_password: proxy.password }.compact
end end

View File

@ -3,7 +3,7 @@ Rails.application.config.middleware.use OmniAuth::Builder do
end end
Devise.setup do |config| Devise.setup do |config|
# Devise omniauth strategies # Devise omniauth strategies
options = {} options = {}
options[:redirect_at_sign_in] = ENV['OAUTH_REDIRECT_AT_SIGN_IN'] == 'true' options[:redirect_at_sign_in] = ENV['OAUTH_REDIRECT_AT_SIGN_IN'] == 'true'
@ -38,7 +38,7 @@ Devise.setup do |config|
saml_options = options saml_options = options
saml_options[:assertion_consumer_service_url] = ENV['SAML_ACS_URL'] if ENV['SAML_ACS_URL'] saml_options[:assertion_consumer_service_url] = ENV['SAML_ACS_URL'] if ENV['SAML_ACS_URL']
saml_options[:issuer] = ENV['SAML_ISSUER'] if ENV['SAML_ISSUER'] saml_options[:issuer] = ENV['SAML_ISSUER'] if ENV['SAML_ISSUER']
saml_options[:idp_sso_target_url] = ENV['SAML_IDP_SSO_TARGET_URL'] if ENV['SAML_IDP_SSO_TARGET_URL'] saml_options[:idp_sso_target_url] = ENV['SAML_IDP_SSO_TARGET_URL'] if ENV['SAML_IDP_SSO_TARGET_URL']
saml_options[:idp_sso_target_url_runtime_params] = ENV['SAML_IDP_SSO_TARGET_PARAMS'] if ENV['SAML_IDP_SSO_TARGET_PARAMS'] # FIXME: Should be parsable Hash saml_options[:idp_sso_target_url_runtime_params] = ENV['SAML_IDP_SSO_TARGET_PARAMS'] if ENV['SAML_IDP_SSO_TARGET_PARAMS'] # FIXME: Should be parsable Hash
saml_options[:idp_cert] = ENV['SAML_IDP_CERT'] if ENV['SAML_IDP_CERT'] saml_options[:idp_cert] = ENV['SAML_IDP_CERT'] if ENV['SAML_IDP_CERT']
saml_options[:idp_cert_fingerprint] = ENV['SAML_IDP_CERT_FINGERPRINT'] if ENV['SAML_IDP_CERT_FINGERPRINT'] saml_options[:idp_cert_fingerprint] = ENV['SAML_IDP_CERT_FINGERPRINT'] if ENV['SAML_IDP_CERT_FINGERPRINT']
@ -62,5 +62,4 @@ Devise.setup do |config|
saml_options[:uid_attribute] = ENV['SAML_UID_ATTRIBUTE'] if ENV['SAML_UID_ATTRIBUTE'] saml_options[:uid_attribute] = ENV['SAML_UID_ATTRIBUTE'] if ENV['SAML_UID_ATTRIBUTE']
config.omniauth :saml, saml_options config.omniauth :saml, saml_options
end end
end end

View File

@ -1,7 +1,7 @@
require 'open-uri' require 'open-uri'
module OpenURI module OpenURI
def OpenURI.redirectable?(uri1, uri2) # :nodoc: def self.redirectable?(uri1, uri2) # :nodoc:
uri1.scheme.downcase == uri2.scheme.downcase || uri1.scheme.downcase == uri2.scheme.downcase ||
(/\A(?:http|https|ftp)\z/i =~ uri1.scheme && /\A(?:http|https|ftp)\z/i =~ uri2.scheme) (/\A(?:http|https|ftp)\z/i =~ uri1.scheme && /\A(?:http|https|ftp)\z/i =~ uri2.scheme)
end end

View File

@ -42,7 +42,7 @@ class Rack::Attack
# (blocklist & throttles are skipped) # (blocklist & throttles are skipped)
Rack::Attack.safelist('allow from localhost') do |req| Rack::Attack.safelist('allow from localhost') do |req|
# Requests are allowed if the return value is truthy # Requests are allowed if the return value is truthy
'127.0.0.1' == req.ip || '::1' == req.ip req.ip == '127.0.0.1' || req.ip == '::1'
end end
throttle('throttle_authenticated_api', limit: 300, period: 5.minutes) do |req| throttle('throttle_authenticated_api', limit: 300, period: 5.minutes) do |req|

View File

@ -19,4 +19,4 @@ Sidekiq.configure_client do |config|
config.redis = redis_params config.redis = redis_params
end end
Sidekiq::Logging.logger.level = ::Logger::const_get(ENV.fetch('RAILS_LOG_LEVEL', 'info').upcase.to_s) Sidekiq::Logging.logger.level = ::Logger.const_get(ENV.fetch('RAILS_LOG_LEVEL', 'info').upcase.to_s)

View File

@ -1,6 +1,5 @@
module Twitter module Twitter
class Regex class Regex
REGEXEN[:valid_general_url_path_chars] = /[^\p{White_Space}\(\)\?]/iou REGEXEN[:valid_general_url_path_chars] = /[^\p{White_Space}\(\)\?]/iou
REGEXEN[:valid_url_path_ending_chars] = /[^\p{White_Space}\(\)\?!\*';:=\,\.\$%\[\]~&\|@]|(?:#{REGEXEN[:valid_url_balanced_parens]})/iou REGEXEN[:valid_url_path_ending_chars] = /[^\p{White_Space}\(\)\?!\*';:=\,\.\$%\[\]~&\|@]|(?:#{REGEXEN[:valid_url_balanced_parens]})/iou
REGEXEN[:valid_url_balanced_parens] = / REGEXEN[:valid_url_balanced_parens] = /

View File

@ -1,7 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
Rails.application.configure do Rails.application.configure do
# You can generate the keys using the following command (first is the private key, second is the public one) # You can generate the keys using the following command (first is the private key, second is the public one)
# You should only generate this once per instance. If you later decide to change it, all push subscription will # You should only generate this once per instance. If you later decide to change it, all push subscription will
# be invalidated, requiring the users to access the website again to resubscribe. # be invalidated, requiring the users to access the website again to resubscribe.

View File

@ -31,9 +31,9 @@ de:
privacy_policy: Datenschutzerklärung privacy_policy: Datenschutzerklärung
source_code: Quellcode source_code: Quellcode
status_count_after: status_count_after:
one: Status one: Statusmeldung
other: Status other: Statusmeldungen
status_count_before: die status_count_before: mit
terms: Nutzungsbedingungen terms: Nutzungsbedingungen
user_count_after: user_count_after:
one: Benutzer one: Benutzer

View File

@ -919,6 +919,7 @@ en:
tips: Tips tips: Tips
title: Welcome aboard, %{name}! title: Welcome aboard, %{name}!
users: users:
follow_limit_reached: You cannot follow more than %{limit} people
invalid_email: The e-mail address is invalid invalid_email: The e-mail address is invalid
invalid_otp_token: Invalid two-factor code invalid_otp_token: Invalid two-factor code
otp_lost_help_html: If you lost access to both, you may get in touch with %{email} otp_lost_help_html: If you lost access to both, you may get in touch with %{email}

View File

@ -1,7 +1,7 @@
threads_count = ENV.fetch('MAX_THREADS') { 5 }.to_i threads_count = ENV.fetch('MAX_THREADS') { 5 }.to_i
threads threads_count, threads_count threads threads_count, threads_count
if ENV['SOCKET'] then if ENV['SOCKET']
bind 'unix://' + ENV['SOCKET'] bind 'unix://' + ENV['SOCKET']
else else
port ENV.fetch('PORT') { 3000 } port ENV.fetch('PORT') { 3000 }

View File

@ -34,12 +34,12 @@ class CreateDoorkeeperTables < ActiveRecord::Migration[4.2]
# https://github.com/doorkeeper-gem/doorkeeper/tree/v3.0.0.rc1#custom-access-token-generator # https://github.com/doorkeeper-gem/doorkeeper/tree/v3.0.0.rc1#custom-access-token-generator
# #
# t.text :token, null: false # t.text :token, null: false
t.string :token, null: false t.string :token, null: false
t.string :refresh_token t.string :refresh_token
t.integer :expires_in t.integer :expires_in
t.datetime :revoked_at t.datetime :revoked_at
t.datetime :created_at, null: false t.datetime :created_at, null: false
t.string :scopes t.string :scopes
end end

View File

@ -4,4 +4,4 @@ class AddOwnerToApplication < ActiveRecord::Migration[4.2]
add_column :oauth_applications, :owner_type, :string, null: true add_column :oauth_applications, :owner_type, :string, null: true
add_index :oauth_applications, [:owner_id, :owner_type] add_index :oauth_applications, [:owner_id, :owner_type]
end end
end end

View File

@ -7,7 +7,7 @@ end
class RailsSettingsMigration < MIGRATION_BASE_CLASS class RailsSettingsMigration < MIGRATION_BASE_CLASS
def self.up def self.up
create_table :settings do |t| create_table :settings do |t|
t.string :var, :null => false t.string :var, :null => false
t.text :value t.text :value
t.references :target, :null => false, :polymorphic => true t.references :target, :null => false, :polymorphic => true
t.timestamps :null => true t.timestamps :null => true

View File

@ -8,7 +8,7 @@ class AddShortcodeToMediaAttachments < ActiveRecord::Migration[5.0]
end end
def down def down
remove_index :media_attachments, :shortcode remove_index :media_attachments, :shortcode
remove_column :media_attachments, :shortcode remove_column :media_attachments, :shortcode
end end
end end

View File

@ -1,5 +1,4 @@
class ChangeTagSearchIndexToBtree < ActiveRecord::Migration[5.1] class ChangeTagSearchIndexToBtree < ActiveRecord::Migration[5.1]
def up def up
remove_index :tags, name: :hashtag_search_index remove_index :tags, name: :hashtag_search_index
execute 'CREATE INDEX hashtag_search_index ON tags (name text_pattern_ops);' execute 'CREATE INDEX hashtag_search_index ON tags (name text_pattern_ops);'

View File

@ -28,7 +28,7 @@ class FixReblogsInFeeds < ActiveRecord::Migration[5.1]
-- So, first, we iterate over the user's feed to find any reblogs. -- So, first, we iterate over the user's feed to find any reblogs.
local items = redis.call('zrange', timeline_key, 0, -1, 'withscores') local items = redis.call('zrange', timeline_key, 0, -1, 'withscores')
for i = 1, #items, 2 do for i = 1, #items, 2 do
local reblogged_id = items[i] local reblogged_id = items[i]
local reblogging_id = items[i + 1] local reblogging_id = items[i + 1]

View File

@ -11,7 +11,7 @@ class AddReblogsToFollows < ActiveRecord::Migration[5.1]
add_column_with_default :follow_requests, :show_reblogs, :boolean, default: true, allow_null: false add_column_with_default :follow_requests, :show_reblogs, :boolean, default: true, allow_null: false
end end
end end
def down def down
remove_column :follows, :show_reblogs remove_column :follows, :show_reblogs
remove_column :follow_requests, :show_reblogs remove_column :follow_requests, :show_reblogs

View File

@ -11,7 +11,6 @@
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2018_08_20_232245) do ActiveRecord::Schema.define(version: 2018_08_20_232245) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"

View File

@ -5,6 +5,7 @@ require_relative 'mastodon/media_cli'
require_relative 'mastodon/emoji_cli' require_relative 'mastodon/emoji_cli'
require_relative 'mastodon/accounts_cli' require_relative 'mastodon/accounts_cli'
require_relative 'mastodon/feeds_cli' require_relative 'mastodon/feeds_cli'
require_relative 'mastodon/settings_cli'
module Mastodon module Mastodon
class CLI < Thor class CLI < Thor
@ -19,5 +20,8 @@ module Mastodon
desc 'feeds SUBCOMMAND ...ARGS', 'Manage feeds' desc 'feeds SUBCOMMAND ...ARGS', 'Manage feeds'
subcommand 'feeds', Mastodon::FeedsCLI subcommand 'feeds', Mastodon::FeedsCLI
desc 'settings SUBCOMMAND ...ARGS', 'Manage dynamic settings'
subcommand 'settings', Mastodon::SettingsCLI
end end
end end

View File

@ -0,0 +1,26 @@
# frozen_string_literal: true
require_relative '../../config/boot'
require_relative '../../config/environment'
require_relative 'cli_helper'
module Mastodon
class RegistrationsCLI < Thor
desc 'open', 'Open registrations'
def open
Setting.open_registrations = true
say('OK', :green)
end
desc 'close', 'Close registrations'
def close
Setting.open_registrations = false
say('OK', :green)
end
end
class SettingsCLI < Thor
desc 'registrations SUBCOMMAND ...ARGS', 'Manage state of registrations'
subcommand 'registrations', RegistrationsCLI
end
end

View File

@ -1,7 +1,5 @@
# frozen_string_literal: true # frozen_string_literal: true
require 'optparse'
require 'colorize'
require 'tty-command' require 'tty-command'
require 'tty-prompt' require 'tty-prompt'
@ -390,25 +388,6 @@ namespace :mastodon do
end end
end end
namespace :push do
desc 'Unsubscribes from PuSH updates of feeds nobody follows locally'
task clear: :environment do
Pubsubhubbub::UnsubscribeWorker.push_bulk(Account.remote.without_followers.where.not(subscription_expires_at: nil).pluck(:id))
end
end
namespace :settings do
desc 'Open registrations on this instance'
task open_registrations: :environment do
Setting.open_registrations = true
end
desc 'Close registrations on this instance'
task close_registrations: :environment do
Setting.open_registrations = false
end
end
namespace :webpush do namespace :webpush do
desc 'Generate VAPID key' desc 'Generate VAPID key'
task generate_vapid_key: :environment do task generate_vapid_key: :environment do
@ -427,7 +406,3 @@ def disable_log_stdout!
HttpLog.configuration.logger = dev_null HttpLog.configuration.logger = dev_null
Paperclip.options[:log] = false Paperclip.options[:log] = false
end end
def prepare_for_options!
2.times { ARGV.shift }
end

View File

@ -3,8 +3,8 @@ require 'rails_helper'
RSpec.describe AccountsController, type: :controller do RSpec.describe AccountsController, type: :controller do
render_views render_views
let(:alice) { Fabricate(:account, username: 'alice') } let(:alice) { Fabricate(:account, username: 'alice') }
let(:eve) { Fabricate(:user) } let(:eve) { Fabricate(:user) }
describe 'GET #show' do describe 'GET #show' do
let!(:status1) { Status.create!(account: alice, text: 'Hello world') } let!(:status1) { Status.create!(account: alice, text: 'Hello world') }

View File

@ -25,7 +25,7 @@ RSpec.describe Admin::AccountsController, type: :controller do
expect(h[:remote]).to eq '1' expect(h[:remote]).to eq '1'
expect(h[:by_domain]).to eq 'domain' expect(h[:by_domain]).to eq 'domain'
expect(h[:silenced]).to eq '1' expect(h[:silenced]).to eq '1'
expect(h[:recent]).to eq '1' expect(h[:alphabetic]).to eq '1'
expect(h[:suspended]).to eq '1' expect(h[:suspended]).to eq '1'
expect(h[:username]).to eq 'username' expect(h[:username]).to eq 'username'
expect(h[:display_name]).to eq 'display name' expect(h[:display_name]).to eq 'display name'
@ -40,7 +40,7 @@ RSpec.describe Admin::AccountsController, type: :controller do
remote: '1', remote: '1',
by_domain: 'domain', by_domain: 'domain',
silenced: '1', silenced: '1',
recent: '1', alphabetic: '1',
suspended: '1', suspended: '1',
username: 'username', username: 'username',
display_name: 'display name', display_name: 'display name',
@ -75,7 +75,6 @@ RSpec.describe Admin::AccountsController, type: :controller do
end end
end end
describe 'POST #subscribe' do describe 'POST #subscribe' do
subject { post :subscribe, params: { id: account.id } } subject { post :subscribe, params: { id: account.id } }

View File

@ -40,7 +40,7 @@ RSpec.describe Admin::EmailDomainBlocksController, type: :controller do
describe 'POST #create' do describe 'POST #create' do
it 'blocks the domain when succeeded to save' do it 'blocks the domain when succeeded to save' do
post :create, params: { email_domain_block: { domain: 'example.com'} } post :create, params: { email_domain_block: { domain: 'example.com' } }
expect(flash[:notice]).to eq I18n.t('admin.email_domain_blocks.created_msg') expect(flash[:notice]).to eq I18n.t('admin.email_domain_blocks.created_msg')
expect(response).to redirect_to(admin_email_domain_blocks_path) expect(response).to redirect_to(admin_email_domain_blocks_path)
@ -50,7 +50,7 @@ RSpec.describe Admin::EmailDomainBlocksController, type: :controller do
describe 'DELETE #destroy' do describe 'DELETE #destroy' do
it 'unblocks the domain' do it 'unblocks the domain' do
email_domain_block = Fabricate(:email_domain_block) email_domain_block = Fabricate(:email_domain_block)
delete :destroy, params: { id: email_domain_block.id } delete :destroy, params: { id: email_domain_block.id }
expect(flash[:notice]).to eq I18n.t('admin.email_domain_blocks.destroyed_msg') expect(flash[:notice]).to eq I18n.t('admin.email_domain_blocks.destroyed_msg')
expect(response).to redirect_to(admin_email_domain_blocks_path) expect(response).to redirect_to(admin_email_domain_blocks_path)

View File

@ -24,7 +24,7 @@ describe Admin::InvitesController do
subject { post :create, params: { invite: { max_uses: '10', expires_in: 1800 } } } subject { post :create, params: { invite: { max_uses: '10', expires_in: 1800 } } }
it 'succeeds to create a invite' do it 'succeeds to create a invite' do
expect{ subject }.to change { Invite.count }.by(1) expect { subject }.to change { Invite.count }.by(1)
expect(subject).to redirect_to admin_invites_path expect(subject).to redirect_to admin_invites_path
expect(Invite.last).to have_attributes(user_id: user.id, max_uses: 10) expect(Invite.last).to have_attributes(user_id: user.id, max_uses: 10)
end end

View File

@ -15,7 +15,6 @@ describe Admin::ReportNotesController do
let(:report) { Fabricate(:report, action_taken: action_taken, action_taken_by_account_id: account_id) } let(:report) { Fabricate(:report, action_taken: action_taken, action_taken_by_account_id: account_id) }
context 'when parameter is valid' do context 'when parameter is valid' do
context 'when report is unsolved' do context 'when report is unsolved' do
let(:action_taken) { false } let(:action_taken) { false }
let(:account_id) { nil } let(:account_id) { nil }
@ -24,7 +23,7 @@ describe Admin::ReportNotesController do
let(:params) { { report_note: { content: 'test content', report_id: report.id }, create_and_resolve: nil } } let(:params) { { report_note: { content: 'test content', report_id: report.id }, create_and_resolve: nil } }
it 'creates a report note and resolves report' do it 'creates a report note and resolves report' do
expect{ subject }.to change{ ReportNote.count }.by(1) expect { subject }.to change { ReportNote.count }.by(1)
expect(report.reload).to be_action_taken expect(report.reload).to be_action_taken
expect(subject).to redirect_to admin_reports_path expect(subject).to redirect_to admin_reports_path
end end
@ -34,7 +33,7 @@ describe Admin::ReportNotesController do
let(:params) { { report_note: { content: 'test content', report_id: report.id } } } let(:params) { { report_note: { content: 'test content', report_id: report.id } } }
it 'creates a report note and does not resolve report' do it 'creates a report note and does not resolve report' do
expect{ subject }.to change{ ReportNote.count }.by(1) expect { subject }.to change { ReportNote.count }.by(1)
expect(report.reload).not_to be_action_taken expect(report.reload).not_to be_action_taken
expect(subject).to redirect_to admin_report_path(report) expect(subject).to redirect_to admin_report_path(report)
end end
@ -49,7 +48,7 @@ describe Admin::ReportNotesController do
let(:params) { { report_note: { content: 'test content', report_id: report.id }, create_and_unresolve: nil } } let(:params) { { report_note: { content: 'test content', report_id: report.id }, create_and_unresolve: nil } }
it 'creates a report note and unresolves report' do it 'creates a report note and unresolves report' do
expect{ subject }.to change{ ReportNote.count }.by(1) expect { subject }.to change { ReportNote.count }.by(1)
expect(report.reload).not_to be_action_taken expect(report.reload).not_to be_action_taken
expect(subject).to redirect_to admin_report_path(report) expect(subject).to redirect_to admin_report_path(report)
end end
@ -59,7 +58,7 @@ describe Admin::ReportNotesController do
let(:params) { { report_note: { content: 'test content', report_id: report.id } } } let(:params) { { report_note: { content: 'test content', report_id: report.id } } }
it 'creates a report note and does not unresolve report' do it 'creates a report note and does not unresolve report' do
expect{ subject }.to change{ ReportNote.count }.by(1) expect { subject }.to change { ReportNote.count }.by(1)
expect(report.reload).to be_action_taken expect(report.reload).to be_action_taken
expect(subject).to redirect_to admin_report_path(report) expect(subject).to redirect_to admin_report_path(report)
end end
@ -84,7 +83,7 @@ describe Admin::ReportNotesController do
let!(:report_note) { Fabricate(:report_note) } let!(:report_note) { Fabricate(:report_note) }
it 'deletes note' do it 'deletes note' do
expect{ subject }.to change{ ReportNote.count }.by(-1) expect { subject }.to change { ReportNote.count }.by(-1)
expect(subject).to redirect_to admin_report_path(report_note.report) expect(subject).to redirect_to admin_report_path(report_note.report)
end end
end end

View File

@ -13,7 +13,7 @@ describe Admin::ReportedStatusesController do
describe 'POST #create' do describe 'POST #create' do
subject do subject do
-> { post :create, params: { :report_id => report, action => '', :form_status_batch => { status_ids: status_ids } } } -> { post :create, params: { :report_id => report, action => '', :form_status_batch => { status_ids: status_ids } } }
end end
let(:action) { 'nsfw_on' } let(:action) { 'nsfw_on' }

View File

@ -24,7 +24,7 @@ describe Admin::StatusesController do
end end
it 'returns http success with media' do it 'returns http success with media' do
get :index, params: { account_id: account.id , media: true } get :index, params: { account_id: account.id, media: true }
statuses = assigns(:statuses).to_a statuses = assigns(:statuses).to_a
expect(statuses.size).to eq 1 expect(statuses.size).to eq 1

View File

@ -154,7 +154,7 @@ RSpec.describe Api::V1::AccountsController, type: :controller do
before do before do
user.account.follow!(other_account) user.account.follow!(other_account)
post :mute, params: {id: other_account.id } post :mute, params: { id: other_account.id }
end end
it 'returns http success' do it 'returns http success' do
@ -182,7 +182,7 @@ RSpec.describe Api::V1::AccountsController, type: :controller do
before do before do
user.account.follow!(other_account) user.account.follow!(other_account)
post :mute, params: {id: other_account.id, notifications: false } post :mute, params: { id: other_account.id, notifications: false }
end end
it 'returns http success' do it 'returns http success' do

View File

@ -25,7 +25,6 @@ RSpec.describe Api::V1::Statuses::FavouritedByAccountsController, type: :control
expect(response.headers['Link'].links.size).to eq(2) expect(response.headers['Link'].links.size).to eq(2)
end end
end end
end end
context 'without an oauth token' do context 'without an oauth token' do

View File

@ -31,7 +31,7 @@ describe Api::V1::StreamingController do
describe 'GET #index' do describe 'GET #index' do
it 'redirects to streaming host' do it 'redirects to streaming host' do
get :index, params: {access_token: 'deadbeef', stream: 'public'} get :index, params: { access_token: 'deadbeef', stream: 'public' }
expect(response).to have_http_status(301) expect(response).to have_http_status(301)
request_uri = URI.parse(request.url) request_uri = URI.parse(request.url)
redirect_to_uri = URI.parse(response.location) redirect_to_uri = URI.parse(response.location)
@ -42,5 +42,4 @@ describe Api::V1::StreamingController do
end end
end end
end end
end end

View File

@ -5,7 +5,7 @@ require 'rails_helper'
describe Api::V1::Timelines::HomeController do describe Api::V1::Timelines::HomeController do
render_views render_views
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice'), current_sign_in_at: 1.day.ago) } let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice'), current_sign_in_at: 1.day.ago) }
before do before do
allow(controller).to receive(:doorkeeper_token) { token } allow(controller).to receive(:doorkeeper_token) { token }

View File

@ -5,7 +5,7 @@ require 'rails_helper'
describe Api::V1::Timelines::PublicController do describe Api::V1::Timelines::PublicController do
render_views render_views
let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) } let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
before do before do
allow(controller).to receive(:doorkeeper_token) { token } allow(controller).to receive(:doorkeeper_token) { token }

View File

@ -14,7 +14,7 @@ describe Api::Web::EmbedsController do
context 'when successfully finds status' do context 'when successfully finds status' do
let(:status) { Fabricate(:status) } let(:status) { Fabricate(:status) }
let(:url) { "http://#{ Rails.configuration.x.web_domain }/@#{status.account.username}/#{status.id}" } let(:url) { "http://#{Rails.configuration.x.web_domain}/@#{status.account.username}/#{status.id}" }
it 'returns a right response' do it 'returns a right response' do
expect(response).to have_http_status :ok expect(response).to have_http_status :ok

View File

@ -201,7 +201,7 @@ describe ApplicationController, type: :controller do
describe 'raise_not_found' do describe 'raise_not_found' do
it 'raises error' do it 'raises error' do
controller.params[:unmatched_route] = 'unmatched' controller.params[:unmatched_route] = 'unmatched'
expect{ controller.raise_not_found }.to raise_error(ActionController::RoutingError, 'No route matches unmatched') expect { controller.raise_not_found }.to raise_error(ActionController::RoutingError, 'No route matches unmatched')
end end
end end

View File

@ -67,7 +67,7 @@ describe Auth::ConfirmationsController, type: :controller do
end end
describe 'PATCH #finish_signup' do describe 'PATCH #finish_signup' do
subject { patch :finish_signup, params: { user: { email: email }} } subject { patch :finish_signup, params: { user: { email: email } } }
let(:user) { Fabricate(:user) } let(:user) { Fabricate(:user) }
before do before do

View File

@ -8,6 +8,7 @@ describe ApplicationController, type: :controller do
def index def index
send_export_file send_export_file
end end
def export_data def export_data
@export.account.username @export.account.username
end end

View File

@ -43,7 +43,7 @@ describe InvitesController do
let(:user) { Fabricate(:user, moderator: false, admin: true) } let(:user) { Fabricate(:user, moderator: false, admin: true) }
it 'succeeds to create a invite' do it 'succeeds to create a invite' do
expect{ subject }.to change { Invite.count }.by(1) expect { subject }.to change { Invite.count }.by(1)
expect(subject).to redirect_to invites_path expect(subject).to redirect_to invites_path
expect(Invite.last).to have_attributes(user_id: user.id, max_uses: 10) expect(Invite.last).to have_attributes(user_id: user.id, max_uses: 10)
end end

View File

@ -14,11 +14,11 @@ describe RemoteUnfollowsController do
before do before do
sign_in current_user sign_in current_user
current_account.follow!(remote_account) current_account.follow!(remote_account)
stub_request(:post, 'http://example.com/inbox'){ { status: 200 } } stub_request(:post, 'http://example.com/inbox') { { status: 200 } }
end end
context 'when successfully unfollow remote account' do context 'when successfully unfollow remote account' do
let(:acct) {"acct:#{ remote_account.username }@#{ remote_account.domain }"} let(:acct) { "acct:#{remote_account.username}@#{remote_account.domain}" }
it do it do
is_expected.to render_template :success is_expected.to render_template :success
@ -27,7 +27,7 @@ describe RemoteUnfollowsController do
end end
context 'when fails to unfollow remote account' do context 'when fails to unfollow remote account' do
let(:acct) {"acct:#{ remote_account.username + '_test' }@#{ remote_account.domain }"} let(:acct) { "acct:#{remote_account.username + '_test'}@#{remote_account.domain}" }
it do it do
is_expected.to render_template :error is_expected.to render_template :error

View File

@ -21,7 +21,6 @@ describe Settings::ApplicationsController do
end end
end end
describe 'GET #show' do describe 'GET #show' do
it 'returns http success' do it 'returns http success' do
get :show, params: { id: app.id } get :show, params: { id: app.id }
@ -48,13 +47,13 @@ describe Settings::ApplicationsController do
context 'success (passed scopes as a String)' do context 'success (passed scopes as a String)' do
def call_create def call_create
post :create, params: { post :create, params: {
doorkeeper_application: { doorkeeper_application: {
name: 'My New App', name: 'My New App',
redirect_uri: 'urn:ietf:wg:oauth:2.0:oob', redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
website: 'http://google.com', website: 'http://google.com',
scopes: 'read write follow' scopes: 'read write follow'
} }
} }
response response
end end
@ -70,13 +69,13 @@ describe Settings::ApplicationsController do
context 'success (passed scopes as an Array)' do context 'success (passed scopes as an Array)' do
def call_create def call_create
post :create, params: { post :create, params: {
doorkeeper_application: { doorkeeper_application: {
name: 'My New App', name: 'My New App',
redirect_uri: 'urn:ietf:wg:oauth:2.0:oob', redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
website: 'http://google.com', website: 'http://google.com',
scopes: [ 'read', 'write', 'follow' ] scopes: [ 'read', 'write', 'follow' ]
} }
} }
response response
end end
@ -92,13 +91,13 @@ describe Settings::ApplicationsController do
context 'failure' do context 'failure' do
before do before do
post :create, params: { post :create, params: {
doorkeeper_application: { doorkeeper_application: {
name: '', name: '',
redirect_uri: '', redirect_uri: '',
website: '', website: '',
scopes: [] scopes: []
} }
} }
end end
it 'returns http success' do it 'returns http success' do
@ -121,9 +120,9 @@ describe Settings::ApplicationsController do
def call_update def call_update
patch :update, params: { patch :update, params: {
id: app.id, id: app.id,
doorkeeper_application: opts doorkeeper_application: opts
} }
response response
end end
@ -140,14 +139,14 @@ describe Settings::ApplicationsController do
context 'failure' do context 'failure' do
before do before do
patch :update, params: { patch :update, params: {
id: app.id, id: app.id,
doorkeeper_application: { doorkeeper_application: {
name: '', name: '',
redirect_uri: '', redirect_uri: '',
website: '', website: '',
scopes: [] scopes: []
} }
} }
end end
it 'returns http success' do it 'returns http success' do

View File

@ -10,7 +10,6 @@ describe Settings::MigrationsController do
end end
describe 'GET #show' do describe 'GET #show' do
context 'when user is not sign in' do context 'when user is not sign in' do
subject { get :show } subject { get :show }
@ -45,7 +44,6 @@ describe Settings::MigrationsController do
end end
describe 'PUT #update' do describe 'PUT #update' do
context 'when user is not sign in' do context 'when user is not sign in' do
subject { put :update } subject { put :update }

View File

@ -50,7 +50,7 @@ describe Settings::TwoFactorAuthentication::ConfirmationsController do
describe 'when form_two_factor_confirmation parameter is not provided' do describe 'when form_two_factor_confirmation parameter is not provided' do
it 'raises ActionController::ParameterMissing' do it 'raises ActionController::ParameterMissing' do
expect { post :create, params: { } }.to raise_error(ActionController::ParameterMissing) expect { post :create, params: {} }.to raise_error(ActionController::ParameterMissing)
end end
end end

View File

@ -6,5 +6,5 @@ Fabricator(:account) do
username { sequence(:username) { |i| "#{Faker::Internet.user_name(nil, %w(_))}#{i}" } } username { sequence(:username) { |i| "#{Faker::Internet.user_name(nil, %w(_))}#{i}" } }
last_webfingered_at { Time.now.utc } last_webfingered_at { Time.now.utc }
public_key { public_key } public_key { public_key }
private_key { private_key} private_key { private_key }
end end

View File

@ -1,4 +1,4 @@
Fabricator(:list) do Fabricator(:list) do
account account
title "MyString" title "MyString"
end end

View File

@ -1,4 +1,4 @@
Fabricator(:relay) do Fabricator(:relay) do
inbox_url "https://example.com/inbox" inbox_url "https://example.com/inbox"
state :idle state :idle
end end

View File

@ -1,3 +1,2 @@
Fabricator(:site_upload) do Fabricator(:site_upload) do
end end

View File

@ -400,7 +400,7 @@ RSpec.describe FeedManager do
end end
it 'sends push updates' do it 'sends push updates' do
status = Fabricate(:status) status = Fabricate(:status)
FeedManager.instance.push_to_home(receiver, status) FeedManager.instance.push_to_home(receiver, status)

View File

@ -170,12 +170,11 @@ RSpec.describe Formatter do
end end
end end
describe '#format_spoiler' do describe '#format_spoiler' do
subject { Formatter.instance.format_spoiler(status) } subject { Formatter.instance.format_spoiler(status) }
context 'given a post containing plain text' do context 'given a post containing plain text' do
let(:status) { Fabricate(:status, text: 'text', spoiler_text: 'Secret!', uri: nil) } let(:status) { Fabricate(:status, text: 'text', spoiler_text: 'Secret!', uri: nil) }
it 'Returns the spoiler text' do it 'Returns the spoiler text' do
is_expected.to eq 'Secret!' is_expected.to eq 'Secret!'
@ -184,7 +183,7 @@ RSpec.describe Formatter do
context 'given a post with an emoji shortcode at the start' do context 'given a post with an emoji shortcode at the start' do
let!(:emoji) { Fabricate(:custom_emoji) } let!(:emoji) { Fabricate(:custom_emoji) }
let(:status) { Fabricate(:status, text: 'text', spoiler_text: ':coolcat: Secret!', uri: nil) } let(:status) { Fabricate(:status, text: 'text', spoiler_text: ':coolcat: Secret!', uri: nil) }
let(:text) { ':coolcat: Beep boop' } let(:text) { ':coolcat: Beep boop' }
it 'converts the shortcode to an image tag' do it 'converts the shortcode to an image tag' do
@ -207,7 +206,7 @@ RSpec.describe Formatter do
end end
context 'given a post containing plain text' do context 'given a post containing plain text' do
let(:status) { Fabricate(:status, text: 'text', uri: nil) } let(:status) { Fabricate(:status, text: 'text', uri: nil) }
it 'paragraphizes the text' do it 'paragraphizes the text' do
is_expected.to eq '<p>text</p>' is_expected.to eq '<p>text</p>'
@ -215,7 +214,7 @@ RSpec.describe Formatter do
end end
context 'given a post containing line feeds' do context 'given a post containing line feeds' do
let(:status) { Fabricate(:status, text: "line\nfeed", uri: nil) } let(:status) { Fabricate(:status, text: "line\nfeed", uri: nil) }
it 'removes line feeds' do it 'removes line feeds' do
is_expected.not_to include "\n" is_expected.not_to include "\n"
@ -367,7 +366,7 @@ RSpec.describe Formatter do
subject { Formatter.instance.plaintext(status) } subject { Formatter.instance.plaintext(status) }
context 'given a post with local status' do context 'given a post with local status' do
let(:status) { Fabricate(:status, text: '<p>a text by a nerd who uses an HTML tag in text</p>', uri: nil) } let(:status) { Fabricate(:status, text: '<p>a text by a nerd who uses an HTML tag in text</p>', uri: nil) }
it 'returns the raw text' do it 'returns the raw text' do
is_expected.to eq '<p>a text by a nerd who uses an HTML tag in text</p>' is_expected.to eq '<p>a text by a nerd who uses an HTML tag in text</p>'
@ -375,7 +374,7 @@ RSpec.describe Formatter do
end end
context 'given a post with remote status' do context 'given a post with remote status' do
let(:status) { Fabricate(:status, account: remote_account, text: '<script>alert("Hello")</script>') } let(:status) { Fabricate(:status, account: remote_account, text: '<script>alert("Hello")</script>') }
it 'returns tag-stripped text' do it 'returns tag-stripped text' do
is_expected.to eq '' is_expected.to eq ''

View File

@ -90,7 +90,7 @@ describe LanguageDetector do
end end
it 'uses nil when account is present but has no locale' do it 'uses nil when account is present but has no locale' do
result = described_class.instance.detect('', account_without_user_locale) result = described_class.instance.detect('', account_without_user_locale)
expect(result).to eq nil expect(result).to eq nil
end end

View File

@ -880,7 +880,7 @@ RSpec.describe OStatus::AtomSerializer do
ProcessInteractionService.new.call(envelope, block.target_account) ProcessInteractionService.new.call(envelope, block.target_account)
expect{ block.reload }.to raise_error ActiveRecord::RecordNotFound expect { block.reload }.to raise_error ActiveRecord::RecordNotFound
end end
end end

View File

@ -84,7 +84,7 @@ describe Request do
allow(Addrinfo).to receive(:foreach).with('example.com', nil, nil, :SOCK_STREAM) allow(Addrinfo).to receive(:foreach).with('example.com', nil, nil, :SOCK_STREAM)
.and_yield(Addrinfo.new(["AF_INET", 0, "example.com", "0.0.0.0"], :PF_INET, :SOCK_STREAM)) .and_yield(Addrinfo.new(["AF_INET", 0, "example.com", "0.0.0.0"], :PF_INET, :SOCK_STREAM))
.and_yield(Addrinfo.new(["AF_INET6", 0, "example.com", "2001:db8::face"], :PF_INET6, :SOCK_STREAM)) .and_yield(Addrinfo.new(["AF_INET6", 0, "example.com", "2001:db8::face"], :PF_INET6, :SOCK_STREAM))
expect{ subject.perform }.to raise_error Mastodon::ValidationError expect { subject.perform }.to raise_error Mastodon::ValidationError
end end
end end
end end

View File

@ -2,10 +2,10 @@ require 'rails_helper'
describe AccountFilter do describe AccountFilter do
describe 'with empty params' do describe 'with empty params' do
it 'defaults to alphabetic account list' do it 'defaults to recent account list' do
filter = described_class.new({}) filter = described_class.new({})
expect(filter.results).to eq Account.alphabetic expect(filter.results).to eq Account.recent
end end
end end
@ -60,7 +60,7 @@ describe AccountFilter do
end end
describe 'that call account methods' do describe 'that call account methods' do
%i(local remote silenced recent suspended).each do |option| %i(local remote silenced alphabetic suspended).each do |option|
it "delegates the #{option} option" do it "delegates the #{option} option" do
allow(Account).to receive(option).and_return(Account.none) allow(Account).to receive(option).and_return(Account.none)
filter = described_class.new({ option => true }) filter = described_class.new({ option => true })

View File

@ -1,5 +1,4 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe AccountModerationNote, type: :model do RSpec.describe AccountModerationNote, type: :model do
end end

View File

@ -275,7 +275,7 @@ RSpec.describe Account, type: :model do
subject { Fabricate(:account) } subject { Fabricate(:account) }
context 'when the status is a reblog of another status'do context 'when the status is a reblog of another status' do
let(:original_reblog) do let(:original_reblog) do
author = Fabricate(:account, username: 'original_reblogger') author = Fabricate(:account, username: 'original_reblogger')
Fabricate(:status, reblog: original_status, account: author) Fabricate(:status, reblog: original_status, account: author)

View File

@ -1,5 +1,4 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe Admin::ActionLog, type: :model do RSpec.describe Admin::ActionLog, type: :model do
end end

View File

@ -1,5 +1,4 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe Backup, type: :model do RSpec.describe Backup, type: :model do
end end

View File

@ -1,5 +1,4 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe ConversationMute, type: :model do RSpec.describe ConversationMute, type: :model do
end end

View File

@ -4,7 +4,7 @@ RSpec.describe CustomEmoji, type: :model do
describe '#search' do describe '#search' do
let(:custom_emoji) { Fabricate(:custom_emoji, shortcode: shortcode) } let(:custom_emoji) { Fabricate(:custom_emoji, shortcode: shortcode) }
subject { described_class.search(search_term) } subject { described_class.search(search_term) }
context 'shortcode is exact' do context 'shortcode is exact' do
let(:shortcode) { 'blobpats' } let(:shortcode) { 'blobpats' }

View File

@ -1,5 +1,4 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe CustomFilter, type: :model do RSpec.describe CustomFilter, type: :model do
end end

View File

@ -23,6 +23,20 @@ RSpec.describe Follow, type: :model do
follow.valid? follow.valid?
expect(follow).to model_have_error_on_field(:target_account) expect(follow).to model_have_error_on_field(:target_account)
end end
it 'is invalid if account already follows too many people' do
alice.update(following_count: FollowLimitValidator::LIMIT)
expect(subject).to_not be_valid
expect(subject).to model_have_error_on_field(:base)
end
it 'is valid if account is only on the brink of following too many people' do
alice.update(following_count: FollowLimitValidator::LIMIT - 1)
expect(subject).to be_valid
expect(subject).to_not model_have_error_on_field(:base)
end
end end
describe 'recent' do describe 'recent' do

View File

@ -1,5 +1,4 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe ListAccount, type: :model do RSpec.describe ListAccount, type: :model do
end end

View File

@ -1,5 +1,4 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe List, type: :model do RSpec.describe List, type: :model do
end end

View File

@ -131,7 +131,7 @@ RSpec.describe MediaAttachment, type: :model do
expect(media.file.meta["original"]["aspect"]).to eq 1.5 expect(media.file.meta["original"]["aspect"]).to eq 1.5
expect(media.file.meta["small"]["width"]).to eq 490 expect(media.file.meta["small"]["width"]).to eq 490
expect(media.file.meta["small"]["height"]).to eq 327 expect(media.file.meta["small"]["height"]).to eq 327
expect(media.file.meta["small"]["aspect"]).to eq 490.0/327 expect(media.file.meta["small"]["aspect"]).to eq 490.0 / 327
end end
end end

View File

@ -1,5 +1,4 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe Mute, type: :model do RSpec.describe Mute, type: :model do
end end

View File

@ -1,5 +1,4 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe PreviewCard, type: :model do RSpec.describe PreviewCard, type: :model do
end end

View File

@ -34,7 +34,7 @@ RSpec.describe RemoteFollow do
subject { remote_follow.valid? } subject { remote_follow.valid? }
context 'attrs with acct' do context 'attrs with acct' do
let(:attrs) { { acct: 'gargron@quitter.no' }} let(:attrs) { { acct: 'gargron@quitter.no' } }
it do it do
is_expected.to be true is_expected.to be true
@ -42,7 +42,7 @@ RSpec.describe RemoteFollow do
end end
context 'attrs without acct' do context 'attrs without acct' do
let(:attrs) { { } } let(:attrs) { {} }
it do it do
is_expected.to be false is_expected.to be false

View File

@ -254,7 +254,7 @@ RSpec.describe User, type: :model do
it_behaves_like 'Settings-extended' do it_behaves_like 'Settings-extended' do
def create! def create!
User.create!(account: Fabricate(:account), email: 'foo@mastodon.space', password: 'abcd1234' ) User.create!(account: Fabricate(:account), email: 'foo@mastodon.space', password: 'abcd1234')
end end
def fabricate def fabricate

View File

@ -1,5 +1,4 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe Web::Setting, type: :model do RSpec.describe Web::Setting, type: :model do
end end

View File

@ -34,7 +34,7 @@ RSpec.describe ActivityPub::ProcessCollectionService, type: :service do
end end
it 'processes payload with actor if valid signature exists' do it 'processes payload with actor if valid signature exists' do
payload['signature'] = {'type' => 'RsaSignature2017'} payload['signature'] = { 'type' => 'RsaSignature2017' }
expect_any_instance_of(ActivityPub::LinkedDataSignature).to receive(:verify_account!).and_return(actor) expect_any_instance_of(ActivityPub::LinkedDataSignature).to receive(:verify_account!).and_return(actor)
expect(ActivityPub::Activity).to receive(:factory).with(instance_of(Hash), actor, instance_of(Hash)) expect(ActivityPub::Activity).to receive(:factory).with(instance_of(Hash), actor, instance_of(Hash))
@ -43,7 +43,7 @@ RSpec.describe ActivityPub::ProcessCollectionService, type: :service do
end end
it 'does not process payload if invalid signature exists' do it 'does not process payload if invalid signature exists' do
payload['signature'] = {'type' => 'RsaSignature2017'} payload['signature'] = { 'type' => 'RsaSignature2017' }
expect_any_instance_of(ActivityPub::LinkedDataSignature).to receive(:verify_account!).and_return(nil) expect_any_instance_of(ActivityPub::LinkedDataSignature).to receive(:verify_account!).and_return(nil)
expect(ActivityPub::Activity).not_to receive(:factory) expect(ActivityPub::Activity).not_to receive(:factory)

View File

@ -57,7 +57,7 @@ RSpec.describe FetchAtomService, type: :service do
context 'content type is application/atom+xml' do context 'content type is application/atom+xml' do
let(:content_type) { 'application/atom+xml' } let(:content_type) { 'application/atom+xml' }
it { is_expected.to eq [url, {:prefetched_body=>""}, :ostatus] } it { is_expected.to eq [url, { :prefetched_body => "" }, :ostatus] }
end end
context 'content_type is json' do context 'content_type is json' do

View File

@ -3,80 +3,107 @@ require 'rails_helper'
RSpec.describe VerifyLinkService, type: :service do RSpec.describe VerifyLinkService, type: :service do
subject { described_class.new } subject { described_class.new }
let(:account) { Fabricate(:account, username: 'alice') } context 'given a local account' do
let(:field) { Account::Field.new(account, 'name' => 'Website', 'value' => 'http://example.com') } let(:account) { Fabricate(:account, username: 'alice') }
let(:field) { Account::Field.new(account, 'name' => 'Website', 'value' => 'http://example.com') }
before do before do
stub_request(:head, 'https://redirect.me/abc').to_return(status: 301, headers: { 'Location' => ActivityPub::TagManager.instance.url_for(account) }) stub_request(:head, 'https://redirect.me/abc').to_return(status: 301, headers: { 'Location' => ActivityPub::TagManager.instance.url_for(account) })
stub_request(:get, 'http://example.com').to_return(status: 200, body: html) stub_request(:get, 'http://example.com').to_return(status: 200, body: html)
subject.call(field) subject.call(field)
end
context 'when a link contains an <a> back' do
let(:html) do
<<-HTML
<!doctype html>
<body>
<a href="#{ActivityPub::TagManager.instance.url_for(account)}" rel="me">Follow me on Mastodon</a>
</body>
HTML
end end
it 'marks the field as verified' do context 'when a link contains an <a> back' do
expect(field.verified?).to be true let(:html) do
<<-HTML
<!doctype html>
<body>
<a href="#{ActivityPub::TagManager.instance.url_for(account)}" rel="me">Follow me on Mastodon</a>
</body>
HTML
end
it 'marks the field as verified' do
expect(field.verified?).to be true
end
end
context 'when a link contains an <a rel="noopener"> back' do
let(:html) do
<<-HTML
<!doctype html>
<body>
<a href="#{ActivityPub::TagManager.instance.url_for(account)}" rel="noopener me" target="_blank">Follow me on Mastodon</a>
</body>
HTML
end
it 'marks the field as verified' do
expect(field.verified?).to be true
end
end
context 'when a link contains a <link> back' do
let(:html) do
<<-HTML
<!doctype html>
<head>
<link type="text/html" href="#{ActivityPub::TagManager.instance.url_for(account)}" rel="me" />
</head>
HTML
end
it 'marks the field as verified' do
expect(field.verified?).to be true
end
end
context 'when a link goes through a redirect back' do
let(:html) do
<<-HTML
<!doctype html>
<head>
<link type="text/html" href="https://redirect.me/abc" rel="me" />
</head>
HTML
end
it 'marks the field as verified' do
expect(field.verified?).to be true
end
end
context 'when a link does not contain a link back' do
let(:html) { '' }
it 'marks the field as verified' do
expect(field.verified?).to be false
end
end end
end end
context 'when a link contains an <a rel="noopener"> back' do context 'given a remote account' do
let(:html) do let(:account) { Fabricate(:account, username: 'alice', domain: 'example.com', url: 'https://profile.example.com/alice') }
<<-HTML let(:field) { Account::Field.new(account, 'name' => 'Website', 'value' => '<a href="http://example.com" rel="me"><span class="invisible">http://</span><span class="">example.com</span><span class="invisible"></span></a>') }
<!doctype html>
<body> before do
<a href="#{ActivityPub::TagManager.instance.url_for(account)}" rel="noopener me" target="_blank">Follow me on Mastodon</a> stub_request(:get, 'http://example.com').to_return(status: 200, body: html)
</body> subject.call(field)
HTML
end end
it 'marks the field as verified' do context 'when a link contains an <a> back' do
expect(field.verified?).to be true let(:html) do
end <<-HTML
end <!doctype html>
<body>
<a href="https://profile.example.com/alice" rel="me">Follow me on Mastodon</a>
</body>
HTML
end
context 'when a link contains a <link> back' do it 'marks the field as verified' do
let(:html) do expect(field.verified?).to be true
<<-HTML end
<!doctype html>
<head>
<link type="text/html" href="#{ActivityPub::TagManager.instance.url_for(account)}" rel="me" />
</head>
HTML
end
it 'marks the field as verified' do
expect(field.verified?).to be true
end
end
context 'when a link goes through a redirect back' do
let(:html) do
<<-HTML
<!doctype html>
<head>
<link type="text/html" href="https://redirect.me/abc" rel="me" />
</head>
HTML
end
it 'marks the field as verified' do
expect(field.verified?).to be true
end
end
context 'when a link does not contain a link back' do
let(:html) { '' }
it 'marks the field as verified' do
expect(field.verified?).to be false
end end
end end
end end

View File

@ -49,8 +49,8 @@ describe 'stream_entries/show.html.haml', without_verify_partial_doubles: true d
assign(:stream_entry, reply.stream_entry) assign(:stream_entry, reply.stream_entry)
assign(:account, alice) assign(:account, alice)
assign(:type, reply.stream_entry.activity_type.downcase) assign(:type, reply.stream_entry.activity_type.downcase)
assign(:ancestors, reply.stream_entry.activity.ancestors(1, bob) ) assign(:ancestors, reply.stream_entry.activity.ancestors(1, bob))
assign(:descendant_threads, [{ statuses: reply.stream_entry.activity.descendants(1)}]) assign(:descendant_threads, [{ statuses: reply.stream_entry.activity.descendants(1) }])
render render