~cytrogen/masto-fe

6dbd44faea49ad44d26ee9fa9007ee0fca90dbbc — Claire 2 years ago a0bc061 + b896b16
Merge commit 'b896b16cb3c8626fbee12a7eda7f882114b1a040' into glitch-soc/merge-upstream
40 files changed, 228 insertions(+), 217 deletions(-)

M .rubocop.yml
M .rubocop_todo.yml
M app/controllers/api/v1/featured_tags_controller.rb
M app/controllers/media_controller.rb
M app/controllers/statuses_controller.rb
M app/helpers/application_helper.rb
M app/javascript/mastodon/containers/media_container.jsx
M app/javascript/mastodon/features/interaction_modal/index.jsx
M app/javascript/mastodon/features/ui/components/header.jsx
M app/javascript/mastodon/features/ui/components/sign_in_banner.jsx
M app/models/identity.rb
M app/serializers/rest/instance_serializer.rb
M bin/tootctl
R lib/mastodon/{accounts_cli => cli/accounts}.rb
R lib/mastodon/{cache_cli => cli/cache}.rb
R lib/mastodon/{canonical_email_blocks_cli => cli/canonical_email_blocks}.rb
R lib/mastodon/{domains_cli => cli/domains}.rb
R lib/mastodon/{email_domain_blocks_cli => cli/email_domain_blocks}.rb
R lib/mastodon/{emoji_cli => cli/emoji}.rb
R lib/mastodon/{feeds_cli => cli/feeds}.rb
R lib/mastodon/{cli_helper => cli/helper}.rb
R lib/mastodon/{ip_blocks_cli => cli/ip_blocks}.rb
R lib/{cli => mastodon/cli/main}.rb
R lib/mastodon/{maintenance_cli => cli/maintenance}.rb
R lib/mastodon/{media_cli => cli/media}.rb
R lib/mastodon/{preview_cards_cli => cli/preview_cards}.rb
R lib/mastodon/{search_cli => cli/search}.rb
R lib/mastodon/{settings_cli => cli/settings}.rb
R lib/mastodon/{statuses_cli => cli/statuses}.rb
R lib/mastodon/{upgrade_cli => cli/upgrade}.rb
M spec/controllers/api/v1/accounts/notes_controller_spec.rb
M spec/controllers/api/v1/media_controller_spec.rb
M spec/controllers/settings/applications_controller_spec.rb
R spec/lib/mastodon/{ip_blocks_cli_spec => cli/ip_blocks_spec}.rb
R spec/lib/mastodon/{cli_spec => cli/main_spec}.rb
R spec/lib/mastodon/{settings_cli_spec => cli/settings_spec}.rb
M spec/lib/status_filter_spec.rb
M spec/models/user_spec.rb
A spec/requests/backups_spec.rb
M spec/services/post_status_service_spec.rb
M .rubocop.yml => .rubocop.yml +10 -11
@@ 43,7 43,7 @@ Layout/LineLength:
    - !ruby/regexp / \# .*$/
    - !ruby/regexp /^\# .*$/
  Exclude:
    - lib/**/*cli*.rb
    - 'lib/mastodon/cli/*.rb'
    - db/*migrate/**/*
    - db/seeds/**/*



@@ 57,7 57,7 @@ Lint/UselessAccessModifier:
# https://docs.rubocop.org/rubocop/cops_metrics.html#metricsabcsize
Metrics/AbcSize:
  Exclude:
    - 'lib/**/*cli*.rb'
    - 'lib/mastodon/cli/*.rb'
    - db/*migrate/**/*

# Reason: Some functions cannot be broken up, but others may be refactor candidates


@@ 66,7 66,7 @@ Metrics/BlockLength:
  CountAsOne: ['array', 'hash', 'heredoc', 'method_call']
  Exclude:
    - 'config/routes.rb'
    - 'lib/mastodon/*_cli.rb'
    - 'lib/mastodon/cli/*.rb'
    - 'lib/tasks/*.rake'
    - 'app/models/concerns/account_associations.rb'
    - 'app/models/concerns/account_interactions.rb'


@@ 95,14 95,14 @@ Metrics/BlockLength:
# https://docs.rubocop.org/rubocop/cops_metrics.html#metricsblocknesting
Metrics/BlockNesting:
  Exclude:
    - 'lib/mastodon/*_cli.rb'
    - 'lib/mastodon/cli/*.rb'

# Reason: Some Excluded files would be candidates for refactoring but not currently addressed
# https://docs.rubocop.org/rubocop/cops_metrics.html#metricsclasslength
Metrics/ClassLength:
  CountAsOne: ['array', 'hash', 'heredoc', 'method_call']
  Exclude:
    - 'lib/mastodon/*_cli.rb'
    - 'lib/mastodon/cli/*.rb'
    - 'app/controllers/admin/accounts_controller.rb'
    - 'app/controllers/api/base_controller.rb'
    - 'app/controllers/api/v1/admin/accounts_controller.rb'


@@ 146,7 146,7 @@ Metrics/ClassLength:
# https://docs.rubocop.org/rubocop/cops_metrics.html#metricscyclomaticcomplexity
Metrics/CyclomaticComplexity:
  Exclude:
    - lib/mastodon/*cli*.rb
    - lib/mastodon/cli/*.rb
    - db/*migrate/**/*

# Reason: Currently disabled in .rubocop_todo.yml


@@ 154,7 154,7 @@ Metrics/CyclomaticComplexity:
Metrics/MethodLength:
  CountAsOne: [array, heredoc]
  Exclude:
    - 'lib/mastodon/*_cli.rb'
    - 'lib/mastodon/cli/*.rb'

# Reason:
# https://docs.rubocop.org/rubocop/cops_metrics.html#metricsmodulelength


@@ 171,13 171,12 @@ Rails/FilePath:
Rails/HttpStatus:
  EnforcedStyle: numeric

# Reason: Allowed only in the `tootctl` CLI application code
# Reason: Allowed in `tootctl` CLI code and in boot ENV checker
# https://docs.rubocop.org/rubocop-rails/cops_rails.html#railsexit
Rails/Exit:
  Exclude:
    - 'lib/mastodon/*_cli.rb'
    - 'lib/mastodon/cli_helper.rb'
    - 'lib/cli.rb'
    - 'config/boot.rb'
    - 'lib/mastodon/cli/*.rb'

# Reason: Some single letter camel case files shouldn't be split
# https://docs.rubocop.org/rubocop-rspec/cops_rspec.html#rspecfilepath

M .rubocop_todo.yml => .rubocop_todo.yml +8 -29
@@ 396,12 396,6 @@ RSpec/ExpectChange:
    - 'spec/services/unsuspend_account_service_spec.rb'
    - 'spec/workers/scheduler/accounts_statuses_cleanup_scheduler_spec.rb'

RSpec/ExpectInHook:
  Exclude:
    - 'spec/controllers/api/v1/media_controller_spec.rb'
    - 'spec/controllers/settings/applications_controller_spec.rb'
    - 'spec/lib/status_filter_spec.rb'

# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: implicit, each, example


@@ 565,15 559,6 @@ RSpec/PendingWithoutReason:
  Exclude:
    - 'spec/models/account_spec.rb'

# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: Strict, EnforcedStyle, AllowedExplicitMatchers.
# SupportedStyles: inflected, explicit
RSpec/PredicateMatcher:
  Exclude:
    - 'spec/controllers/api/v1/accounts/notes_controller_spec.rb'
    - 'spec/models/user_spec.rb'
    - 'spec/services/post_status_service_spec.rb'

RSpec/StubbedMock:
  Exclude:
    - 'spec/controllers/api/base_controller_spec.rb'


@@ 716,12 701,6 @@ Rails/DuplicateAssociation:
    - 'app/serializers/activitypub/note_serializer.rb'

# Configuration parameters: Include.
# Include: app/**/*.rb, config/**/*.rb, lib/**/*.rb
Rails/Exit:
  Exclude:
    - 'config/boot.rb'

# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/HasAndBelongsToMany:
  Exclude:


@@ 855,9 834,9 @@ Rails/SkipsModelValidations:
    - 'db/post_migrate/20220617202502_migrate_roles.rb'
    - 'db/post_migrate/20221101190723_backfill_admin_action_logs.rb'
    - 'db/post_migrate/20221206114142_backfill_admin_action_logs_again.rb'
    - 'lib/cli.rb'
    - 'lib/mastodon/accounts_cli.rb'
    - 'lib/mastodon/maintenance_cli.rb'
    - 'lib/mastodon/cli/accounts.rb'
    - 'lib/mastodon/cli/main.rb'
    - 'lib/mastodon/cli/maintenance.rb'
    - 'spec/controllers/api/v1/admin/accounts_controller_spec.rb'
    - 'spec/lib/activitypub/activity/follow_spec.rb'
    - 'spec/services/follow_service_spec.rb'


@@ 939,7 918,7 @@ Rails/WhereExists:
    - 'app/validators/vote_validator.rb'
    - 'app/workers/move_worker.rb'
    - 'db/migrate/20190529143559_preserve_old_layout_for_existing_users.rb'
    - 'lib/mastodon/email_domain_blocks_cli.rb'
    - 'lib/mastodon/cli/email_domain_blocks.rb'
    - 'lib/tasks/tests.rake'
    - 'spec/controllers/api/v1/accounts/notes_controller_spec.rb'
    - 'spec/controllers/api/v1/tags_controller_spec.rb'


@@ 1001,7 980,7 @@ Style/FormatStringToken:
  Exclude:
    - 'app/models/privacy_policy.rb'
    - 'config/initializers/devise.rb'
    - 'lib/mastodon/maintenance_cli.rb'
    - 'lib/mastodon/cli/maintenance.rb'
    - 'lib/paperclip/color_extractor.rb'

# This cop supports unsafe autocorrection (--autocorrect-all).


@@ 1446,9 1425,9 @@ Style/GuardClause:
    - 'db/post_migrate/20220704024901_migrate_settings_to_user_roles.rb'
    - 'lib/devise/two_factor_ldap_authenticatable.rb'
    - 'lib/devise/two_factor_pam_authenticatable.rb'
    - 'lib/mastodon/accounts_cli.rb'
    - 'lib/mastodon/maintenance_cli.rb'
    - 'lib/mastodon/media_cli.rb'
    - 'lib/mastodon/cli/accounts.rb'
    - 'lib/mastodon/cli/maintenance.rb'
    - 'lib/mastodon/cli/media.rb'
    - 'lib/paperclip/attachment_extensions.rb'
    - 'lib/tasks/repo.rake'


M app/controllers/api/v1/featured_tags_controller.rb => app/controllers/api/v1/featured_tags_controller.rb +0 -4
@@ 31,8 31,4 @@ class Api::V1::FeaturedTagsController < Api::BaseController
  def set_featured_tags
    @featured_tags = current_account.featured_tags.order(statuses_count: :desc)
  end

  def featured_tag_params
    params.require(:name)
  end
end

M app/controllers/media_controller.rb => app/controllers/media_controller.rb +1 -1
@@ 46,7 46,7 @@ class MediaController < ApplicationController
  end

  def allow_iframing
    response.headers['X-Frame-Options'] = 'ALLOWALL'
    response.headers.delete('X-Frame-Options')
  end

  def set_pack

M app/controllers/statuses_controller.rb => app/controllers/statuses_controller.rb +1 -1
@@ 46,7 46,7 @@ class StatusesController < ApplicationController
    return not_found if @status.hidden? || @status.reblog?

    expires_in 180, public: true
    response.headers['X-Frame-Options'] = 'ALLOWALL'
    response.headers.delete('X-Frame-Options')

    render layout: 'embedded'
  end

M app/helpers/application_helper.rb => app/helpers/application_helper.rb +1 -1
@@ 52,7 52,7 @@ module ApplicationHelper
    if closed_registrations? || omniauth_only?
      'https://joinmastodon.org/#getting-started'
    else
      new_user_registration_path
      ENV.fetch('SSO_ACCOUNT_SIGN_UP', new_user_registration_path)
    end
  end


M app/javascript/mastodon/containers/media_container.jsx => app/javascript/mastodon/containers/media_container.jsx +8 -1
@@ 73,6 73,13 @@ export default class MediaContainer extends PureComponent {
  render () {
    const { locale, components } = this.props;

    let handleOpenVideo;

    // Don't offer to expand the video in a lightbox if we're in a frame
    if (window.self === window.top) {
      handleOpenVideo = this.handleOpenVideo;
    }

    return (
      <IntlProvider locale={locale} messages={messages}>
        <>


@@ 89,7 96,7 @@ export default class MediaContainer extends PureComponent {

              ...(componentName === 'Video' ? {
                componentIndex: i,
                onOpenVideo: this.handleOpenVideo,
                onOpenVideo: handleOpenVideo,
              } : {
                onOpenMedia: this.handleOpenMedia,
              }),

M app/javascript/mastodon/features/interaction_modal/index.jsx => app/javascript/mastodon/features/interaction_modal/index.jsx +4 -2
@@ 9,6 9,7 @@ import { openModal, closeModal } from 'mastodon/actions/modal';

const mapStateToProps = (state, { accountId }) => ({
  displayNameHtml: state.getIn(['accounts', accountId, 'display_name_html']),
  signupUrl: state.getIn(['server', 'server', 'registrations', 'url'], '/auth/sign_up'),
});

const mapDispatchToProps = (dispatch) => ({


@@ 81,6 82,7 @@ class InteractionModal extends PureComponent {
    url: PropTypes.string,
    type: PropTypes.oneOf(['reply', 'reblog', 'favourite', 'follow']),
    onSignupClick: PropTypes.func.isRequired,
    signupUrl: PropTypes.string.isRequired,
  };

  handleSignupClick = () => {


@@ 88,7 90,7 @@ class InteractionModal extends PureComponent {
  };

  render () {
    const { url, type, displayNameHtml } = this.props;
    const { url, type, displayNameHtml, signupUrl } = this.props;

    const name = <bdi dangerouslySetInnerHTML={{ __html: displayNameHtml }} />;



@@ 121,7 123,7 @@ class InteractionModal extends PureComponent {

    if (registrationsOpen) {
      signupButton = (
        <a href='/auth/sign_up' className='button button--block button-tertiary'>
        <a href={signupUrl} className='button button--block button-tertiary'>
          <FormattedMessage id='sign_in_banner.create_account' defaultMessage='Create account' />
        </a>
      );

M app/javascript/mastodon/features/ui/components/header.jsx => app/javascript/mastodon/features/ui/components/header.jsx +8 -3
@@ 16,6 16,10 @@ const Account = connect(state => ({
  </Link>
));

const mapStateToProps = (state) => ({
  signupUrl: state.getIn(['server', 'server', 'registrations', 'url'], '/auth/sign_up'),
});

const mapDispatchToProps = (dispatch) => ({
  openClosedRegistrationsModal() {
    dispatch(openModal('CLOSED_REGISTRATIONS'));


@@ 31,11 35,12 @@ class Header extends PureComponent {
  static propTypes = {
    openClosedRegistrationsModal: PropTypes.func,
    location: PropTypes.object,
    signupUrl: PropTypes.string.isRequired,
  };

  render () {
    const { signedIn } = this.context.identity;
    const { location, openClosedRegistrationsModal } = this.props;
    const { location, openClosedRegistrationsModal, signupUrl } = this.props;

    let content;



@@ 51,7 56,7 @@ class Header extends PureComponent {

      if (registrationsOpen) {
        signupButton = (
          <a href='/auth/sign_up' className='button'>
          <a href={signupUrl} className='button'>
            <FormattedMessage id='sign_in_banner.create_account' defaultMessage='Create account' />
          </a>
        );


@@ 87,4 92,4 @@ class Header extends PureComponent {

}

export default withRouter(connect(null, mapDispatchToProps)(Header));
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Header));

M app/javascript/mastodon/features/ui/components/sign_in_banner.jsx => app/javascript/mastodon/features/ui/components/sign_in_banner.jsx +5 -3
@@ 1,11 1,11 @@
import { useCallback } from 'react';
import { FormattedMessage } from 'react-intl';
import { useDispatch } from 'react-redux';
import { useAppDispatch, useAppSelector } from 'mastodon/store';
import { registrationsOpen } from 'mastodon/initial_state';
import { openModal } from 'mastodon/actions/modal';

const SignInBanner = () => {
  const dispatch = useDispatch();
  const dispatch = useAppDispatch();

  const openClosedRegistrationsModal = useCallback(
    () => dispatch(openModal('CLOSED_REGISTRATIONS')),


@@ 14,9 14,11 @@ const SignInBanner = () => {

  let signupButton;

  const signupUrl = useAppSelector((state) => state.getIn(['server', 'server', 'registrations', 'url'], '/auth/sign_up'));

  if (registrationsOpen) {
    signupButton = (
      <a href='/auth/sign_up' className='button button--block'>
      <a href={signupUrl} className='button button--block'>
        <FormattedMessage id='sign_in_banner.create_account' defaultMessage='Create account' />
      </a>
    );

M app/models/identity.rb => app/models/identity.rb +1 -1
@@ 13,7 13,7 @@
#

class Identity < ApplicationRecord
  belongs_to :user, dependent: :destroy
  belongs_to :user
  validates :uid, presence: true, uniqueness: { scope: :provider }
  validates :provider, presence: true


M app/serializers/rest/instance_serializer.rb => app/serializers/rest/instance_serializer.rb +1 -0
@@ 86,6 86,7 @@ class REST::InstanceSerializer < ActiveModel::Serializer
      enabled: registrations_enabled?,
      approval_required: Setting.registrations_mode == 'approved',
      message: registrations_enabled? ? nil : registrations_message,
      url: ENV.fetch('SSO_ACCOUNT_SIGN_UP', nil),
    }
  end


M bin/tootctl => bin/tootctl +2 -2
@@ 2,11 2,11 @@
APP_PATH = File.expand_path('../config/application', __dir__)

require_relative '../config/boot'
require_relative '../lib/cli'
require_relative '../lib/mastodon/cli/main'

begin
  Chewy.strategy(:mastodon) do
    Mastodon::CLI.start(ARGV)
    Mastodon::CLI::Main.start(ARGV)
  end
rescue Interrupt
  exit(130)

R lib/mastodon/accounts_cli.rb => lib/mastodon/cli/accounts.rb +6 -6
@@ 1,13 1,13 @@
# frozen_string_literal: true

require 'set'
require_relative '../../config/boot'
require_relative '../../config/environment'
require_relative 'cli_helper'
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'

module Mastodon
  class AccountsCLI < Thor
    include CLIHelper
module Mastodon::CLI
  class Accounts < Thor
    include Helper

    def self.exit_on_failure?
      true

R lib/mastodon/cache_cli.rb => lib/mastodon/cli/cache.rb +6 -6
@@ 1,12 1,12 @@
# frozen_string_literal: true

require_relative '../../config/boot'
require_relative '../../config/environment'
require_relative 'cli_helper'
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'

module Mastodon
  class CacheCLI < Thor
    include CLIHelper
module Mastodon::CLI
  class Cache < Thor
    include Helper

    def self.exit_on_failure?
      true

R lib/mastodon/canonical_email_blocks_cli.rb => lib/mastodon/cli/canonical_email_blocks.rb +6 -6
@@ 1,13 1,13 @@
# frozen_string_literal: true

require 'concurrent'
require_relative '../../config/boot'
require_relative '../../config/environment'
require_relative 'cli_helper'
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'

module Mastodon
  class CanonicalEmailBlocksCLI < Thor
    include CLIHelper
module Mastodon::CLI
  class CanonicalEmailBlocks < Thor
    include Helper

    def self.exit_on_failure?
      true

R lib/mastodon/domains_cli.rb => lib/mastodon/cli/domains.rb +6 -6
@@ 1,13 1,13 @@
# frozen_string_literal: true

require 'concurrent'
require_relative '../../config/boot'
require_relative '../../config/environment'
require_relative 'cli_helper'
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'

module Mastodon
  class DomainsCLI < Thor
    include CLIHelper
module Mastodon::CLI
  class Domains < Thor
    include Helper

    def self.exit_on_failure?
      true

R lib/mastodon/email_domain_blocks_cli.rb => lib/mastodon/cli/email_domain_blocks.rb +6 -6
@@ 1,13 1,13 @@
# frozen_string_literal: true

require 'concurrent'
require_relative '../../config/boot'
require_relative '../../config/environment'
require_relative 'cli_helper'
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'

module Mastodon
  class EmailDomainBlocksCLI < Thor
    include CLIHelper
module Mastodon::CLI
  class EmailDomainBlocks < Thor
    include Helper

    def self.exit_on_failure?
      true

R lib/mastodon/emoji_cli.rb => lib/mastodon/cli/emoji.rb +5 -5
@@ 1,12 1,12 @@
# frozen_string_literal: true

require 'rubygems/package'
require_relative '../../config/boot'
require_relative '../../config/environment'
require_relative 'cli_helper'
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'

module Mastodon
  class EmojiCLI < Thor
module Mastodon::CLI
  class Emoji < Thor
    def self.exit_on_failure?
      true
    end

R lib/mastodon/feeds_cli.rb => lib/mastodon/cli/feeds.rb +6 -6
@@ 1,12 1,12 @@
# frozen_string_literal: true

require_relative '../../config/boot'
require_relative '../../config/environment'
require_relative 'cli_helper'
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'

module Mastodon
  class FeedsCLI < Thor
    include CLIHelper
module Mastodon::CLI
  class Feeds < Thor
    include Helper
    include Redisable

    def self.exit_on_failure?

R lib/mastodon/cli_helper.rb => lib/mastodon/cli/helper.rb +2 -2
@@ 9,8 9,8 @@ HttpLog.configuration.logger = dev_null
Paperclip.options[:log]      = false
Chewy.logger                 = dev_null

module Mastodon
  module CLIHelper
module Mastodon::CLI
  module Helper
    def dry_run?
      options[:dry_run]
    end

R lib/mastodon/ip_blocks_cli.rb => lib/mastodon/cli/ip_blocks.rb +5 -5
@@ 1,12 1,12 @@
# frozen_string_literal: true

require 'rubygems/package'
require_relative '../../config/boot'
require_relative '../../config/environment'
require_relative 'cli_helper'
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'

module Mastodon
  class IpBlocksCLI < Thor
module Mastodon::CLI
  class IpBlocks < Thor
    def self.exit_on_failure?
      true
    end

R lib/cli.rb => lib/mastodon/cli/main.rb +34 -34
@@ 1,73 1,73 @@
# frozen_string_literal: true

require 'thor'
require_relative 'mastodon/media_cli'
require_relative 'mastodon/emoji_cli'
require_relative 'mastodon/accounts_cli'
require_relative 'mastodon/feeds_cli'
require_relative 'mastodon/search_cli'
require_relative 'mastodon/settings_cli'
require_relative 'mastodon/statuses_cli'
require_relative 'mastodon/domains_cli'
require_relative 'mastodon/preview_cards_cli'
require_relative 'mastodon/cache_cli'
require_relative 'mastodon/upgrade_cli'
require_relative 'mastodon/email_domain_blocks_cli'
require_relative 'mastodon/canonical_email_blocks_cli'
require_relative 'mastodon/ip_blocks_cli'
require_relative 'mastodon/maintenance_cli'
require_relative 'mastodon/version'

module Mastodon
  class CLI < Thor
require_relative 'media'
require_relative 'emoji'
require_relative 'accounts'
require_relative 'feeds'
require_relative 'search'
require_relative 'settings'
require_relative 'statuses'
require_relative 'domains'
require_relative 'preview_cards'
require_relative 'cache'
require_relative 'upgrade'
require_relative 'email_domain_blocks'
require_relative 'canonical_email_blocks'
require_relative 'ip_blocks'
require_relative 'maintenance'
require_relative '../version'

module Mastodon::CLI
  class Main < Thor
    def self.exit_on_failure?
      true
    end

    desc 'media SUBCOMMAND ...ARGS', 'Manage media files'
    subcommand 'media', Mastodon::MediaCLI
    subcommand 'media', Media

    desc 'emoji SUBCOMMAND ...ARGS', 'Manage custom emoji'
    subcommand 'emoji', Mastodon::EmojiCLI
    subcommand 'emoji', Emoji

    desc 'accounts SUBCOMMAND ...ARGS', 'Manage accounts'
    subcommand 'accounts', Mastodon::AccountsCLI
    subcommand 'accounts', Accounts

    desc 'feeds SUBCOMMAND ...ARGS', 'Manage feeds'
    subcommand 'feeds', Mastodon::FeedsCLI
    subcommand 'feeds', Feeds

    desc 'search SUBCOMMAND ...ARGS', 'Manage the search engine'
    subcommand 'search', Mastodon::SearchCLI
    subcommand 'search', Search

    desc 'settings SUBCOMMAND ...ARGS', 'Manage dynamic settings'
    subcommand 'settings', Mastodon::SettingsCLI
    subcommand 'settings', Settings

    desc 'statuses SUBCOMMAND ...ARGS', 'Manage statuses'
    subcommand 'statuses', Mastodon::StatusesCLI
    subcommand 'statuses', Statuses

    desc 'domains SUBCOMMAND ...ARGS', 'Manage account domains'
    subcommand 'domains', Mastodon::DomainsCLI
    subcommand 'domains', Domains

    desc 'preview_cards SUBCOMMAND ...ARGS', 'Manage preview cards'
    subcommand 'preview_cards', Mastodon::PreviewCardsCLI
    subcommand 'preview_cards', PreviewCards

    desc 'cache SUBCOMMAND ...ARGS', 'Manage cache'
    subcommand 'cache', Mastodon::CacheCLI
    subcommand 'cache', Cache

    desc 'upgrade SUBCOMMAND ...ARGS', 'Various version upgrade utilities'
    subcommand 'upgrade', Mastodon::UpgradeCLI
    subcommand 'upgrade', Upgrade

    desc 'email_domain_blocks SUBCOMMAND ...ARGS', 'Manage e-mail domain blocks'
    subcommand 'email_domain_blocks', Mastodon::EmailDomainBlocksCLI
    subcommand 'email_domain_blocks', EmailDomainBlocks

    desc 'ip_blocks SUBCOMMAND ...ARGS', 'Manage IP blocks'
    subcommand 'ip_blocks', Mastodon::IpBlocksCLI
    subcommand 'ip_blocks', IpBlocks

    desc 'canonical_email_blocks SUBCOMMAND ...ARGS', 'Manage canonical e-mail blocks'
    subcommand 'canonical_email_blocks', Mastodon::CanonicalEmailBlocksCLI
    subcommand 'canonical_email_blocks', CanonicalEmailBlocks

    desc 'maintenance SUBCOMMAND ...ARGS', 'Various maintenance utilities'
    subcommand 'maintenance', Mastodon::MaintenanceCLI
    subcommand 'maintenance', Maintenance

    option :dry_run, type: :boolean
    desc 'self-destruct', 'Erase the server from the federation'

R lib/mastodon/maintenance_cli.rb => lib/mastodon/cli/maintenance.rb +6 -6
@@ 1,13 1,13 @@
# frozen_string_literal: true

require 'tty-prompt'
require_relative '../../config/boot'
require_relative '../../config/environment'
require_relative 'cli_helper'
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'

module Mastodon
  class MaintenanceCLI < Thor
    include CLIHelper
module Mastodon::CLI
  class Maintenance < Thor
    include Helper

    def self.exit_on_failure?
      true

R lib/mastodon/media_cli.rb => lib/mastodon/cli/media.rb +6 -6
@@ 1,13 1,13 @@
# frozen_string_literal: true

require_relative '../../config/boot'
require_relative '../../config/environment'
require_relative 'cli_helper'
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'

module Mastodon
  class MediaCLI < Thor
module Mastodon::CLI
  class Media < Thor
    include ActionView::Helpers::NumberHelper
    include CLIHelper
    include Helper

    VALID_PATH_SEGMENTS_SIZE = [7, 10].freeze


R lib/mastodon/preview_cards_cli.rb => lib/mastodon/cli/preview_cards.rb +6 -6
@@ 1,14 1,14 @@
# frozen_string_literal: true

require 'tty-prompt'
require_relative '../../config/boot'
require_relative '../../config/environment'
require_relative 'cli_helper'
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'

module Mastodon
  class PreviewCardsCLI < Thor
module Mastodon::CLI
  class PreviewCards < Thor
    include ActionView::Helpers::NumberHelper
    include CLIHelper
    include Helper

    def self.exit_on_failure?
      true

R lib/mastodon/search_cli.rb => lib/mastodon/cli/search.rb +6 -6
@@ 1,12 1,12 @@
# frozen_string_literal: true

require_relative '../../config/boot'
require_relative '../../config/environment'
require_relative 'cli_helper'
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'

module Mastodon
  class SearchCLI < Thor
    include CLIHelper
module Mastodon::CLI
  class Search < Thor
    include Helper

    # Indices are sorted by amount of data to be expected in each, so that
    # smaller indices can go online sooner

R lib/mastodon/settings_cli.rb => lib/mastodon/cli/settings.rb +7 -7
@@ 1,11 1,11 @@
# frozen_string_literal: true

require_relative '../../config/boot'
require_relative '../../config/environment'
require_relative 'cli_helper'
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'

module Mastodon
  class RegistrationsCLI < Thor
module Mastodon::CLI
  class Registrations < Thor
    def self.exit_on_failure?
      true
    end


@@ 37,8 37,8 @@ module Mastodon
    end
  end

  class SettingsCLI < Thor
  class Settings < Thor
    desc 'registrations SUBCOMMAND ...ARGS', 'Manage state of registrations'
    subcommand 'registrations', RegistrationsCLI
    subcommand 'registrations', Registrations
  end
end

R lib/mastodon/statuses_cli.rb => lib/mastodon/cli/statuses.rb +6 -6
@@ 1,12 1,12 @@
# frozen_string_literal: true

require_relative '../../config/boot'
require_relative '../../config/environment'
require_relative 'cli_helper'
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'

module Mastodon
  class StatusesCLI < Thor
    include CLIHelper
module Mastodon::CLI
  class Statuses < Thor
    include Helper
    include ActionView::Helpers::NumberHelper

    def self.exit_on_failure?

R lib/mastodon/upgrade_cli.rb => lib/mastodon/cli/upgrade.rb +6 -6
@@ 1,12 1,12 @@
# frozen_string_literal: true

require_relative '../../config/boot'
require_relative '../../config/environment'
require_relative 'cli_helper'
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'

module Mastodon
  class UpgradeCLI < Thor
    include CLIHelper
module Mastodon::CLI
  class Upgrade < Thor
    include Helper

    def self.exit_on_failure?
      true

M spec/controllers/api/v1/accounts/notes_controller_spec.rb => spec/controllers/api/v1/accounts/notes_controller_spec.rb +1 -1
@@ 43,7 43,7 @@ describe Api::V1::Accounts::NotesController do

      it 'does not create account note' do
        subject
        expect(AccountNote.where(account_id: user.account.id, target_account_id: account.id).exists?).to be_falsey
        expect(AccountNote.where(account_id: user.account.id, target_account_id: account.id)).to_not exist
      end
    end
  end

M spec/controllers/api/v1/media_controller_spec.rb => spec/controllers/api/v1/media_controller_spec.rb +2 -6
@@ 15,23 15,19 @@ RSpec.describe Api::V1::MediaController do
  describe 'POST #create' do
    describe 'with paperclip errors' do
      context 'when imagemagick cant identify the file type' do
        before do
        it 'returns http 422' do
          expect_any_instance_of(Account).to receive_message_chain(:media_attachments, :create!).and_raise(Paperclip::Errors::NotIdentifiedByImageMagickError)
          post :create, params: { file: fixture_file_upload('attachment.jpg', 'image/jpeg') }
        end

        it 'returns http 422' do
          expect(response).to have_http_status(422)
        end
      end

      context 'when there is a generic error' do
        before do
        it 'returns http 422' do
          expect_any_instance_of(Account).to receive_message_chain(:media_attachments, :create!).and_raise(Paperclip::Error)
          post :create, params: { file: fixture_file_upload('attachment.jpg', 'image/jpeg') }
        end

        it 'returns http 422' do
          expect(response).to have_http_status(500)
        end
      end

M spec/controllers/settings/applications_controller_spec.rb => spec/controllers/settings/applications_controller_spec.rb +1 -3
@@ 182,12 182,10 @@ describe Settings::ApplicationsController do
  describe 'regenerate' do
    let(:token) { user.token_for_app(app) }

    before do
    it 'creates new token' do
      expect(token).to_not be_nil
      post :regenerate, params: { id: app.id }
    end

    it 'creates new token' do
      expect(user.token_for_app(app)).to_not eql(token)
    end
  end

R spec/lib/mastodon/ip_blocks_cli_spec.rb => spec/lib/mastodon/cli/ip_blocks_spec.rb +2 -2
@@ 1,9 1,9 @@
# frozen_string_literal: true

require 'rails_helper'
require 'mastodon/ip_blocks_cli'
require 'mastodon/cli/ip_blocks'

RSpec.describe Mastodon::IpBlocksCLI do
RSpec.describe Mastodon::CLI::IpBlocks do
  let(:cli) { described_class.new }

  describe '#add' do

R spec/lib/mastodon/cli_spec.rb => spec/lib/mastodon/cli/main_spec.rb +2 -2
@@ 1,9 1,9 @@
# frozen_string_literal: true

require 'rails_helper'
require 'cli'
require 'mastodon/cli/main'

describe Mastodon::CLI do
describe Mastodon::CLI::Main do
  describe 'version' do
    it 'returns the Mastodon version' do
      expect { described_class.new.invoke(:version) }.to output(

R spec/lib/mastodon/settings_cli_spec.rb => spec/lib/mastodon/cli/settings_spec.rb +3 -3
@@ 1,11 1,11 @@
# frozen_string_literal: true

require 'rails_helper'
require 'mastodon/settings_cli'
require 'mastodon/cli/settings'

RSpec.describe Mastodon::SettingsCLI do
RSpec.describe Mastodon::CLI::Settings do
  describe 'subcommand "registrations"' do
    let(:cli) { Mastodon::RegistrationsCLI.new }
    let(:cli) { Mastodon::CLI::Registrations.new }

    before do
      Setting.registrations_mode = nil

M spec/lib/status_filter_spec.rb => spec/lib/status_filter_spec.rb +8 -8
@@ 7,7 7,7 @@ describe StatusFilter do
    let(:status) { Fabricate(:status) }

    context 'without an account' do
      subject { described_class.new(status, nil) }
      subject(:filter) { described_class.new(status, nil) }

      context 'when there are no connections' do
        it { is_expected.to_not be_filtered }


@@ 22,16 22,16 @@ describe StatusFilter do
      end

      context 'when status policy does not allow show' do
        before do
        it 'filters the status' do
          expect_any_instance_of(StatusPolicy).to receive(:show?).and_return(false)
        end

        it { is_expected.to be_filtered }
          expect(filter).to be_filtered
        end
      end
    end

    context 'with real account' do
      subject { described_class.new(status, account) }
      subject(:filter) { described_class.new(status, account) }

      let(:account) { Fabricate(:account) }



@@ 73,11 73,11 @@ describe StatusFilter do
      end

      context 'when status policy does not allow show' do
        before do
        it 'filters the status' do
          expect_any_instance_of(StatusPolicy).to receive(:show?).and_return(false)
        end

        it { is_expected.to be_filtered }
          expect(filter).to be_filtered
        end
      end
    end
  end

M spec/models/user_spec.rb => spec/models/user_spec.rb +7 -7
@@ 115,19 115,19 @@ RSpec.describe User do
    it 'allows a non-blacklisted user to be created' do
      user = User.new(email: 'foo@example.com', account: account, password: password, agreement: true)

      expect(user.valid?).to be_truthy
      expect(user).to be_valid
    end

    it 'does not allow a blacklisted user to be created' do
      user = User.new(email: 'foo@mvrht.com', account: account, password: password, agreement: true)

      expect(user.valid?).to be_falsey
      expect(user).to_not be_valid
    end

    it 'does not allow a subdomain blacklisted user to be created' do
      user = User.new(email: 'foo@mvrht.com.topdomain.tld', account: account, password: password, agreement: true)

      expect(user.valid?).to be_falsey
      expect(user).to_not be_valid
    end
  end



@@ 350,17 350,17 @@ RSpec.describe User do

    it 'does not allow a user to be created unless they are whitelisted' do
      user = User.new(email: 'foo@example.com', account: account, password: password, agreement: true)
      expect(user.valid?).to be_falsey
      expect(user).to_not be_valid
    end

    it 'allows a user to be created if they are whitelisted' do
      user = User.new(email: 'foo@mastodon.space', account: account, password: password, agreement: true)
      expect(user.valid?).to be_truthy
      expect(user).to be_valid
    end

    it 'does not allow a user with a whitelisted top domain as subdomain in their email address to be created' do
      user = User.new(email: 'foo@mastodon.space.userdomain.com', account: account, password: password, agreement: true)
      expect(user.valid?).to be_falsey
      expect(user).to_not be_valid
    end

    context do


@@ 374,7 374,7 @@ RSpec.describe User do
        Rails.configuration.x.email_domains_blacklist = 'blacklisted.mastodon.space'

        user = User.new(email: 'foo@blacklisted.mastodon.space', account: account, password: password)
        expect(user.valid?).to be_falsey
        expect(user).to_not be_valid
      end
    end
  end

A spec/requests/backups_spec.rb => spec/requests/backups_spec.rb +26 -0
@@ 0,0 1,26 @@
# frozen_string_literal: true

require 'rails_helper'

describe 'Backups' do
  include RoutingHelper

  describe 'GET backups#download' do
    let(:user) { Fabricate(:user) }
    let(:backup) { Fabricate(:backup, user: user) }

    before do
      sign_in user
    end

    it 'Downloads a user backup' do
      get download_backup_path(backup)

      expect(response).to redirect_to(backup_dump_url)
    end

    def backup_dump_url
      full_asset_url(backup.dump.url)
    end
  end
end

M spec/services/post_status_service_spec.rb => spec/services/post_status_service_spec.rb +1 -1
@@ 48,7 48,7 @@ RSpec.describe PostStatusService, type: :service do
      expect(status.params['text']).to eq 'Hi future!'
      expect(status.params['media_ids']).to eq [media.id]
      expect(media.reload.status).to be_nil
      expect(Status.where(text: 'Hi future!').exists?).to be_falsey
      expect(Status.where(text: 'Hi future!')).to_not exist
    end

    it 'does not change statuses count' do