~cytrogen/masto-fe

d7fcd70023d481cb6a53aef7a58dabfd6a2fa7b2 — Claire 2 years ago cfc0da7 + 2016c5d
Merge commit '2016c5d912f400ae98ee03ce269112de2f9ec62d' into glitch-soc/merge-upstream

Conflicts:
- `config/initializers/cors.rb`:
  Upstream refactored this file, and glitch-soc had local changes.
  I could not find the rationale for the glitch-soc changes, so I
  used upstream's version.
M .haml-lint_todo.yml => .haml-lint_todo.yml +4 -6
@@ 1,13 1,13 @@
# This configuration was generated by
# `haml-lint --auto-gen-config`
# on 2023-08-28 13:08:37 -0400 using Haml-Lint version 0.50.0.
# on 2023-09-28 10:26:23 -0400 using Haml-Lint version 0.50.0.
# The point is for the user to remove these configuration records
# one by one as the lints are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of Haml-Lint, may require this file to be generated again.

linters:
  # Offense count: 945
  # Offense count: 944
  LineLength:
    enabled: false



@@ 15,7 15,7 @@ linters:
  UnnecessaryStringOutput:
    enabled: false

  # Offense count: 57
  # Offense count: 59
  RuboCop:
    enabled: false



@@ 26,12 26,10 @@ linters:
      - 'app/views/admin/reports/show.html.haml'
      - 'app/views/disputes/strikes/show.html.haml'

  # Offense count: 28
  # Offense count: 18
  InstanceVariables:
    exclude:
      - 'app/views/admin/reports/_actions.html.haml'
      - 'app/views/admin/roles/_form.html.haml'
      - 'app/views/admin/webhooks/_form.html.haml'
      - 'app/views/auth/registrations/_status.html.haml'
      - 'app/views/auth/sessions/two_factor/_otp_authentication_form.html.haml'
      - 'app/views/relationships/_account.html.haml'

M .rubocop.yml => .rubocop.yml +0 -6
@@ 75,12 75,6 @@ Metrics/AbcSize:
    - 'lib/mastodon/cli/*.rb'
    - db/*migrate/**/*

# Reason:
# https://docs.rubocop.org/rubocop/cops_metrics.html#metricsblocknesting
Metrics/BlockNesting:
  Exclude:
    - 'lib/mastodon/cli/*.rb'

# Reason: Currently disabled in .rubocop_todo.yml
# https://docs.rubocop.org/rubocop/cops_metrics.html#metricscyclomaticcomplexity
Metrics/CyclomaticComplexity:

M .rubocop_todo.yml => .rubocop_todo.yml +0 -9
@@ 14,14 14,6 @@ Bundler/OrderedGems:
    - 'Gemfile'

# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: with_first_argument, with_fixed_indentation
Layout/ArgumentAlignment:
  Exclude:
    - 'config/initializers/cors.rb'
    - 'config/initializers/session_store.rb'

# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
# SupportedHashRocketStyles: key, separator, table
# SupportedColonStyles: key, separator, table


@@ 844,6 836,5 @@ Style/TrailingCommaInHashLiteral:
Style/WordArray:
  Exclude:
    - 'app/helpers/languages_helper.rb'
    - 'config/initializers/cors.rb'
    - 'spec/controllers/settings/imports_controller_spec.rb'
    - 'spec/models/form/import_spec.rb'

M Gemfile.lock => Gemfile.lock +1 -1
@@ 640,7 640,7 @@ GEM
      sidekiq (>= 5, < 8)
    rspec-support (3.12.1)
    rspec_chunked (0.6)
    rubocop (1.56.3)
    rubocop (1.56.4)
      base64 (~> 0.1.1)
      json (~> 2.3)
      language_server-protocol (>= 3.17.0)

M app/helpers/routing_helper.rb => app/helpers/routing_helper.rb +2 -1
@@ 3,11 3,12 @@
module RoutingHelper
  extend ActiveSupport::Concern

  include Rails.application.routes.url_helpers
  include ActionView::Helpers::AssetTagHelper
  include Webpacker::Helper

  included do
    include Rails.application.routes.url_helpers

    def default_url_options
      ActionMailer::Base.default_url_options
    end

M app/models/form/import.rb => app/models/form/import.rb +16 -8
@@ 43,14 43,14 @@ class Form::Import
  validate :validate_data

  def guessed_type
    return :muting if csv_data.headers.include?('Hide notifications')
    return :following if csv_data.headers.include?('Show boosts') || csv_data.headers.include?('Notify on new posts') || csv_data.headers.include?('Languages')
    return :following if data.original_filename&.start_with?('follows') || data.original_filename&.start_with?('following_accounts')
    return :blocking if data.original_filename&.start_with?('blocks') || data.original_filename&.start_with?('blocked_accounts')
    return :muting if data.original_filename&.start_with?('mutes') || data.original_filename&.start_with?('muted_accounts')
    return :domain_blocking if data.original_filename&.start_with?('domain_blocks') || data.original_filename&.start_with?('blocked_domains')
    return :bookmarks if data.original_filename&.start_with?('bookmarks')
    return :lists if data.original_filename&.start_with?('lists')
    return :muting if csv_headers_match?('Hide notifications')
    return :following if csv_headers_match?('Show boosts') || csv_headers_match?('Notify on new posts') || csv_headers_match?('Languages')
    return :following if file_name_matches?('follows') || file_name_matches?('following_accounts')
    return :blocking if file_name_matches?('blocks') || file_name_matches?('blocked_accounts')
    return :muting if file_name_matches?('mutes') || file_name_matches?('muted_accounts')
    return :domain_blocking if file_name_matches?('domain_blocks') || file_name_matches?('blocked_domains')
    return :bookmarks if file_name_matches?('bookmarks')
    return :lists if file_name_matches?('lists')
  end

  # Whether the uploaded CSV file seems to correspond to a different import type than the one selected


@@ 79,6 79,14 @@ class Form::Import

  private

  def file_name_matches?(string)
    data.original_filename&.start_with?(string)
  end

  def csv_headers_match?(string)
    csv_data.headers.include?(string)
  end

  def default_csv_headers
    case type.to_sym
    when :following, :blocking, :muting

M app/models/report_filter.rb => app/models/report_filter.rb +1 -1
@@ 19,7 19,7 @@ class ReportFilter
    scope = Report.unresolved

    params.each do |key, value|
      scope = scope.merge scope_for(key, value), rewhere: true
      scope = scope.merge scope_for(key, value)
    end

    scope

M app/views/admin/roles/_form.html.haml => app/views/admin/roles/_form.html.haml +24 -28
@@ 1,40 1,36 @@
= simple_form_for @role, url: @role.new_record? ? admin_roles_path : admin_role_path(@role) do |f|
  = render 'shared/error_messages', object: @role
= render 'shared/error_messages', object: form.object

  - if @role.everyone?
    .flash-message.info
      = t('admin.roles.everyone_full_description_html')
  - else
    .fields-group
      = f.input :name, wrapper: :with_label

    - unless current_user.role.id == @role.id
      .fields-group
        = f.input :position, wrapper: :with_label, input_html: { max: current_user.role.position - 1 }
- if form.object.everyone?
  .flash-message.info
    = t('admin.roles.everyone_full_description_html')
- else
  .fields-group
    = form.input :name, wrapper: :with_label

  - unless current_user.role == form.object
    .fields-group
      = f.input :color, wrapper: :with_label, input_html: { placeholder: '#000000', type: 'color' }
      = form.input :position, wrapper: :with_label, input_html: { max: current_user.role.position - 1 }

    %hr.spacer/
  .fields-group
    = form.input :color, wrapper: :with_label, input_html: { placeholder: '#000000', type: 'color' }

    .fields-group
      = f.input :highlighted, wrapper: :with_label
  %hr.spacer/

    %hr.spacer/
  .fields-group
    = form.input :highlighted, wrapper: :with_label

  - unless current_user.role.id == @role.id
  %hr.spacer/

    .field-group
      .input.with_block_label
        %label= t('simple_form.labels.user_role.permissions_as_keys')
        %span.hint= t('simple_form.hints.user_role.permissions_as_keys')
- unless current_user.role == form.object

      - (@role.everyone? ? UserRole::Flags::CATEGORIES.slice(:invites) : UserRole::Flags::CATEGORIES).each do |category, permissions|
        %h4= t(category, scope: 'admin.roles.categories')
  .field-group
    .input.with_block_label
      %label= t('simple_form.labels.user_role.permissions_as_keys')
      %span.hint= t('simple_form.hints.user_role.permissions_as_keys')

        = f.input :permissions_as_keys, collection: permissions, wrapper: :with_block_label, include_blank: false, label_method: ->(privilege) { safe_join([t("admin.roles.privileges.#{privilege}"), content_tag(:span, t("admin.roles.privileges.#{privilege}_description"), class: 'hint')]) }, required: false, as: :check_boxes, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li', label: false, hint: false, disabled: permissions.filter { |privilege| UserRole::FLAGS[privilege] & current_user.role.computed_permissions == 0 }
    - (form.object.everyone? ? UserRole::Flags::CATEGORIES.slice(:invites) : UserRole::Flags::CATEGORIES).each do |category, permissions|
      %h4= t(category, scope: 'admin.roles.categories')

    %hr.spacer/
      = form.input :permissions_as_keys, collection: permissions, wrapper: :with_block_label, include_blank: false, label_method: ->(privilege) { safe_join([t("admin.roles.privileges.#{privilege}"), content_tag(:span, t("admin.roles.privileges.#{privilege}_description"), class: 'hint')]) }, required: false, as: :check_boxes, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li', label: false, hint: false, disabled: permissions.filter { |privilege| UserRole::FLAGS[privilege] & current_user.role.computed_permissions == 0 }

  .actions
    = f.button :button, @role.new_record? ? t('admin.roles.add_new') : t('generic.save_changes'), type: :submit
  %hr.spacer/

M app/views/admin/roles/edit.html.haml => app/views/admin/roles/edit.html.haml +4 -1
@@ 4,4 4,7 @@
- content_for :heading_actions do
  = link_to t('admin.roles.delete'), admin_role_path(@role), method: :delete, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button button--destructive' if can?(:destroy, @role)

= render partial: 'form'
= simple_form_for @role, url: admin_role_path(@role) do |form|
  = render partial: 'form', object: form
  .actions
    = form.button :button, t('generic.save_changes'), type: :submit

M app/views/admin/roles/new.html.haml => app/views/admin/roles/new.html.haml +4 -1
@@ 1,4 1,7 @@
- content_for :page_title do
  = t('admin.roles.add_new')

= render partial: 'form'
= simple_form_for @role, url: admin_roles_path do |form|
  = render partial: 'form', object: form
  .actions
    = form.button :button, t('admin.roles.add_new'), type: :submit

M app/views/admin/webhooks/_form.html.haml => app/views/admin/webhooks/_form.html.haml +7 -11
@@ 1,14 1,10 @@
= simple_form_for @webhook, url: @webhook.new_record? ? admin_webhooks_path : admin_webhook_path(@webhook) do |f|
  = render 'shared/error_messages', object: @webhook
= render 'shared/error_messages', object: form.object

  .fields-group
    = f.input :url, wrapper: :with_block_label, input_html: { placeholder: 'https://' }
.fields-group
  = form.input :url, wrapper: :with_block_label, input_html: { placeholder: 'https://' }

  .fields-group
    = f.input :events, collection: Webhook::EVENTS, wrapper: :with_block_label, include_blank: false, as: :check_boxes, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li', disabled: Webhook::EVENTS.filter { |event| !current_user.role.can?(Webhook.permission_for_event(event)) }
.fields-group
  = form.input :events, collection: Webhook::EVENTS, wrapper: :with_block_label, include_blank: false, as: :check_boxes, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li', disabled: Webhook::EVENTS.filter { |event| !current_user.role.can?(Webhook.permission_for_event(event)) }

  .fields-group
    = f.input :template, wrapper: :with_block_label, input_html: { placeholder: '{ "content": "Hello {{object.username}}" }' }

  .actions
    = f.button :button, @webhook.new_record? ? t('admin.webhooks.add_new') : t('generic.save_changes'), type: :submit
.fields-group
  = form.input :template, wrapper: :with_block_label, input_html: { placeholder: '{ "content": "Hello {{object.username}}" }' }

M app/views/admin/webhooks/edit.html.haml => app/views/admin/webhooks/edit.html.haml +4 -1
@@ 1,4 1,7 @@
- content_for :page_title do
  = t('admin.webhooks.edit')

= render partial: 'form'
= simple_form_for @webhook, url: admin_webhook_path(@webhook) do |form|
  = render partial: 'form', object: form
  .actions
    = form.button :button, t('generic.save_changes'), type: :submit

M app/views/admin/webhooks/new.html.haml => app/views/admin/webhooks/new.html.haml +4 -1
@@ 1,4 1,7 @@
- content_for :page_title do
  = t('admin.webhooks.new')

= render partial: 'form'
= simple_form_for @webhook, url: admin_webhooks_path do |form|
  = render partial: 'form', object: form
  .actions
    = form.button :button, t('admin.webhooks.add_new'), type: :submit

M config/initializers/cors.rb => config/initializers/cors.rb +11 -25
@@ 11,30 11,16 @@ Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins '*'

    resource '/.well-known/*',
      headers: :any,
      methods: [:get],
      credentials: false
    resource '/@:username',
      headers: :any,
      methods: [:get],
      credentials: false
    resource '/users/:username',
      headers: :any,
      methods: [:get],
      credentials: false
    resource '/api/*',
      headers: :any,
      methods: [:post, :put, :delete, :get, :patch, :options],
      credentials: false,
      expose: ['Link', 'X-RateLimit-Reset', 'X-RateLimit-Limit', 'X-RateLimit-Remaining', 'X-Request-Id']
    resource '/oauth/token',
      headers: :any,
      methods: [:post],
      credentials: false
    resource '/assets/*', headers: :any, methods: [:get, :head, :options]
    resource '/stylesheets/*', headers: :any, methods: [:get, :head, :options]
    resource '/javascripts/*', headers: :any, methods: [:get, :head, :options]
    resource '/packs/*', headers: :any, methods: [:get, :head, :options]
    with_options headers: :any, credentials: false do
      with_options methods: [:get] do
        resource '/.well-known/*'
        resource '/@:username'
        resource '/users/:username'
      end
      resource '/api/*',
               expose: %w(Link X-RateLimit-Reset X-RateLimit-Limit X-RateLimit-Remaining X-Request-Id),
               methods: %i(post put delete get patch options)
      resource '/oauth/token', methods: [:post]
    end
  end
end

M config/initializers/session_store.rb => config/initializers/session_store.rb +7 -4
@@ 2,7 2,10 @@

# Be sure to restart your server when you modify this file.

Rails.application.config.session_store :cookie_store,
  key: '_mastodon_session',
  secure: false, # All cookies have their secure flag set by the force_ssl option in production
  same_site: :lax
Rails
  .application
  .config
  .session_store :cookie_store,
                 key: '_mastodon_session',
                 secure: false, # All cookies have their secure flag set by the force_ssl option in production
                 same_site: :lax

M lib/mastodon/cli/upgrade.rb => lib/mastodon/cli/upgrade.rb +25 -17
@@ 125,27 125,12 @@ module Mastodon::CLI
        progress.log("Moving #{previous_path} to #{upgraded_path}") if options[:verbose]

        begin
          unless dry_run?
            FileUtils.mkdir_p(File.dirname(upgraded_path))
            FileUtils.mv(previous_path, upgraded_path)

            begin
              FileUtils.rmdir(File.dirname(previous_path), parents: true)
            rescue Errno::ENOTEMPTY
              # OK
            end
          end
          move_previous_to_upgraded
        rescue => e
          progress.log(pastel.red("Error processing #{previous_path}: #{e}"))
          success = false

          unless dry_run?
            begin
              FileUtils.rmdir(File.dirname(upgraded_path), parents: true)
            rescue Errno::ENOTEMPTY
              # OK
            end
          end
          remove_directory
        end
      end



@@ 155,5 140,28 @@ module Mastodon::CLI
      attachment.instance_write(:storage_schema_version, previous_storage_schema_version)
      success
    end

    def move_previous_to_upgraded(previous_path, upgraded_path)
      return if dry_run?

      FileUtils.mkdir_p(File.dirname(upgraded_path))
      FileUtils.mv(previous_path, upgraded_path)

      begin
        FileUtils.rmdir(File.dirname(previous_path), parents: true)
      rescue Errno::ENOTEMPTY
        # OK
      end
    end

    def remove_directory(path)
      return if dry_run?

      begin
        FileUtils.rmdir(File.dirname(path), parents: true)
      rescue Errno::ENOTEMPTY
        # OK
      end
    end
  end
end