Merge commit '4a22e72b9b1b8f14792efcc649b0db8bc27f0df2' into glitch-soc/merge-upstream
commit
2e02d03524
|
@ -23,9 +23,17 @@ jobs:
|
||||||
needs: pre_job
|
needs: pre_job
|
||||||
if: needs.pre_job.outputs.should_skip != 'true'
|
if: needs.pre_job.outputs.should_skip != 'true'
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
postgres:
|
||||||
|
- 14-alpine
|
||||||
|
- 15-alpine
|
||||||
|
|
||||||
services:
|
services:
|
||||||
postgres:
|
postgres:
|
||||||
image: postgres:14-alpine
|
image: postgres:${{ matrix.postgres}}
|
||||||
env:
|
env:
|
||||||
POSTGRES_PASSWORD: postgres
|
POSTGRES_PASSWORD: postgres
|
||||||
POSTGRES_USER: postgres
|
POSTGRES_USER: postgres
|
||||||
|
|
|
@ -23,9 +23,17 @@ jobs:
|
||||||
needs: pre_job
|
needs: pre_job
|
||||||
if: needs.pre_job.outputs.should_skip != 'true'
|
if: needs.pre_job.outputs.should_skip != 'true'
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
postgres:
|
||||||
|
- 14-alpine
|
||||||
|
- 15-alpine
|
||||||
|
|
||||||
services:
|
services:
|
||||||
postgres:
|
postgres:
|
||||||
image: postgres:14-alpine
|
image: postgres:${{ matrix.postgres}}
|
||||||
env:
|
env:
|
||||||
POSTGRES_PASSWORD: postgres
|
POSTGRES_PASSWORD: postgres
|
||||||
POSTGRES_USER: postgres
|
POSTGRES_USER: postgres
|
||||||
|
|
|
@ -21,12 +21,6 @@ Layout/ArgumentAlignment:
|
||||||
- 'config/initializers/cors.rb'
|
- 'config/initializers/cors.rb'
|
||||||
- 'config/initializers/session_store.rb'
|
- 'config/initializers/session_store.rb'
|
||||||
|
|
||||||
# This cop supports safe autocorrection (--autocorrect).
|
|
||||||
# Configuration parameters: AllowForAlignment, AllowBeforeTrailingComments, ForceEqualSignAlignment.
|
|
||||||
Layout/ExtraSpacing:
|
|
||||||
Exclude:
|
|
||||||
- 'config/initializers/omniauth.rb'
|
|
||||||
|
|
||||||
# This cop supports safe autocorrection (--autocorrect).
|
# This cop supports safe autocorrection (--autocorrect).
|
||||||
# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
|
# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
|
||||||
# SupportedHashRocketStyles: key, separator, table
|
# SupportedHashRocketStyles: key, separator, table
|
||||||
|
@ -39,12 +33,6 @@ Layout/HashAlignment:
|
||||||
- 'config/initializers/rack_attack.rb'
|
- 'config/initializers/rack_attack.rb'
|
||||||
- 'config/routes.rb'
|
- 'config/routes.rb'
|
||||||
|
|
||||||
# This cop supports safe autocorrection (--autocorrect).
|
|
||||||
# Configuration parameters: Width, AllowedPatterns.
|
|
||||||
Layout/IndentationWidth:
|
|
||||||
Exclude:
|
|
||||||
- 'config/initializers/ffmpeg.rb'
|
|
||||||
|
|
||||||
# This cop supports safe autocorrection (--autocorrect).
|
# This cop supports safe autocorrection (--autocorrect).
|
||||||
# Configuration parameters: AllowDoxygenCommentStyle, AllowGemfileRubyComment.
|
# Configuration parameters: AllowDoxygenCommentStyle, AllowGemfileRubyComment.
|
||||||
Layout/LeadingCommentSpace:
|
Layout/LeadingCommentSpace:
|
||||||
|
@ -52,14 +40,6 @@ Layout/LeadingCommentSpace:
|
||||||
- 'config/application.rb'
|
- 'config/application.rb'
|
||||||
- 'config/initializers/omniauth.rb'
|
- 'config/initializers/omniauth.rb'
|
||||||
|
|
||||||
# This cop supports safe autocorrection (--autocorrect).
|
|
||||||
# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces.
|
|
||||||
# SupportedStyles: space, no_space
|
|
||||||
# SupportedStylesForEmptyBraces: space, no_space
|
|
||||||
Layout/SpaceBeforeBlockBraces:
|
|
||||||
Exclude:
|
|
||||||
- 'config/initializers/paperclip.rb'
|
|
||||||
|
|
||||||
# This cop supports safe autocorrection (--autocorrect).
|
# This cop supports safe autocorrection (--autocorrect).
|
||||||
# Configuration parameters: EnforcedStyle.
|
# Configuration parameters: EnforcedStyle.
|
||||||
# SupportedStyles: require_no_space, require_space
|
# SupportedStyles: require_no_space, require_space
|
||||||
|
@ -68,19 +48,6 @@ Layout/SpaceInLambdaLiteral:
|
||||||
- 'config/environments/production.rb'
|
- 'config/environments/production.rb'
|
||||||
- 'config/initializers/content_security_policy.rb'
|
- 'config/initializers/content_security_policy.rb'
|
||||||
|
|
||||||
# This cop supports safe autocorrection (--autocorrect).
|
|
||||||
# Configuration parameters: EnforcedStyle.
|
|
||||||
# SupportedStyles: space, no_space
|
|
||||||
Layout/SpaceInsideStringInterpolation:
|
|
||||||
Exclude:
|
|
||||||
- 'config/initializers/webauthn.rb'
|
|
||||||
|
|
||||||
# This cop supports safe autocorrection (--autocorrect).
|
|
||||||
# Configuration parameters: AllowInHeredoc.
|
|
||||||
Layout/TrailingWhitespace:
|
|
||||||
Exclude:
|
|
||||||
- 'config/initializers/paperclip.rb'
|
|
||||||
|
|
||||||
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
||||||
Lint/AmbiguousBlockAssociation:
|
Lint/AmbiguousBlockAssociation:
|
||||||
Exclude:
|
Exclude:
|
||||||
|
@ -621,7 +588,6 @@ RSpec/NoExpectationExample:
|
||||||
|
|
||||||
RSpec/PendingWithoutReason:
|
RSpec/PendingWithoutReason:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'spec/controllers/statuses_controller_spec.rb'
|
|
||||||
- 'spec/models/account_spec.rb'
|
- 'spec/models/account_spec.rb'
|
||||||
|
|
||||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||||
|
@ -637,10 +603,6 @@ RSpec/RepeatedExample:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'spec/policies/status_policy_spec.rb'
|
- 'spec/policies/status_policy_spec.rb'
|
||||||
|
|
||||||
RSpec/RepeatedExampleGroupBody:
|
|
||||||
Exclude:
|
|
||||||
- 'spec/controllers/statuses_controller_spec.rb'
|
|
||||||
|
|
||||||
RSpec/StubbedMock:
|
RSpec/StubbedMock:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'spec/controllers/api/base_controller_spec.rb'
|
- 'spec/controllers/api/base_controller_spec.rb'
|
||||||
|
|
|
@ -55,7 +55,7 @@ SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||||
ENV DEBIAN_FRONTEND="noninteractive" \
|
ENV DEBIAN_FRONTEND="noninteractive" \
|
||||||
PATH="${PATH}:/opt/ruby/bin:/opt/mastodon/bin"
|
PATH="${PATH}:/opt/ruby/bin:/opt/mastodon/bin"
|
||||||
|
|
||||||
# Ignoreing these here since we don't want to pin any versions and the Debian image removes apt-get content after use
|
# Ignoring these here since we don't want to pin any versions and the Debian image removes apt-get content after use
|
||||||
# hadolint ignore=DL3008,DL3009
|
# hadolint ignore=DL3008,DL3009
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
echo "Etc/UTC" > /etc/localtime && \
|
echo "Etc/UTC" > /etc/localtime && \
|
||||||
|
|
85
Gemfile
85
Gemfile
|
@ -99,54 +99,87 @@ gem 'json-ld'
|
||||||
gem 'json-ld-preloaded', '~> 3.2'
|
gem 'json-ld-preloaded', '~> 3.2'
|
||||||
gem 'rdf-normalize', '~> 0.5'
|
gem 'rdf-normalize', '~> 0.5'
|
||||||
|
|
||||||
group :development, :test do
|
gem 'private_address_check', '~> 0.5'
|
||||||
gem 'fabrication', '~> 2.30'
|
|
||||||
gem 'fuubar', '~> 2.5'
|
|
||||||
gem 'i18n-tasks', '~> 1.0', require: false
|
|
||||||
gem 'rspec-rails', '~> 6.0'
|
|
||||||
gem 'rspec_chunked', '~> 0.6'
|
|
||||||
|
|
||||||
gem 'rubocop-capybara', require: false
|
|
||||||
gem 'rubocop-performance', require: false
|
|
||||||
gem 'rubocop-rails', require: false
|
|
||||||
gem 'rubocop-rspec', require: false
|
|
||||||
gem 'rubocop', require: false
|
|
||||||
end
|
|
||||||
|
|
||||||
group :production, :test do
|
|
||||||
gem 'private_address_check', '~> 0.5'
|
|
||||||
end
|
|
||||||
|
|
||||||
group :test do
|
group :test do
|
||||||
gem 'capybara', '~> 3.39'
|
# RSpec runner for rails
|
||||||
gem 'climate_control'
|
gem 'rspec-rails', '~> 6.0'
|
||||||
gem 'faker', '~> 3.2'
|
|
||||||
gem 'json-schema', '~> 4.0'
|
# Used to split testing into chunks in CI
|
||||||
gem 'rack-test', '~> 2.1'
|
gem 'rspec_chunked', '~> 0.6'
|
||||||
gem 'rails-controller-testing', '~> 1.0'
|
|
||||||
gem 'rspec_junit_formatter', '~> 0.6'
|
# RSpec progress bar formatter
|
||||||
|
gem 'fuubar', '~> 2.5'
|
||||||
|
|
||||||
|
# Extra RSpec extenion methods and helpers for sidekiq
|
||||||
gem 'rspec-sidekiq', '~> 3.1'
|
gem 'rspec-sidekiq', '~> 3.1'
|
||||||
|
|
||||||
|
# Browser integration testing
|
||||||
|
gem 'capybara', '~> 3.39'
|
||||||
|
|
||||||
|
# Used to mock environment variables
|
||||||
|
gem 'climate_control', '~> 0.2'
|
||||||
|
|
||||||
|
# Generating fake data for specs
|
||||||
|
gem 'faker', '~> 3.2'
|
||||||
|
|
||||||
|
# Generate test objects for specs
|
||||||
|
gem 'fabrication', '~> 2.30'
|
||||||
|
|
||||||
|
# Add back helpers functions removed in Rails 5.1
|
||||||
|
gem 'rails-controller-testing', '~> 1.0'
|
||||||
|
|
||||||
|
# Validate schemas in specs
|
||||||
|
gem 'json-schema', '~> 4.0'
|
||||||
|
|
||||||
|
# Test harness fo rack components
|
||||||
|
gem 'rack-test', '~> 2.1'
|
||||||
|
|
||||||
|
# Coverage formatter for RSpec test if DISABLE_SIMPLECOV is false
|
||||||
gem 'simplecov', '~> 0.22', require: false
|
gem 'simplecov', '~> 0.22', require: false
|
||||||
|
|
||||||
|
# Stub web requests for specs
|
||||||
gem 'webmock', '~> 3.18'
|
gem 'webmock', '~> 3.18'
|
||||||
end
|
end
|
||||||
|
|
||||||
group :development do
|
group :development do
|
||||||
|
# Code linting CLI and plugins
|
||||||
|
gem 'rubocop', require: false
|
||||||
|
gem 'rubocop-capybara', require: false
|
||||||
|
gem 'rubocop-performance', require: false
|
||||||
|
gem 'rubocop-rails', require: false
|
||||||
|
gem 'rubocop-rspec', require: false
|
||||||
|
|
||||||
|
# Annotates modules with schema
|
||||||
gem 'annotate', '~> 3.2'
|
gem 'annotate', '~> 3.2'
|
||||||
|
|
||||||
|
# Enhanced error message pages for development
|
||||||
gem 'better_errors', '~> 2.9'
|
gem 'better_errors', '~> 2.9'
|
||||||
gem 'binding_of_caller', '~> 1.0'
|
gem 'binding_of_caller', '~> 1.0'
|
||||||
|
|
||||||
|
# Preview mail in the browser
|
||||||
gem 'letter_opener', '~> 1.8'
|
gem 'letter_opener', '~> 1.8'
|
||||||
gem 'letter_opener_web', '~> 2.0'
|
gem 'letter_opener_web', '~> 2.0'
|
||||||
gem 'memory_profiler'
|
|
||||||
|
# Security analysis CLI tools
|
||||||
gem 'brakeman', '~> 5.4', require: false
|
gem 'brakeman', '~> 5.4', require: false
|
||||||
gem 'bundler-audit', '~> 0.9', require: false
|
gem 'bundler-audit', '~> 0.9', require: false
|
||||||
|
|
||||||
|
# Linter CLI for HAML files
|
||||||
gem 'haml_lint', require: false
|
gem 'haml_lint', require: false
|
||||||
|
|
||||||
|
# Deployment automation
|
||||||
gem 'capistrano', '~> 3.17'
|
gem 'capistrano', '~> 3.17'
|
||||||
gem 'capistrano-rails', '~> 1.6'
|
gem 'capistrano-rails', '~> 1.6'
|
||||||
gem 'capistrano-rbenv', '~> 2.2'
|
gem 'capistrano-rbenv', '~> 2.2'
|
||||||
gem 'capistrano-yarn', '~> 2.0'
|
gem 'capistrano-yarn', '~> 2.0'
|
||||||
|
|
||||||
gem 'stackprof'
|
# Validate missing i18n keys
|
||||||
|
gem 'i18n-tasks', '~> 1.0', require: false
|
||||||
|
|
||||||
|
# Profiling tools
|
||||||
|
gem 'memory_profiler', require: false
|
||||||
|
gem 'stackprof', require: false
|
||||||
end
|
end
|
||||||
|
|
||||||
group :production do
|
group :production do
|
||||||
|
|
|
@ -601,8 +601,6 @@ GEM
|
||||||
sidekiq (>= 2.4.0)
|
sidekiq (>= 2.4.0)
|
||||||
rspec-support (3.12.0)
|
rspec-support (3.12.0)
|
||||||
rspec_chunked (0.6)
|
rspec_chunked (0.6)
|
||||||
rspec_junit_formatter (0.6.0)
|
|
||||||
rspec-core (>= 2, < 4, != 2.12.0)
|
|
||||||
rubocop (1.50.2)
|
rubocop (1.50.2)
|
||||||
json (~> 2.3)
|
json (~> 2.3)
|
||||||
parallel (~> 1.10)
|
parallel (~> 1.10)
|
||||||
|
@ -787,7 +785,7 @@ DEPENDENCIES
|
||||||
capybara (~> 3.39)
|
capybara (~> 3.39)
|
||||||
charlock_holmes (~> 0.7.7)
|
charlock_holmes (~> 0.7.7)
|
||||||
chewy (~> 7.3)
|
chewy (~> 7.3)
|
||||||
climate_control
|
climate_control (~> 0.2)
|
||||||
cocoon (~> 1.2)
|
cocoon (~> 1.2)
|
||||||
color_diff (~> 0.1)
|
color_diff (~> 0.1)
|
||||||
concurrent-ruby
|
concurrent-ruby
|
||||||
|
@ -866,7 +864,6 @@ DEPENDENCIES
|
||||||
rspec-rails (~> 6.0)
|
rspec-rails (~> 6.0)
|
||||||
rspec-sidekiq (~> 3.1)
|
rspec-sidekiq (~> 3.1)
|
||||||
rspec_chunked (~> 0.6)
|
rspec_chunked (~> 0.6)
|
||||||
rspec_junit_formatter (~> 0.6)
|
|
||||||
rubocop
|
rubocop
|
||||||
rubocop-capybara
|
rubocop-capybara
|
||||||
rubocop-performance
|
rubocop-performance
|
||||||
|
|
|
@ -29,7 +29,7 @@ class Api::V1::Admin::DomainAllowsController < Api::BaseController
|
||||||
def create
|
def create
|
||||||
authorize :domain_allow, :create?
|
authorize :domain_allow, :create?
|
||||||
|
|
||||||
@domain_allow = DomainAllow.find_by(resource_params)
|
@domain_allow = DomainAllow.find_by(domain: resource_params[:domain])
|
||||||
|
|
||||||
if @domain_allow.nil?
|
if @domain_allow.nil?
|
||||||
@domain_allow = DomainAllow.create!(resource_params)
|
@domain_allow = DomainAllow.create!(resource_params)
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
class Api::V1::Statuses::ReblogsController < Api::BaseController
|
class Api::V1::Statuses::ReblogsController < Api::BaseController
|
||||||
include Authorization
|
include Authorization
|
||||||
|
include Redisable
|
||||||
|
include Lockable
|
||||||
|
|
||||||
before_action -> { doorkeeper_authorize! :write, :'write:statuses' }
|
before_action -> { doorkeeper_authorize! :write, :'write:statuses' }
|
||||||
before_action :require_user!
|
before_action :require_user!
|
||||||
|
@ -10,7 +12,9 @@ class Api::V1::Statuses::ReblogsController < Api::BaseController
|
||||||
override_rate_limit_headers :create, family: :statuses
|
override_rate_limit_headers :create, family: :statuses
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@status = ReblogService.new.call(current_account, @reblog, reblog_params)
|
with_redis_lock("reblog:#{current_account.id}:#{@reblog.id}") do
|
||||||
|
@status = ReblogService.new.call(current_account, @reblog, reblog_params)
|
||||||
|
end
|
||||||
|
|
||||||
render json: @status, serializer: REST::StatusSerializer
|
render json: @status, serializer: REST::StatusSerializer
|
||||||
end
|
end
|
||||||
|
|
|
@ -132,7 +132,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_sessions
|
def set_sessions
|
||||||
@sessions = current_user.session_activations
|
@sessions = current_user.session_activations.order(updated_at: :desc)
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_strikes
|
def set_strikes
|
||||||
|
|
|
@ -10,6 +10,8 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio
|
||||||
before_action :set_body_classes
|
before_action :set_body_classes
|
||||||
before_action :set_cache_headers
|
before_action :set_cache_headers
|
||||||
|
|
||||||
|
before_action :set_last_used_at_by_app, only: :index, unless: -> { request.format == :json }
|
||||||
|
|
||||||
skip_before_action :require_functional!
|
skip_before_action :require_functional!
|
||||||
|
|
||||||
include Localized
|
include Localized
|
||||||
|
@ -40,4 +42,14 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio
|
||||||
def set_cache_headers
|
def set_cache_headers
|
||||||
response.cache_control.replace(private: true, no_store: true)
|
response.cache_control.replace(private: true, no_store: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_last_used_at_by_app
|
||||||
|
@last_used_at_by_app = Doorkeeper::AccessToken
|
||||||
|
.select('DISTINCT ON (application_id) application_id, last_used_at')
|
||||||
|
.where(resource_owner_id: current_resource_owner.id)
|
||||||
|
.where.not(last_used_at: nil)
|
||||||
|
.order(application_id: :desc, last_used_at: :desc)
|
||||||
|
.pluck(:application_id, :last_used_at)
|
||||||
|
.to_h
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import * as html from '../html';
|
import * as html from '../html';
|
||||||
|
|
||||||
describe('html', () => {
|
describe('html', () => {
|
||||||
describe('unsecapeHTML', () => {
|
describe('unescapeHTML', () => {
|
||||||
it('returns unescaped HTML', () => {
|
it('returns unescaped HTML', () => {
|
||||||
const output = html.unescapeHTML('<p>lorem</p><p>ipsum</p><br><br>');
|
const output = html.unescapeHTML('<p>lorem</p><p>ipsum</p><br><br>');
|
||||||
expect(output).toEqual('lorem\n\nipsum\n<br>');
|
expect(output).toEqual('lorem\n\nipsum\n<br>');
|
||||||
|
|
|
@ -14,11 +14,6 @@ declare module '*.jpg' {
|
||||||
export default path;
|
export default path;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module '*.jpg' {
|
|
||||||
const path: string;
|
|
||||||
export default path;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '*.png' {
|
declare module '*.png' {
|
||||||
const path: string;
|
const path: string;
|
||||||
export default path;
|
export default path;
|
||||||
|
|
|
@ -16,7 +16,7 @@ class ActivityPub::Activity::Flag < ActivityPub::Activity
|
||||||
@account,
|
@account,
|
||||||
target_account,
|
target_account,
|
||||||
status_ids: target_statuses.nil? ? [] : target_statuses.map(&:id),
|
status_ids: target_statuses.nil? ? [] : target_statuses.map(&:id),
|
||||||
comment: @json['content'] || '',
|
comment: report_comment,
|
||||||
uri: report_uri
|
uri: report_uri
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
@ -35,4 +35,8 @@ class ActivityPub::Activity::Flag < ActivityPub::Activity
|
||||||
def report_uri
|
def report_uri
|
||||||
@json['id'] unless @json['id'].nil? || non_matching_uri_hosts?(@account.uri, @json['id'])
|
@json['id'] unless @json['id'].nil? || non_matching_uri_hosts?(@account.uri, @json['id'])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def report_comment
|
||||||
|
(@json['content'] || '')[0...5000]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -28,6 +28,8 @@ class ActivityPub::TagManager
|
||||||
return activity_account_status_url(target.account, target) if target.reblog?
|
return activity_account_status_url(target.account, target) if target.reblog?
|
||||||
|
|
||||||
short_account_status_url(target.account, target)
|
short_account_status_url(target.account, target)
|
||||||
|
when :flag
|
||||||
|
target.uri
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -43,6 +45,8 @@ class ActivityPub::TagManager
|
||||||
account_status_url(target.account, target)
|
account_status_url(target.account, target)
|
||||||
when :emoji
|
when :emoji
|
||||||
emoji_url(target)
|
emoji_url(target)
|
||||||
|
when :flag
|
||||||
|
target.uri
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -9,10 +9,6 @@ module ApplicationExtension
|
||||||
validates :redirect_uri, length: { maximum: 2_000 }
|
validates :redirect_uri, length: { maximum: 2_000 }
|
||||||
end
|
end
|
||||||
|
|
||||||
def most_recently_used_access_token
|
|
||||||
@most_recently_used_access_token ||= access_tokens.where.not(last_used_at: nil).order(last_used_at: :desc).first
|
|
||||||
end
|
|
||||||
|
|
||||||
def confirmation_redirect_uri
|
def confirmation_redirect_uri
|
||||||
redirect_uri.lines.first.strip
|
redirect_uri.lines.first.strip
|
||||||
end
|
end
|
||||||
|
|
|
@ -140,7 +140,7 @@ class LinkDetailsExtractor
|
||||||
end
|
end
|
||||||
|
|
||||||
def html
|
def html
|
||||||
player_url.present? ? content_tag(:iframe, nil, src: player_url, width: width, height: height, allowtransparency: 'true', scrolling: 'no', frameborder: '0') : nil
|
player_url.present? ? content_tag(:iframe, nil, src: player_url, width: width, height: height, allowfullscreen: 'true', allowtransparency: 'true', scrolling: 'no', frameborder: '0') : nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def width
|
def width
|
||||||
|
|
|
@ -40,7 +40,10 @@ class Report < ApplicationRecord
|
||||||
scope :resolved, -> { where.not(action_taken_at: nil) }
|
scope :resolved, -> { where.not(action_taken_at: nil) }
|
||||||
scope :with_accounts, -> { includes([:account, :target_account, :action_taken_by_account, :assigned_account].index_with({ user: [:invite_request, :invite] })) }
|
scope :with_accounts, -> { includes([:account, :target_account, :action_taken_by_account, :assigned_account].index_with({ user: [:invite_request, :invite] })) }
|
||||||
|
|
||||||
validates :comment, length: { maximum: 1_000 }
|
# A report is considered local if the reporter is local
|
||||||
|
delegate :local?, to: :account
|
||||||
|
|
||||||
|
validates :comment, length: { maximum: 1_000 }, if: :local?
|
||||||
validates :rule_ids, absence: true, unless: :violation?
|
validates :rule_ids, absence: true, unless: :violation?
|
||||||
|
|
||||||
validate :validate_rule_ids
|
validate :validate_rule_ids
|
||||||
|
@ -51,10 +54,6 @@ class Report < ApplicationRecord
|
||||||
violation: 2_000,
|
violation: 2_000,
|
||||||
}
|
}
|
||||||
|
|
||||||
def local?
|
|
||||||
false # Force uri_for to use uri attribute
|
|
||||||
end
|
|
||||||
|
|
||||||
before_validation :set_uri, only: :create
|
before_validation :set_uri, only: :create
|
||||||
|
|
||||||
after_create_commit :trigger_webhooks
|
after_create_commit :trigger_webhooks
|
||||||
|
|
|
@ -101,8 +101,8 @@ class BackupService < BaseService
|
||||||
actor[:likes] = 'likes.json'
|
actor[:likes] = 'likes.json'
|
||||||
actor[:bookmarks] = 'bookmarks.json'
|
actor[:bookmarks] = 'bookmarks.json'
|
||||||
|
|
||||||
download_to_zip(tar, account.avatar, "avatar#{File.extname(account.avatar.path)}") if account.avatar.exists?
|
download_to_zip(zipfile, account.avatar, "avatar#{File.extname(account.avatar.path)}") if account.avatar.exists?
|
||||||
download_to_zip(tar, account.header, "header#{File.extname(account.header.path)}") if account.header.exists?
|
download_to_zip(zipfile, account.header, "header#{File.extname(account.header.path)}") if account.header.exists?
|
||||||
|
|
||||||
json = Oj.dump(actor)
|
json = Oj.dump(actor)
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
class VoteValidator < ActiveModel::Validator
|
class VoteValidator < ActiveModel::Validator
|
||||||
def validate(vote)
|
def validate(vote)
|
||||||
vote.errors.add(:base, I18n.t('polls.errors.expired')) if vote.poll_expired?
|
vote.errors.add(:base, I18n.t('polls.errors.expired')) if vote.poll_expired?
|
||||||
|
|
||||||
vote.errors.add(:base, I18n.t('polls.errors.invalid_choice')) if invalid_choice?(vote)
|
vote.errors.add(:base, I18n.t('polls.errors.invalid_choice')) if invalid_choice?(vote)
|
||||||
|
vote.errors.add(:base, I18n.t('polls.errors.self_vote')) if self_vote?(vote)
|
||||||
|
|
||||||
vote.errors.add(:base, I18n.t('polls.errors.already_voted')) if additional_voting_not_allowed?(vote)
|
vote.errors.add(:base, I18n.t('polls.errors.already_voted')) if additional_voting_not_allowed?(vote)
|
||||||
end
|
end
|
||||||
|
@ -27,6 +27,10 @@ class VoteValidator < ActiveModel::Validator
|
||||||
vote.choice.negative? || vote.choice >= vote.poll.options.size
|
vote.choice.negative? || vote.choice >= vote.poll.options.size
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self_vote?(vote)
|
||||||
|
vote.account_id == vote.poll.account_id
|
||||||
|
end
|
||||||
|
|
||||||
def already_voted_for_same_choice_on_multiple_poll?(vote)
|
def already_voted_for_same_choice_on_multiple_poll?(vote)
|
||||||
if vote.persisted?
|
if vote.persisted?
|
||||||
account_votes_on_same_poll(vote).where(choice: vote.choice).where.not(poll_votes: { id: vote }).exists?
|
account_votes_on_same_poll(vote).where(choice: vote.choice).where.not(poll_votes: { id: vote }).exists?
|
||||||
|
|
|
@ -18,8 +18,8 @@
|
||||||
|
|
||||||
.announcements-list__item__action-bar
|
.announcements-list__item__action-bar
|
||||||
.announcements-list__item__meta
|
.announcements-list__item__meta
|
||||||
- if application.most_recently_used_access_token
|
- if @last_used_at_by_app[application.id]
|
||||||
= t('doorkeeper.authorized_applications.index.last_used_at', date: l(application.most_recently_used_access_token.last_used_at.to_date))
|
= t('doorkeeper.authorized_applications.index.last_used_at', date: l(@last_used_at_by_app[application.id].to_date))
|
||||||
- else
|
- else
|
||||||
= t('doorkeeper.authorized_applications.index.never_used')
|
= t('doorkeeper.authorized_applications.index.never_used')
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ class PostProcessMediaWorker
|
||||||
media_attachment.processing = :in_progress
|
media_attachment.processing = :in_progress
|
||||||
media_attachment.save
|
media_attachment.save
|
||||||
|
|
||||||
# Because paperclip-av-transcover overwrites this attribute
|
# Because paperclip-av-transcoder overwrites this attribute
|
||||||
# we will save it here and restore it after reprocess is done
|
# we will save it here and restore it after reprocess is done
|
||||||
previous_meta = media_attachment.file_meta
|
previous_meta = media_attachment.file_meta
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
if ENV['FFMPEG_BINARY'].present?
|
if ENV['FFMPEG_BINARY'].present?
|
||||||
FFMPEG.ffmpeg_binary = ENV['FFMPEG_BINARY']
|
FFMPEG.ffmpeg_binary = ENV['FFMPEG_BINARY']
|
||||||
end
|
end
|
||||||
|
|
|
@ -73,7 +73,7 @@ Devise.setup do |config|
|
||||||
oidc_options[:display_name] = ENV['OIDC_DISPLAY_NAME'] #OPTIONAL
|
oidc_options[:display_name] = ENV['OIDC_DISPLAY_NAME'] #OPTIONAL
|
||||||
oidc_options[:issuer] = ENV['OIDC_ISSUER'] if ENV['OIDC_ISSUER'] #NEED
|
oidc_options[:issuer] = ENV['OIDC_ISSUER'] if ENV['OIDC_ISSUER'] #NEED
|
||||||
oidc_options[:discovery] = ENV['OIDC_DISCOVERY'] == 'true' if ENV['OIDC_DISCOVERY'] #OPTIONAL (default: false)
|
oidc_options[:discovery] = ENV['OIDC_DISCOVERY'] == 'true' if ENV['OIDC_DISCOVERY'] #OPTIONAL (default: false)
|
||||||
oidc_options[:client_auth_method] = ENV['OIDC_CLIENT_AUTH_METHOD'] if ENV['OIDC_CLIENT_AUTH_METHOD'] #OPTIONAL (default: basic)
|
oidc_options[:client_auth_method] = ENV['OIDC_CLIENT_AUTH_METHOD'] if ENV['OIDC_CLIENT_AUTH_METHOD'] #OPTIONAL (default: basic)
|
||||||
scope_string = ENV['OIDC_SCOPE'] if ENV['OIDC_SCOPE'] #NEED
|
scope_string = ENV['OIDC_SCOPE'] if ENV['OIDC_SCOPE'] #NEED
|
||||||
scopes = scope_string.split(',')
|
scopes = scope_string.split(',')
|
||||||
oidc_options[:scope] = scopes.map { |x| x.to_sym }
|
oidc_options[:scope] = scopes.map { |x| x.to_sym }
|
||||||
|
|
|
@ -61,13 +61,13 @@ if ENV['S3_ENABLED'] == 'true'
|
||||||
|
|
||||||
s3_options: {
|
s3_options: {
|
||||||
signature_version: ENV.fetch('S3_SIGNATURE_VERSION') { 'v4' },
|
signature_version: ENV.fetch('S3_SIGNATURE_VERSION') { 'v4' },
|
||||||
http_open_timeout: ENV.fetch('S3_OPEN_TIMEOUT'){ '5' }.to_i,
|
http_open_timeout: ENV.fetch('S3_OPEN_TIMEOUT') { '5' }.to_i,
|
||||||
http_read_timeout: ENV.fetch('S3_READ_TIMEOUT'){ '5' }.to_i,
|
http_read_timeout: ENV.fetch('S3_READ_TIMEOUT') { '5' }.to_i,
|
||||||
http_idle_timeout: 5,
|
http_idle_timeout: 5,
|
||||||
retry_limit: 0,
|
retry_limit: 0,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
Paperclip::Attachment.default_options[:s3_permissions] = ->(*) { nil } if ENV['S3_PERMISSION'] == ''
|
Paperclip::Attachment.default_options[:s3_permissions] = ->(*) { nil } if ENV['S3_PERMISSION'] == ''
|
||||||
|
|
||||||
if ENV.has_key?('S3_ENDPOINT')
|
if ENV.has_key?('S3_ENDPOINT')
|
||||||
|
@ -124,7 +124,7 @@ elsif ENV['SWIFT_ENABLED'] == 'true'
|
||||||
openstack_cache_ttl: ENV.fetch('SWIFT_CACHE_TTL') { 60 },
|
openstack_cache_ttl: ENV.fetch('SWIFT_CACHE_TTL') { 60 },
|
||||||
openstack_temp_url_key: ENV['SWIFT_TEMP_URL_KEY'],
|
openstack_temp_url_key: ENV['SWIFT_TEMP_URL_KEY'],
|
||||||
},
|
},
|
||||||
|
|
||||||
fog_file: { 'Cache-Control' => 'public, max-age=315576000, immutable' },
|
fog_file: { 'Cache-Control' => 'public, max-age=315576000, immutable' },
|
||||||
|
|
||||||
fog_directory: ENV['SWIFT_CONTAINER'],
|
fog_directory: ENV['SWIFT_CONTAINER'],
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
WebAuthn.configure do |config|
|
WebAuthn.configure do |config|
|
||||||
# This value needs to match `window.location.origin` evaluated by
|
# This value needs to match `window.location.origin` evaluated by
|
||||||
# the User Agent during registration and authentication ceremonies.
|
# the User Agent during registration and authentication ceremonies.
|
||||||
config.origin = "#{Rails.configuration.x.use_https ? 'https' : 'http' }://#{Rails.configuration.x.web_domain}"
|
config.origin = "#{Rails.configuration.x.use_https ? 'https' : 'http'}://#{Rails.configuration.x.web_domain}"
|
||||||
|
|
||||||
# Relying Party name for display purposes
|
# Relying Party name for display purposes
|
||||||
config.rp_name = "Mastodon"
|
config.rp_name = "Mastodon"
|
||||||
|
|
|
@ -1446,6 +1446,7 @@ en:
|
||||||
expired: The poll has already ended
|
expired: The poll has already ended
|
||||||
invalid_choice: The chosen vote option does not exist
|
invalid_choice: The chosen vote option does not exist
|
||||||
over_character_limit: cannot be longer than %{max} characters each
|
over_character_limit: cannot be longer than %{max} characters each
|
||||||
|
self_vote: You cannot vote in your own polls
|
||||||
too_few_options: must have more than one item
|
too_few_options: must have more than one item
|
||||||
too_many_options: can't contain more than %{max} items
|
too_many_options: can't contain more than %{max} items
|
||||||
preferences:
|
preferences:
|
||||||
|
|
|
@ -10,7 +10,6 @@ const config = {
|
||||||
'<rootDir>/tmp/',
|
'<rootDir>/tmp/',
|
||||||
'<rootDir>/app/javascript/themes/',
|
'<rootDir>/app/javascript/themes/',
|
||||||
],
|
],
|
||||||
setupFiles: ['raf/polyfill'],
|
|
||||||
setupFilesAfterEnv: ['<rootDir>/app/javascript/mastodon/test_setup.js'],
|
setupFilesAfterEnv: ['<rootDir>/app/javascript/mastodon/test_setup.js'],
|
||||||
collectCoverageFrom: [
|
collectCoverageFrom: [
|
||||||
'app/javascript/mastodon/**/*.{js,jsx,ts,tsx}',
|
'app/javascript/mastodon/**/*.{js,jsx,ts,tsx}',
|
||||||
|
|
|
@ -24,7 +24,7 @@ module Mastodon
|
||||||
desc 'remove', 'Remove remote media files, headers or avatars'
|
desc 'remove', 'Remove remote media files, headers or avatars'
|
||||||
long_desc <<-DESC
|
long_desc <<-DESC
|
||||||
Removes locally cached copies of media attachments (and optionally profile
|
Removes locally cached copies of media attachments (and optionally profile
|
||||||
headers and avatars) from other servers. By default, only media attachements
|
headers and avatars) from other servers. By default, only media attachments
|
||||||
are removed.
|
are removed.
|
||||||
The --days option specifies how old media attachments have to be before
|
The --days option specifies how old media attachments have to be before
|
||||||
they are removed. In case of avatars and headers, it specifies how old
|
they are removed. In case of avatars and headers, it specifies how old
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace :tests do
|
||||||
end
|
end
|
||||||
|
|
||||||
if Account.where(domain: Rails.configuration.x.local_domain).exists?
|
if Account.where(domain: Rails.configuration.x.local_domain).exists?
|
||||||
puts 'Faux remote accounts not properly claned up'
|
puts 'Faux remote accounts not properly cleaned up'
|
||||||
exit(1)
|
exit(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@
|
||||||
"intl-messageformat": "^2.2.0",
|
"intl-messageformat": "^2.2.0",
|
||||||
"intl-relativeformat": "^6.4.3",
|
"intl-relativeformat": "^6.4.3",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"jsdom": "^21.1.2",
|
"jsdom": "^22.0.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"mark-loader": "^0.1.6",
|
"mark-loader": "^0.1.6",
|
||||||
"marky": "^1.2.5",
|
"marky": "^1.2.5",
|
||||||
|
@ -158,7 +158,6 @@
|
||||||
"@types/pg": "^8.6.6",
|
"@types/pg": "^8.6.6",
|
||||||
"@types/prop-types": "^15.7.5",
|
"@types/prop-types": "^15.7.5",
|
||||||
"@types/punycode": "^2.1.0",
|
"@types/punycode": "^2.1.0",
|
||||||
"@types/raf": "^3.4.0",
|
|
||||||
"@types/react": "^16.14.38",
|
"@types/react": "^16.14.38",
|
||||||
"@types/react-dom": "^16.9.18",
|
"@types/react-dom": "^16.9.18",
|
||||||
"@types/react-helmet": "^6.1.6",
|
"@types/react-helmet": "^6.1.6",
|
||||||
|
@ -198,7 +197,6 @@
|
||||||
"jest-environment-jsdom": "^29.5.0",
|
"jest-environment-jsdom": "^29.5.0",
|
||||||
"lint-staged": "^13.2.2",
|
"lint-staged": "^13.2.2",
|
||||||
"prettier": "^2.8.8",
|
"prettier": "^2.8.8",
|
||||||
"raf": "^3.4.1",
|
|
||||||
"react-intl-translations-manager": "^5.0.3",
|
"react-intl-translations-manager": "^5.0.3",
|
||||||
"react-test-renderer": "^16.14.0",
|
"react-test-renderer": "^16.14.0",
|
||||||
"stylelint": "^15.6.1",
|
"stylelint": "^15.6.1",
|
||||||
|
|
|
@ -32,7 +32,7 @@ RSpec.describe Admin::ConfirmationsController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'POST #resernd' do
|
describe 'POST #resend' do
|
||||||
subject { post :resend, params: { account_id: user.account.id } }
|
subject { post :resend, params: { account_id: user.account.id } }
|
||||||
|
|
||||||
let!(:user) { Fabricate(:user, confirmed_at: confirmed_at) }
|
let!(:user) { Fabricate(:user, confirmed_at: confirmed_at) }
|
||||||
|
|
|
@ -5,23 +5,182 @@ require 'rails_helper'
|
||||||
describe Api::V1::Admin::CanonicalEmailBlocksController do
|
describe Api::V1::Admin::CanonicalEmailBlocksController do
|
||||||
render_views
|
render_views
|
||||||
|
|
||||||
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
|
let(:role) { UserRole.find_by(name: 'Admin') }
|
||||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'admin:read') }
|
let(:user) { Fabricate(:user, role: role) }
|
||||||
let(:account) { Fabricate(:account) }
|
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||||
|
let(:scopes) { 'admin:read:canonical_email_blocks admin:write:canonical_email_blocks' }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(controller).to receive(:doorkeeper_token) { token }
|
allow(controller).to receive(:doorkeeper_token) { token }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
shared_examples 'forbidden for wrong scope' do |wrong_scope|
|
||||||
|
let(:scopes) { wrong_scope }
|
||||||
|
|
||||||
|
it 'returns http forbidden' do
|
||||||
|
expect(response).to have_http_status(403)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
shared_examples 'forbidden for wrong role' do |wrong_role|
|
||||||
|
let(:role) { UserRole.find_by(name: wrong_role) }
|
||||||
|
|
||||||
|
it 'returns http forbidden' do
|
||||||
|
expect(response).to have_http_status(403)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe 'GET #index' do
|
describe 'GET #index' do
|
||||||
|
context 'with wrong scope' do
|
||||||
|
before do
|
||||||
|
get :index
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'read:statuses'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with wrong role' do
|
||||||
|
before do
|
||||||
|
get :index
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong role', ''
|
||||||
|
it_behaves_like 'forbidden for wrong role', 'Moderator'
|
||||||
|
end
|
||||||
|
|
||||||
it 'returns http success' do
|
it 'returns http success' do
|
||||||
get :index, params: { account_id: account.id, limit: 2 }
|
get :index
|
||||||
|
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when there is no canonical email block' do
|
||||||
|
it 'returns an empty list' do
|
||||||
|
get :index
|
||||||
|
|
||||||
|
body = body_as_json
|
||||||
|
|
||||||
|
expect(body).to be_empty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when there are canonical email blocks' do
|
||||||
|
let!(:canonical_email_blocks) { Fabricate.times(5, :canonical_email_block) }
|
||||||
|
let(:expected_email_hashes) { canonical_email_blocks.pluck(:canonical_email_hash) }
|
||||||
|
|
||||||
|
it 'returns the correct canonical email hashes' do
|
||||||
|
get :index
|
||||||
|
|
||||||
|
json = body_as_json
|
||||||
|
|
||||||
|
expect(json.pluck(:canonical_email_hash)).to match_array(expected_email_hashes)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with limit param' do
|
||||||
|
let(:params) { { limit: 2 } }
|
||||||
|
|
||||||
|
it 'returns only the requested number of canonical email blocks' do
|
||||||
|
get :index, params: params
|
||||||
|
|
||||||
|
json = body_as_json
|
||||||
|
|
||||||
|
expect(json.size).to eq(params[:limit])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with since_id param' do
|
||||||
|
let(:params) { { since_id: canonical_email_blocks[1].id } }
|
||||||
|
|
||||||
|
it 'returns only the canonical email blocks after since_id' do
|
||||||
|
get :index, params: params
|
||||||
|
|
||||||
|
canonical_email_blocks_ids = canonical_email_blocks.pluck(:id).map(&:to_s)
|
||||||
|
json = body_as_json
|
||||||
|
|
||||||
|
expect(json.pluck(:id)).to match_array(canonical_email_blocks_ids[2..])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with max_id param' do
|
||||||
|
let(:params) { { max_id: canonical_email_blocks[3].id } }
|
||||||
|
|
||||||
|
it 'returns only the canonical email blocks before max_id' do
|
||||||
|
get :index, params: params
|
||||||
|
|
||||||
|
canonical_email_blocks_ids = canonical_email_blocks.pluck(:id).map(&:to_s)
|
||||||
|
json = body_as_json
|
||||||
|
|
||||||
|
expect(json.pluck(:id)).to match_array(canonical_email_blocks_ids[..2])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'GET #show' do
|
||||||
|
let!(:canonical_email_block) { Fabricate(:canonical_email_block) }
|
||||||
|
let(:params) { { id: canonical_email_block.id } }
|
||||||
|
|
||||||
|
context 'with wrong scope' do
|
||||||
|
before do
|
||||||
|
get :show, params: params
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'read:statuses'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with wrong role' do
|
||||||
|
before do
|
||||||
|
get :show, params: params
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong role', ''
|
||||||
|
it_behaves_like 'forbidden for wrong role', 'Moderator'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when canonical email block exists' do
|
||||||
|
it 'returns http success' do
|
||||||
|
get :show, params: params
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns canonical email block data correctly' do
|
||||||
|
get :show, params: params
|
||||||
|
|
||||||
|
json = body_as_json
|
||||||
|
|
||||||
|
expect(json[:id]).to eq(canonical_email_block.id.to_s)
|
||||||
|
expect(json[:canonical_email_hash]).to eq(canonical_email_block.canonical_email_hash)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when canonical block does not exist' do
|
||||||
|
it 'returns http not found' do
|
||||||
|
get :show, params: { id: 0 }
|
||||||
|
|
||||||
|
expect(response).to have_http_status(404)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'POST #test' do
|
describe 'POST #test' do
|
||||||
|
context 'with wrong scope' do
|
||||||
|
before do
|
||||||
|
post :test
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'read:statuses'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with wrong role' do
|
||||||
|
before do
|
||||||
|
post :test, params: { email: 'whatever@email.com' }
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong role', ''
|
||||||
|
it_behaves_like 'forbidden for wrong role', 'Moderator'
|
||||||
|
end
|
||||||
|
|
||||||
context 'when required email is not provided' do
|
context 'when required email is not provided' do
|
||||||
it 'returns http bad request' do
|
it 'returns http bad request' do
|
||||||
post :test
|
post :test
|
||||||
|
@ -68,4 +227,132 @@ describe Api::V1::Admin::CanonicalEmailBlocksController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'POST #create' do
|
||||||
|
let(:params) { { email: 'example@email.com' } }
|
||||||
|
let(:canonical_email_block) { CanonicalEmailBlock.new(email: params[:email]) }
|
||||||
|
|
||||||
|
context 'with wrong scope' do
|
||||||
|
before do
|
||||||
|
post :create, params: params
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'read:statuses'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with wrong role' do
|
||||||
|
before do
|
||||||
|
post :create, params: params
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong role', ''
|
||||||
|
it_behaves_like 'forbidden for wrong role', 'Moderator'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
post :create, params: params
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns canonical_email_hash correctly' do
|
||||||
|
post :create, params: params
|
||||||
|
|
||||||
|
json = body_as_json
|
||||||
|
|
||||||
|
expect(json[:canonical_email_hash]).to eq(canonical_email_block.canonical_email_hash)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when required email param is not provided' do
|
||||||
|
it 'returns http unprocessable entity' do
|
||||||
|
post :create
|
||||||
|
|
||||||
|
expect(response).to have_http_status(422)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when canonical_email_hash param is provided instead of email' do
|
||||||
|
let(:params) { { canonical_email_hash: 'dd501ce4e6b08698f19df96f2f15737e48a75660b1fa79b6ff58ea25ee4851a4' } }
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
post :create, params: params
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns correct canonical_email_hash' do
|
||||||
|
post :create, params: params
|
||||||
|
|
||||||
|
json = body_as_json
|
||||||
|
|
||||||
|
expect(json[:canonical_email_hash]).to eq(params[:canonical_email_hash])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when both email and canonical_email_hash params are provided' do
|
||||||
|
let(:params) { { email: 'example@email.com', canonical_email_hash: 'dd501ce4e6b08698f19df96f2f15737e48a75660b1fa79b6ff58ea25ee4851a4' } }
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
post :create, params: params
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'ignores canonical_email_hash param' do
|
||||||
|
post :create, params: params
|
||||||
|
|
||||||
|
json = body_as_json
|
||||||
|
|
||||||
|
expect(json[:canonical_email_hash]).to eq(canonical_email_block.canonical_email_hash)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when canonical email was already blocked' do
|
||||||
|
before do
|
||||||
|
canonical_email_block.save
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http unprocessable entity' do
|
||||||
|
post :create, params: params
|
||||||
|
|
||||||
|
expect(response).to have_http_status(422)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'DELETE #destroy' do
|
||||||
|
let!(:canonical_email_block) { Fabricate(:canonical_email_block) }
|
||||||
|
let(:params) { { id: canonical_email_block.id } }
|
||||||
|
|
||||||
|
context 'with wrong scope' do
|
||||||
|
before do
|
||||||
|
delete :destroy, params: params
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'read:statuses'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with wrong role' do
|
||||||
|
before do
|
||||||
|
delete :destroy, params: params
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong role', ''
|
||||||
|
it_behaves_like 'forbidden for wrong role', 'Moderator'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
delete :destroy, params: params
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when canonical email block is not found' do
|
||||||
|
it 'returns http not found' do
|
||||||
|
delete :destroy, params: { id: 0 }
|
||||||
|
|
||||||
|
expect(response).to have_http_status(404)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -128,5 +128,13 @@ RSpec.describe Api::V1::Admin::DomainAllowsController do
|
||||||
expect(response).to have_http_status(422)
|
expect(response).to have_http_status(422)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when domain name is not specified' do
|
||||||
|
it 'returns http unprocessable entity' do
|
||||||
|
post :create
|
||||||
|
|
||||||
|
expect(response).to have_http_status(422)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,19 +5,280 @@ require 'rails_helper'
|
||||||
describe Api::V1::Admin::EmailDomainBlocksController do
|
describe Api::V1::Admin::EmailDomainBlocksController do
|
||||||
render_views
|
render_views
|
||||||
|
|
||||||
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
|
let(:role) { UserRole.find_by(name: 'Admin') }
|
||||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'admin:read') }
|
let(:user) { Fabricate(:user, role: role) }
|
||||||
|
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||||
let(:account) { Fabricate(:account) }
|
let(:account) { Fabricate(:account) }
|
||||||
|
let(:scopes) { 'admin:read:email_domain_blocks admin:write:email_domain_blocks' }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(controller).to receive(:doorkeeper_token) { token }
|
allow(controller).to receive(:doorkeeper_token) { token }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
shared_examples 'forbidden for wrong scope' do |wrong_scope|
|
||||||
|
let(:scopes) { wrong_scope }
|
||||||
|
|
||||||
|
it 'returns http forbidden' do
|
||||||
|
expect(response).to have_http_status(403)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
shared_examples 'forbidden for wrong role' do |wrong_role|
|
||||||
|
let(:role) { UserRole.find_by(name: wrong_role) }
|
||||||
|
|
||||||
|
it 'returns http forbidden' do
|
||||||
|
expect(response).to have_http_status(403)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe 'GET #index' do
|
describe 'GET #index' do
|
||||||
|
context 'with wrong scope' do
|
||||||
|
before do
|
||||||
|
get :index
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'read:statuses'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with wrong role' do
|
||||||
|
before do
|
||||||
|
get :index
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong role', ''
|
||||||
|
it_behaves_like 'forbidden for wrong role', 'Moderator'
|
||||||
|
end
|
||||||
|
|
||||||
it 'returns http success' do
|
it 'returns http success' do
|
||||||
get :index, params: { account_id: account.id, limit: 2 }
|
get :index
|
||||||
|
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when there is no email domain block' do
|
||||||
|
it 'returns an empty list' do
|
||||||
|
get :index
|
||||||
|
|
||||||
|
json = body_as_json
|
||||||
|
|
||||||
|
expect(json).to be_empty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when there are email domain blocks' do
|
||||||
|
let!(:email_domain_blocks) { Fabricate.times(5, :email_domain_block) }
|
||||||
|
let(:blocked_email_domains) { email_domain_blocks.pluck(:domain) }
|
||||||
|
|
||||||
|
it 'return the correct blocked email domains' do
|
||||||
|
get :index
|
||||||
|
|
||||||
|
json = body_as_json
|
||||||
|
|
||||||
|
expect(json.pluck(:domain)).to match_array(blocked_email_domains)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with limit param' do
|
||||||
|
let(:params) { { limit: 2 } }
|
||||||
|
|
||||||
|
it 'returns only the requested number of email domain blocks' do
|
||||||
|
get :index, params: params
|
||||||
|
|
||||||
|
json = body_as_json
|
||||||
|
|
||||||
|
expect(json.size).to eq(params[:limit])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with since_id param' do
|
||||||
|
let(:params) { { since_id: email_domain_blocks[1].id } }
|
||||||
|
|
||||||
|
it 'returns only the email domain blocks after since_id' do
|
||||||
|
get :index, params: params
|
||||||
|
|
||||||
|
email_domain_blocks_ids = email_domain_blocks.pluck(:id).map(&:to_s)
|
||||||
|
json = body_as_json
|
||||||
|
|
||||||
|
expect(json.pluck(:id)).to match_array(email_domain_blocks_ids[2..])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with max_id param' do
|
||||||
|
let(:params) { { max_id: email_domain_blocks[3].id } }
|
||||||
|
|
||||||
|
it 'returns only the email domain blocks before max_id' do
|
||||||
|
get :index, params: params
|
||||||
|
|
||||||
|
email_domain_blocks_ids = email_domain_blocks.pluck(:id).map(&:to_s)
|
||||||
|
json = body_as_json
|
||||||
|
|
||||||
|
expect(json.pluck(:id)).to match_array(email_domain_blocks_ids[..2])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'GET #show' do
|
||||||
|
let!(:email_domain_block) { Fabricate(:email_domain_block) }
|
||||||
|
let(:params) { { id: email_domain_block.id } }
|
||||||
|
|
||||||
|
context 'with wrong scope' do
|
||||||
|
before do
|
||||||
|
get :show, params: params
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'read:statuses'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with wrong role' do
|
||||||
|
before do
|
||||||
|
get :show, params: params
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong role', ''
|
||||||
|
it_behaves_like 'forbidden for wrong role', 'Moderator'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when email domain block exists' do
|
||||||
|
it 'returns http success' do
|
||||||
|
get :show, params: params
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns the correct blocked domain' do
|
||||||
|
get :show, params: params
|
||||||
|
|
||||||
|
json = body_as_json
|
||||||
|
|
||||||
|
expect(json[:domain]).to eq(email_domain_block.domain)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when email domain block does not exist' do
|
||||||
|
it 'returns http not found' do
|
||||||
|
get :show, params: { id: 0 }
|
||||||
|
|
||||||
|
expect(response).to have_http_status(404)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'POST #create' do
|
||||||
|
let(:params) { { domain: 'example.com' } }
|
||||||
|
|
||||||
|
context 'with wrong scope' do
|
||||||
|
before do
|
||||||
|
post :create, params: params
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'read:statuses'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with wrong role' do
|
||||||
|
before do
|
||||||
|
post :create, params: params
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong role', ''
|
||||||
|
it_behaves_like 'forbidden for wrong role', 'Moderator'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
post :create, params: params
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns the correct blocked email domain' do
|
||||||
|
post :create, params: params
|
||||||
|
|
||||||
|
json = body_as_json
|
||||||
|
|
||||||
|
expect(json[:domain]).to eq(params[:domain])
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when domain param is not provided' do
|
||||||
|
let(:params) { { domain: '' } }
|
||||||
|
|
||||||
|
it 'returns http unprocessable entity' do
|
||||||
|
post :create, params: params
|
||||||
|
|
||||||
|
expect(response).to have_http_status(422)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when provided domain name has an invalid character' do
|
||||||
|
let(:params) { { domain: 'do\uD800.com' } }
|
||||||
|
|
||||||
|
it 'returns http unprocessable entity' do
|
||||||
|
post :create, params: params
|
||||||
|
|
||||||
|
expect(response).to have_http_status(422)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when provided domain is already blocked' do
|
||||||
|
before do
|
||||||
|
EmailDomainBlock.create(params)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http unprocessable entity' do
|
||||||
|
post :create, params: params
|
||||||
|
|
||||||
|
expect(response).to have_http_status(422)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'DELETE #destroy' do
|
||||||
|
let!(:email_domain_block) { Fabricate(:email_domain_block) }
|
||||||
|
let(:params) { { id: email_domain_block.id } }
|
||||||
|
|
||||||
|
context 'with wrong scope' do
|
||||||
|
before do
|
||||||
|
delete :destroy, params: params
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'read:statuses'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with wrong role' do
|
||||||
|
before do
|
||||||
|
delete :destroy, params: params
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong role', ''
|
||||||
|
it_behaves_like 'forbidden for wrong role', 'Moderator'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
delete :destroy, params: params
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns an empty body' do
|
||||||
|
delete :destroy, params: params
|
||||||
|
|
||||||
|
json = body_as_json
|
||||||
|
|
||||||
|
expect(json).to be_empty
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'deletes email domain block' do
|
||||||
|
delete :destroy, params: params
|
||||||
|
|
||||||
|
email_domain_block = EmailDomainBlock.find_by(id: params[:id])
|
||||||
|
|
||||||
|
expect(email_domain_block).to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when email domain block does not exist' do
|
||||||
|
it 'returns http not found' do
|
||||||
|
delete :destroy, params: { id: 0 }
|
||||||
|
|
||||||
|
expect(response).to have_http_status(404)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,19 +5,305 @@ require 'rails_helper'
|
||||||
describe Api::V1::Admin::IpBlocksController do
|
describe Api::V1::Admin::IpBlocksController do
|
||||||
render_views
|
render_views
|
||||||
|
|
||||||
let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
|
let(:role) { UserRole.find_by(name: 'Admin') }
|
||||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'admin:read') }
|
let(:user) { Fabricate(:user, role: role) }
|
||||||
let(:account) { Fabricate(:account) }
|
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||||
|
let(:scopes) { 'admin:read:ip_blocks admin:write:ip_blocks' }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(controller).to receive(:doorkeeper_token) { token }
|
allow(controller).to receive(:doorkeeper_token) { token }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
shared_examples 'forbidden for wrong scope' do |wrong_scope|
|
||||||
|
let(:scopes) { wrong_scope }
|
||||||
|
|
||||||
|
it 'returns http forbidden' do
|
||||||
|
expect(response).to have_http_status(403)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
shared_examples 'forbidden for wrong role' do |wrong_role|
|
||||||
|
let(:role) { UserRole.find_by(name: wrong_role) }
|
||||||
|
|
||||||
|
it 'returns http forbidden' do
|
||||||
|
expect(response).to have_http_status(403)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe 'GET #index' do
|
describe 'GET #index' do
|
||||||
|
context 'with wrong scope' do
|
||||||
|
before do
|
||||||
|
get :index
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'admin:write:ip_blocks'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with wrong role' do
|
||||||
|
before do
|
||||||
|
get :index
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong role', ''
|
||||||
|
it_behaves_like 'forbidden for wrong role', 'Moderator'
|
||||||
|
end
|
||||||
|
|
||||||
it 'returns http success' do
|
it 'returns http success' do
|
||||||
get :index, params: { account_id: account.id, limit: 2 }
|
get :index
|
||||||
|
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when there is no ip block' do
|
||||||
|
it 'returns an empty body' do
|
||||||
|
get :index
|
||||||
|
|
||||||
|
json = body_as_json
|
||||||
|
|
||||||
|
expect(json).to be_empty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when there are ip blocks' do
|
||||||
|
let!(:ip_blocks) do
|
||||||
|
[
|
||||||
|
IpBlock.create(ip: '192.0.2.0/24', severity: :no_access),
|
||||||
|
IpBlock.create(ip: '172.16.0.1', severity: :sign_up_requires_approval, comment: 'Spam'),
|
||||||
|
IpBlock.create(ip: '2001:0db8::/32', severity: :sign_up_block, expires_in: 10.days),
|
||||||
|
]
|
||||||
|
end
|
||||||
|
let(:expected_response) do
|
||||||
|
ip_blocks.map do |ip_block|
|
||||||
|
{
|
||||||
|
id: ip_block.id.to_s,
|
||||||
|
ip: ip_block.ip,
|
||||||
|
severity: ip_block.severity.to_s,
|
||||||
|
comment: ip_block.comment,
|
||||||
|
created_at: ip_block.created_at.strftime('%Y-%m-%dT%H:%M:%S.%LZ'),
|
||||||
|
expires_at: ip_block.expires_at&.strftime('%Y-%m-%dT%H:%M:%S.%LZ'),
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns the correct blocked ips' do
|
||||||
|
get :index
|
||||||
|
|
||||||
|
json = body_as_json
|
||||||
|
|
||||||
|
expect(json).to match_array(expected_response)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with limit param' do
|
||||||
|
let(:params) { { limit: 2 } }
|
||||||
|
|
||||||
|
it 'returns only the requested number of ip blocks' do
|
||||||
|
get :index, params: params
|
||||||
|
|
||||||
|
json = body_as_json
|
||||||
|
|
||||||
|
expect(json.size).to eq(params[:limit])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'GET #show' do
|
||||||
|
let!(:ip_block) { IpBlock.create(ip: '192.0.2.0/24', severity: :no_access) }
|
||||||
|
let(:params) { { id: ip_block.id } }
|
||||||
|
|
||||||
|
context 'with wrong scope' do
|
||||||
|
before do
|
||||||
|
get :show, params: params
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'admin:write:ip_blocks'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with wrong role' do
|
||||||
|
before do
|
||||||
|
get :show, params: params
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong role', ''
|
||||||
|
it_behaves_like 'forbidden for wrong role', 'Moderator'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
get :show, params: params
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns the correct ip block' do
|
||||||
|
get :show, params: params
|
||||||
|
|
||||||
|
json = body_as_json
|
||||||
|
|
||||||
|
expect(json[:ip]).to eq("#{ip_block.ip}/#{ip_block.ip.prefix}")
|
||||||
|
expect(json[:severity]).to eq(ip_block.severity.to_s)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when ip block does not exist' do
|
||||||
|
it 'returns http not found' do
|
||||||
|
get :show, params: { id: 0 }
|
||||||
|
|
||||||
|
expect(response).to have_http_status(404)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'POST #create' do
|
||||||
|
let(:params) { { ip: '151.0.32.55', severity: 'no_access', comment: 'Spam' } }
|
||||||
|
|
||||||
|
context 'with wrong scope' do
|
||||||
|
before do
|
||||||
|
post :create, params: params
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'admin:read:ip_blocks'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with wrong role' do
|
||||||
|
before do
|
||||||
|
post :create, params: params
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong role', ''
|
||||||
|
it_behaves_like 'forbidden for wrong role', 'Moderator'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
post :create, params: params
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns the correct ip block' do
|
||||||
|
post :create, params: params
|
||||||
|
|
||||||
|
json = body_as_json
|
||||||
|
|
||||||
|
expect(json[:ip]).to eq("#{params[:ip]}/32")
|
||||||
|
expect(json[:severity]).to eq(params[:severity])
|
||||||
|
expect(json[:comment]).to eq(params[:comment])
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when ip is not provided' do
|
||||||
|
let(:params) { { ip: '', severity: 'no_access' } }
|
||||||
|
|
||||||
|
it 'returns http unprocessable entity' do
|
||||||
|
post :create, params: params
|
||||||
|
|
||||||
|
expect(response).to have_http_status(422)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when severity is not provided' do
|
||||||
|
let(:params) { { ip: '173.65.23.1', severity: '' } }
|
||||||
|
|
||||||
|
it 'returns http unprocessable entity' do
|
||||||
|
post :create, params: params
|
||||||
|
|
||||||
|
expect(response).to have_http_status(422)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when provided ip is already blocked' do
|
||||||
|
before do
|
||||||
|
IpBlock.create(params)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http unprocessable entity' do
|
||||||
|
post :create, params: params
|
||||||
|
|
||||||
|
expect(response).to have_http_status(422)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when provided ip address is invalid' do
|
||||||
|
let(:params) { { ip: '520.13.54.120', severity: 'no_access' } }
|
||||||
|
|
||||||
|
it 'returns http unprocessable entity' do
|
||||||
|
post :create, params: params
|
||||||
|
|
||||||
|
expect(response).to have_http_status(422)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'PUT #update' do
|
||||||
|
context 'when ip block exists' do
|
||||||
|
let!(:ip_block) { IpBlock.create(ip: '185.200.13.3', severity: 'no_access', comment: 'Spam', expires_in: 48.hours) }
|
||||||
|
let(:params) { { id: ip_block.id, severity: 'sign_up_requires_approval', comment: 'Decreasing severity' } }
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
put :update, params: params
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns the correct ip block' do
|
||||||
|
put :update, params: params
|
||||||
|
|
||||||
|
json = body_as_json
|
||||||
|
|
||||||
|
expect(json).to match(hash_including({
|
||||||
|
ip: "#{ip_block.ip}/#{ip_block.ip.prefix}",
|
||||||
|
severity: 'sign_up_requires_approval',
|
||||||
|
comment: 'Decreasing severity',
|
||||||
|
}))
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'updates the severity correctly' do
|
||||||
|
expect { put :update, params: params }.to change { ip_block.reload.severity }.from('no_access').to('sign_up_requires_approval')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'updates the comment correctly' do
|
||||||
|
expect { put :update, params: params }.to change { ip_block.reload.comment }.from('Spam').to('Decreasing severity')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when ip block does not exist' do
|
||||||
|
it 'returns http not found' do
|
||||||
|
put :update, params: { id: 0 }
|
||||||
|
|
||||||
|
expect(response).to have_http_status(404)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'DELETE #destroy' do
|
||||||
|
context 'when ip block exists' do
|
||||||
|
let!(:ip_block) { IpBlock.create(ip: '185.200.13.3', severity: 'no_access') }
|
||||||
|
let(:params) { { id: ip_block.id } }
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
delete :destroy, params: params
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns an empty body' do
|
||||||
|
delete :destroy, params: params
|
||||||
|
|
||||||
|
json = body_as_json
|
||||||
|
|
||||||
|
expect(json).to be_empty
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'deletes the ip block' do
|
||||||
|
delete :destroy, params: params
|
||||||
|
|
||||||
|
expect(IpBlock.find_by(id: ip_block.id)).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when ip block does not exist' do
|
||||||
|
it 'returns http not found' do
|
||||||
|
delete :destroy, params: { id: 0 }
|
||||||
|
|
||||||
|
expect(response).to have_http_status(404)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -129,7 +129,7 @@ describe ApplicationController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with request with unparseable Date header' do
|
context 'with request with unparsable Date header' do
|
||||||
before do
|
before do
|
||||||
get :success
|
get :success
|
||||||
|
|
||||||
|
|
|
@ -719,65 +719,180 @@ describe StatusesController do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when status is public' do
|
context 'when status is public' do
|
||||||
pending
|
before do
|
||||||
|
status.update(visibility: :public)
|
||||||
|
get :activity, params: { account_username: account.username, id: status.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(:success)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when status is private' do
|
context 'when status is private' do
|
||||||
pending
|
before do
|
||||||
|
status.update(visibility: :private)
|
||||||
|
get :activity, params: { account_username: account.username, id: status.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http not_found' do
|
||||||
|
expect(response).to have_http_status(404)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when status is direct' do
|
context 'when status is direct' do
|
||||||
pending
|
before do
|
||||||
|
status.update(visibility: :direct)
|
||||||
|
get :activity, params: { account_username: account.username, id: status.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http not_found' do
|
||||||
|
expect(response).to have_http_status(404)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when signed-in' do
|
context 'when signed-in' do
|
||||||
|
let(:user) { Fabricate(:user) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
sign_in(user)
|
||||||
|
end
|
||||||
|
|
||||||
context 'when status is public' do
|
context 'when status is public' do
|
||||||
pending
|
before do
|
||||||
|
status.update(visibility: :public)
|
||||||
|
get :activity, params: { account_username: account.username, id: status.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(:success)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when status is private' do
|
context 'when status is private' do
|
||||||
|
before do
|
||||||
|
status.update(visibility: :private)
|
||||||
|
end
|
||||||
|
|
||||||
context 'when user is authorized to see it' do
|
context 'when user is authorized to see it' do
|
||||||
pending
|
before do
|
||||||
|
user.account.follow!(account)
|
||||||
|
get :activity, params: { account_username: account.username, id: status.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when user is not authorized to see it' do
|
context 'when user is not authorized to see it' do
|
||||||
pending
|
before do
|
||||||
|
get :activity, params: { account_username: account.username, id: status.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http not_found' do
|
||||||
|
expect(response).to have_http_status(404)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when status is direct' do
|
context 'when status is direct' do
|
||||||
|
before do
|
||||||
|
status.update(visibility: :direct)
|
||||||
|
end
|
||||||
|
|
||||||
context 'when user is authorized to see it' do
|
context 'when user is authorized to see it' do
|
||||||
pending
|
before do
|
||||||
|
Fabricate(:mention, account: user.account, status: status)
|
||||||
|
get :activity, params: { account_username: account.username, id: status.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when user is not authorized to see it' do
|
context 'when user is not authorized to see it' do
|
||||||
pending
|
before do
|
||||||
|
get :activity, params: { account_username: account.username, id: status.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http not_found' do
|
||||||
|
expect(response).to have_http_status(404)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with signature' do
|
context 'with signature' do
|
||||||
|
let(:remote_account) { Fabricate(:account, domain: 'example.com') }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(controller).to receive(:signed_request_actor).and_return(remote_account)
|
||||||
|
end
|
||||||
|
|
||||||
context 'when status is public' do
|
context 'when status is public' do
|
||||||
pending
|
before do
|
||||||
|
status.update(visibility: :public)
|
||||||
|
get :activity, params: { account_username: account.username, id: status.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(:success)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when status is private' do
|
context 'when status is private' do
|
||||||
|
before do
|
||||||
|
status.update(visibility: :private)
|
||||||
|
end
|
||||||
|
|
||||||
context 'when user is authorized to see it' do
|
context 'when user is authorized to see it' do
|
||||||
pending
|
before do
|
||||||
|
remote_account.follow!(account)
|
||||||
|
get :activity, params: { account_username: account.username, id: status.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when user is not authorized to see it' do
|
context 'when user is not authorized to see it' do
|
||||||
pending
|
before do
|
||||||
|
get :activity, params: { account_username: account.username, id: status.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http not_found' do
|
||||||
|
expect(response).to have_http_status(404)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when status is direct' do
|
context 'when status is direct' do
|
||||||
|
before do
|
||||||
|
status.update(visibility: :direct)
|
||||||
|
end
|
||||||
|
|
||||||
context 'when user is authorized to see it' do
|
context 'when user is authorized to see it' do
|
||||||
pending
|
before do
|
||||||
|
Fabricate(:mention, account: remote_account, status: status)
|
||||||
|
get :activity, params: { account_username: account.username, id: status.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when user is not authorized to see it' do
|
context 'when user is not authorized to see it' do
|
||||||
pending
|
before do
|
||||||
|
get :activity, params: { account_username: account.username, id: status.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http not_found' do
|
||||||
|
expect(response).to have_http_status(404)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
Fabricator(:canonical_email_block) do
|
Fabricator(:canonical_email_block) do
|
||||||
email 'test@example.com'
|
email { sequence(:email) { |i| "#{i}#{Faker::Internet.email}" } }
|
||||||
reference_account { Fabricate(:account) }
|
reference_account { Fabricate(:account) }
|
||||||
end
|
end
|
||||||
|
|
|
@ -39,6 +39,37 @@ RSpec.describe ActivityPub::Activity::Flag do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when the report comment is excessively long' do
|
||||||
|
subject do
|
||||||
|
described_class.new({
|
||||||
|
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||||
|
id: flag_id,
|
||||||
|
type: 'Flag',
|
||||||
|
content: long_comment,
|
||||||
|
actor: ActivityPub::TagManager.instance.uri_for(sender),
|
||||||
|
object: [
|
||||||
|
ActivityPub::TagManager.instance.uri_for(flagged),
|
||||||
|
ActivityPub::TagManager.instance.uri_for(status),
|
||||||
|
],
|
||||||
|
}.with_indifferent_access, sender)
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:long_comment) { Faker::Lorem.characters(number: 6000) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
subject.perform
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'creates a report but with a truncated comment' do
|
||||||
|
report = Report.find_by(account: sender, target_account: flagged)
|
||||||
|
|
||||||
|
expect(report).to_not be_nil
|
||||||
|
expect(report.comment.length).to eq 5000
|
||||||
|
expect(report.comment).to eq long_comment[0...5000]
|
||||||
|
expect(report.status_ids).to eq [status.id]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'when the reported status is private and should not be visible to the remote server' do
|
context 'when the reported status is private and should not be visible to the remote server' do
|
||||||
let(:status) { Fabricate(:status, account: flagged, uri: 'foobar', visibility: :private) }
|
let(:status) { Fabricate(:status, account: flagged, uri: 'foobar', visibility: :private) }
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
require 'mastodon/migration_warning'
|
||||||
|
|
||||||
|
describe Mastodon::MigrationWarning do
|
||||||
|
describe 'migration_duration_warning' do
|
||||||
|
before do
|
||||||
|
allow(migration).to receive(:valid_environment?).and_return(true)
|
||||||
|
allow(migration).to receive(:sleep).with(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:migration) { Class.new(ActiveRecord::Migration[6.1]).extend(described_class) }
|
||||||
|
|
||||||
|
context 'with the default message' do
|
||||||
|
it 'warns about long migrations' do
|
||||||
|
expectation = expect { migration.migration_duration_warning }
|
||||||
|
|
||||||
|
expectation.to output(/interrupt this migration/).to_stdout
|
||||||
|
expectation.to output(/Continuing in 5/).to_stdout
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with an additional message' do
|
||||||
|
it 'warns about long migrations' do
|
||||||
|
expectation = expect { migration.migration_duration_warning('Get ready for it') }
|
||||||
|
|
||||||
|
expectation.to output(/interrupt this migration/).to_stdout
|
||||||
|
expectation.to output(/Get ready for it/).to_stdout
|
||||||
|
expectation.to output(/Continuing in 5/).to_stdout
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -25,7 +25,7 @@ RSpec.describe AccountMigration do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with unresolveable account' do
|
context 'with unresolvable account' do
|
||||||
let(:target_acct) { 'target@remote' }
|
let(:target_acct) { 'target@remote' }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
|
|
|
@ -698,7 +698,7 @@ RSpec.describe Account do
|
||||||
expect(subject.match('Check this out https://medium.com/@alice/some-article#.abcdef123')).to be_nil
|
expect(subject.match('Check this out https://medium.com/@alice/some-article#.abcdef123')).to be_nil
|
||||||
end
|
end
|
||||||
|
|
||||||
xit 'does not match URL querystring' do
|
xit 'does not match URL query string' do
|
||||||
expect(subject.match('https://example.com/?x=@alice')).to be_nil
|
expect(subject.match('https://example.com/?x=@alice')).to be_nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -121,10 +121,17 @@ describe Report do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'validations' do
|
describe 'validations' do
|
||||||
it 'is invalid if comment is longer than 1000 characters' do
|
let(:remote_account) { Fabricate(:account, domain: 'example.com', protocol: :activitypub, inbox_url: 'http://example.com/inbox') }
|
||||||
|
|
||||||
|
it 'is invalid if comment is longer than 1000 characters only if reporter is local' do
|
||||||
report = Fabricate.build(:report, comment: Faker::Lorem.characters(number: 1001))
|
report = Fabricate.build(:report, comment: Faker::Lorem.characters(number: 1001))
|
||||||
report.valid?
|
expect(report.valid?).to be false
|
||||||
expect(report).to model_have_error_on_field(:comment)
|
expect(report).to model_have_error_on_field(:comment)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'is valid if comment is longer than 1000 characters and reporter is not local' do
|
||||||
|
report = Fabricate.build(:report, account: remote_account, comment: Faker::Lorem.characters(number: 1001))
|
||||||
|
expect(report.valid?).to be true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -90,7 +90,7 @@ RSpec.describe UserSettings::Setting do
|
||||||
|
|
||||||
describe '#key' do
|
describe '#key' do
|
||||||
context 'when there is no namespace' do
|
context 'when there is no namespace' do
|
||||||
it 'returnsn a symbol' do
|
it 'returns a symbol' do
|
||||||
expect(subject.key).to eq :foo
|
expect(subject.key).to eq :foo
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -181,7 +181,7 @@ RSpec.describe ActivityPub::ProcessAccountService, type: :service do
|
||||||
'@context': ['https://www.w3.org/ns/activitystreams'],
|
'@context': ['https://www.w3.org/ns/activitystreams'],
|
||||||
id: "https://foo.test/users/#{i}/featured",
|
id: "https://foo.test/users/#{i}/featured",
|
||||||
type: 'OrderedCollection',
|
type: 'OrderedCollection',
|
||||||
totelItems: 1,
|
totalItems: 1,
|
||||||
orderedItems: [status_json],
|
orderedItems: [status_json],
|
||||||
}.with_indifferent_access
|
}.with_indifferent_access
|
||||||
webfinger = {
|
webfinger = {
|
||||||
|
|
|
@ -21,6 +21,27 @@ RSpec.describe BackupService, type: :service do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when the user has an avatar and header' do
|
||||||
|
before do
|
||||||
|
user.account.update!(avatar: attachment_fixture('avatar.gif'))
|
||||||
|
user.account.update!(header: attachment_fixture('emojo.png'))
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'stores them as expected' do
|
||||||
|
service_call
|
||||||
|
|
||||||
|
json = Oj.load(read_zip_file(backup, 'actor.json'))
|
||||||
|
avatar_path = json.dig('icon', 'url')
|
||||||
|
header_path = json.dig('image', 'url')
|
||||||
|
|
||||||
|
expect(avatar_path).to_not be_nil
|
||||||
|
expect(header_path).to_not be_nil
|
||||||
|
|
||||||
|
expect(read_zip_file(backup, avatar_path)).to be_present
|
||||||
|
expect(read_zip_file(backup, header_path)).to be_present
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
it 'marks the backup as processed' do
|
it 'marks the backup as processed' do
|
||||||
expect { service_call }.to change(backup, :processed).from(false).to(true)
|
expect { service_call }.to change(backup, :processed).from(false).to(true)
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,6 +6,14 @@ RSpec.describe ReportService, type: :service do
|
||||||
subject { described_class.new }
|
subject { described_class.new }
|
||||||
|
|
||||||
let(:source_account) { Fabricate(:account) }
|
let(:source_account) { Fabricate(:account) }
|
||||||
|
let(:target_account) { Fabricate(:account) }
|
||||||
|
|
||||||
|
context 'with a local account' do
|
||||||
|
it 'has a uri' do
|
||||||
|
report = subject.call(source_account, target_account)
|
||||||
|
expect(report.uri).to_not be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'with a remote account' do
|
context 'with a remote account' do
|
||||||
let(:remote_account) { Fabricate(:account, domain: 'example.com', protocol: :activitypub, inbox_url: 'http://example.com/inbox') }
|
let(:remote_account) { Fabricate(:account, domain: 'example.com', protocol: :activitypub, inbox_url: 'http://example.com/inbox') }
|
||||||
|
@ -35,7 +43,6 @@ RSpec.describe ReportService, type: :service do
|
||||||
-> { described_class.new.call(source_account, target_account, status_ids: [status.id]) }
|
-> { described_class.new.call(source_account, target_account, status_ids: [status.id]) }
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:target_account) { Fabricate(:account) }
|
|
||||||
let(:status) { Fabricate(:status, account: target_account, visibility: :direct) }
|
let(:status) { Fabricate(:status, account: target_account, visibility: :direct) }
|
||||||
|
|
||||||
context 'when it is addressed to the reporter' do
|
context 'when it is addressed to the reporter' do
|
||||||
|
@ -91,8 +98,7 @@ RSpec.describe ReportService, type: :service do
|
||||||
-> { described_class.new.call(source_account, target_account) }
|
-> { described_class.new.call(source_account, target_account) }
|
||||||
end
|
end
|
||||||
|
|
||||||
let!(:target_account) { Fabricate(:account) }
|
let!(:other_report) { Fabricate(:report, target_account: target_account) }
|
||||||
let!(:other_report) { Fabricate(:report, target_account: target_account) }
|
|
||||||
|
|
||||||
before do
|
before do
|
||||||
ActionMailer::Base.deliveries.clear
|
ActionMailer::Base.deliveries.clear
|
||||||
|
|
20
yarn.lock
20
yarn.lock
|
@ -2184,11 +2184,6 @@
|
||||||
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb"
|
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb"
|
||||||
integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==
|
integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==
|
||||||
|
|
||||||
"@types/raf@^3.4.0":
|
|
||||||
version "3.4.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/raf/-/raf-3.4.0.tgz#2b72cbd55405e071f1c4d29992638e022b20acc2"
|
|
||||||
integrity sha512-taW5/WYqo36N7V39oYyHP9Ipfd5pNFvGTIQsNGj86xV88YQ7GnI30/yMfKDF7Zgin0m3e+ikX88FvImnK4RjGw==
|
|
||||||
|
|
||||||
"@types/range-parser@*":
|
"@types/range-parser@*":
|
||||||
version "1.2.4"
|
version "1.2.4"
|
||||||
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc"
|
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc"
|
||||||
|
@ -2800,7 +2795,7 @@ acorn@^6.4.1:
|
||||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474"
|
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474"
|
||||||
integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==
|
integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==
|
||||||
|
|
||||||
acorn@^8.0.4, acorn@^8.1.0, acorn@^8.5.0, acorn@^8.8.0, acorn@^8.8.1, acorn@^8.8.2:
|
acorn@^8.0.4, acorn@^8.1.0, acorn@^8.5.0, acorn@^8.8.0, acorn@^8.8.1:
|
||||||
version "8.8.2"
|
version "8.8.2"
|
||||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a"
|
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a"
|
||||||
integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==
|
integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==
|
||||||
|
@ -7537,19 +7532,16 @@ jsdom@^20.0.0:
|
||||||
ws "^8.11.0"
|
ws "^8.11.0"
|
||||||
xml-name-validator "^4.0.0"
|
xml-name-validator "^4.0.0"
|
||||||
|
|
||||||
jsdom@^21.1.2:
|
jsdom@^22.0.0:
|
||||||
version "21.1.2"
|
version "22.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-21.1.2.tgz#6433f751b8718248d646af1cdf6662dc8a1ca7f9"
|
resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-22.0.0.tgz#3295c6992c70089c4b8f5cf060489fddf7ee9816"
|
||||||
integrity sha512-sCpFmK2jv+1sjff4u7fzft+pUh2KSUbUrEHYHyfSIbGTIcmnjyp83qg6qLwdJ/I3LpTXx33ACxeRL7Lsyc6lGQ==
|
integrity sha512-p5ZTEb5h+O+iU02t0GfEjAnkdYPrQSkfuTSMkMYyIoMvUNEHsbG0bHHbfXIcfTqD2UfvjQX7mmgiFsyRwGscVw==
|
||||||
dependencies:
|
dependencies:
|
||||||
abab "^2.0.6"
|
abab "^2.0.6"
|
||||||
acorn "^8.8.2"
|
|
||||||
acorn-globals "^7.0.0"
|
|
||||||
cssstyle "^3.0.0"
|
cssstyle "^3.0.0"
|
||||||
data-urls "^4.0.0"
|
data-urls "^4.0.0"
|
||||||
decimal.js "^10.4.3"
|
decimal.js "^10.4.3"
|
||||||
domexception "^4.0.0"
|
domexception "^4.0.0"
|
||||||
escodegen "^2.0.0"
|
|
||||||
form-data "^4.0.0"
|
form-data "^4.0.0"
|
||||||
html-encoding-sniffer "^3.0.0"
|
html-encoding-sniffer "^3.0.0"
|
||||||
http-proxy-agent "^5.0.0"
|
http-proxy-agent "^5.0.0"
|
||||||
|
@ -9520,7 +9512,7 @@ quick-lru@^4.0.1:
|
||||||
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f"
|
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f"
|
||||||
integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==
|
integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==
|
||||||
|
|
||||||
raf@^3.1.0, raf@^3.4.1:
|
raf@^3.1.0:
|
||||||
version "3.4.1"
|
version "3.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39"
|
resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39"
|
||||||
integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==
|
integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==
|
||||||
|
|
Loading…
Reference in New Issue