~cytrogen/masto-fe

ac2370778a0fa7bda53824384fe5e78e826765ce — Claire 2 years ago 74c27e3 + c676bc9
Merge commit 'c676bc91e9c3aa81eb7cfbce3c5c5e80b84d3d02' into glitch-soc/merge-upstream

Conflicts:
- `config/environments/production.rb`:
  Upstream enforced a code style change and glitch-soc had a few different lines.
  Applied upstream's code style to glitch-soc's changes.
M .haml-lint_todo.yml => .haml-lint_todo.yml +2 -2
@@ 1,6 1,6 @@
# This configuration was generated by
# `haml-lint --auto-gen-config`
# on 2023-09-28 10:42:25 -0400 using Haml-Lint version 0.50.0.
# on 2023-10-03 08:32:28 -0400 using Haml-Lint version 0.51.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


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

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


M .rubocop.yml => .rubocop.yml +1 -0
@@ 28,6 28,7 @@ AllCops:
    - 'Vagrantfile'
    - 'vendor/**/*'
    - 'lib/json_ld/*' # Generated files
    - 'lib/mastodon/migration_helpers.rb' # Vendored from GitLab
    - 'lib/templates/**/*'

# Reason: Prefer Hashes without extreme indentation

M .rubocop_todo.yml => .rubocop_todo.yml +0 -30
@@ 14,38 14,12 @@ Bundler/OrderedGems:
    - 'Gemfile'

# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
# SupportedHashRocketStyles: key, separator, table
# SupportedColonStyles: key, separator, table
# SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit
Layout/HashAlignment:
  Exclude:
    - 'config/environments/production.rb'
    - 'config/initializers/rack_attack.rb'
    - 'config/routes.rb'

# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowDoxygenCommentStyle, AllowGemfileRubyComment.
Layout/LeadingCommentSpace:
  Exclude:
    - 'config/application.rb'
    - 'config/initializers/3_omniauth.rb'

# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns.
# URISchemes: http, https
Layout/LineLength:
  Exclude:
    - 'app/models/account.rb'

# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: require_no_space, require_space
Layout/SpaceInLambdaLiteral:
  Exclude:
    - 'config/environments/production.rb'
    - 'config/initializers/content_security_policy.rb'

# Configuration parameters: AllowComments, AllowEmptyLambdas.
Lint/EmptyBlock:
  Exclude:


@@ 283,10 257,6 @@ RSpec/MultipleMemoizedHelpers:
RSpec/NestedGroups:
  Max: 6

RSpec/PendingWithoutReason:
  Exclude:
    - 'spec/models/account_spec.rb'

# This cop supports unsafe autocorrection (--autocorrect-all).
Rails/ApplicationController:
  Exclude:

A app/helpers/admin/announcements_helper.rb => app/helpers/admin/announcements_helper.rb +11 -0
@@ 0,0 1,11 @@
# frozen_string_literal: true

module Admin::AnnouncementsHelper
  def datetime_pattern
    '[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}(:[0-9]{2}){1,2}'
  end

  def datetime_placeholder
    Time.zone.now.strftime('%FT%R')
  end
end

M app/lib/admin/system_check/elasticsearch_check.rb => app/lib/admin/system_check/elasticsearch_check.rb +25 -4
@@ 76,14 76,35 @@ class Admin::SystemCheck::ElasticsearchCheck < Admin::SystemCheck::BaseCheck
  end

  def compatible_version?
    return false if running_version.nil?

    Gem::Version.new(running_version) >= Gem::Version.new(required_version) ||
      Gem::Version.new(compatible_wire_version) >= Gem::Version.new(required_version)
    running_version_ok? || compatible_wire_version_ok?
  rescue ArgumentError
    false
  end

  def running_version_ok?
    return false if running_version.blank?

    gem_version_running >= gem_version_required
  end

  def compatible_wire_version_ok?
    return false if compatible_wire_version.blank?

    gem_version_compatible_wire >= gem_version_required
  end

  def gem_version_running
    Gem::Version.new(running_version)
  end

  def gem_version_required
    Gem::Version.new(required_version)
  end

  def gem_version_compatible_wire
    Gem::Version.new(compatible_wire_version)
  end

  def mismatched_indexes
    @mismatched_indexes ||= INDEXES.filter_map do |klass|
      klass.base_name if Chewy.client.indices.get_mapping[klass.index_name]&.deep_symbolize_keys != klass.mappings_hash

M app/models/account.rb => app/models/account.rb +1 -1
@@ 66,7 66,7 @@ class Account < ApplicationRecord
  BACKGROUND_REFRESH_INTERVAL = 1.week.freeze

  USERNAME_RE   = /[a-z0-9_]+([a-z0-9_.-]+[a-z0-9_]+)?/i
  MENTION_RE    = %r{(?<=^|[^/[:word:]])@((#{USERNAME_RE})(?:@[[:word:].-]+[[:word:]]+)?)}i
  MENTION_RE    = %r{(?<![=/[:word:]])@((#{USERNAME_RE})(?:@[[:word:].-]+[[:word:]]+)?)}i
  URL_PREFIX_RE = %r{\Ahttp(s?)://[^/]+}
  USERNAME_ONLY_RE = /\A#{USERNAME_RE}\z/i


M app/views/admin/accounts/show.html.haml => app/views/admin/accounts/show.html.haml +1 -1
@@ 72,7 72,7 @@
      .dashboard__counters__label= t 'admin.accounts.login_status'

- if @account.local? && @account.user.nil?
  = link_to t('admin.accounts.unblock_email'), unblock_email_admin_account_path(@account.id), method: :post, class: 'button' if can?(:unblock_email, @account) && CanonicalEmailBlock.where(reference_account_id: @account.id).exists?
  = link_to t('admin.accounts.unblock_email'), unblock_email_admin_account_path(@account.id), method: :post, class: 'button' if can?(:unblock_email, @account) && CanonicalEmailBlock.exists?(reference_account_id: @account.id)
- else
  .table-wrapper
    %table.table.inline-table

M app/views/admin/announcements/edit.html.haml => app/views/admin/announcements/edit.html.haml +3 -3
@@ 5,8 5,8 @@
  = render 'shared/error_messages', object: @announcement

  .fields-group
    = f.input :starts_at, include_blank: true, wrapper: :with_block_label, html5: true, input_html: { pattern: '[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}(:[0-9]{2}){1,2}', placeholder: Time.now.strftime('%FT%R') }
    = f.input :ends_at, include_blank: true, wrapper: :with_block_label, html5: true, input_html: { pattern: '[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}(:[0-9]{2}){1,2}', placeholder: Time.now.strftime('%FT%R') }
    = f.input :starts_at, include_blank: true, wrapper: :with_block_label, html5: true, input_html: { pattern: datetime_pattern, placeholder: datetime_placeholder }
    = f.input :ends_at, include_blank: true, wrapper: :with_block_label, html5: true, input_html: { pattern: datetime_pattern, placeholder: datetime_placeholder }

  .fields-group
    = f.input :all_day, as: :boolean, wrapper: :with_label


@@ 16,7 16,7 @@

  - unless @announcement.published?
    .fields-group
      = f.input :scheduled_at, include_blank: true, wrapper: :with_block_label, html5: true, input_html: { pattern: '[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}(:[0-9]{2}){1,2}', placeholder: Time.now.strftime('%FT%R') }
      = f.input :scheduled_at, include_blank: true, wrapper: :with_block_label, html5: true, input_html: { pattern: datetime_pattern, placeholder: datetime_placeholder }

  .actions
    = f.button :button, t('generic.save_changes'), type: :submit

M app/views/admin/announcements/new.html.haml => app/views/admin/announcements/new.html.haml +3 -3
@@ 5,8 5,8 @@
  = render 'shared/error_messages', object: @announcement

  .fields-group
    = f.input :starts_at, include_blank: true, wrapper: :with_block_label, html5: true, input_html: { pattern: '[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}(:[0-9]{2}){1,2}', placeholder: Time.now.strftime('%FT%R') }
    = f.input :ends_at, include_blank: true, wrapper: :with_block_label, html5: true, input_html: { pattern: '[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}(:[0-9]{2}){1,2}', placeholder: Time.now.strftime('%FT%R') }
    = f.input :starts_at, include_blank: true, wrapper: :with_block_label, html5: true, input_html: { pattern: datetime_pattern, placeholder: datetime_placeholder }
    = f.input :ends_at, include_blank: true, wrapper: :with_block_label, html5: true, input_html: { pattern: datetime_pattern, placeholder: datetime_placeholder }

  .fields-group
    = f.input :all_day, as: :boolean, wrapper: :with_label


@@ 15,7 15,7 @@
    = f.input :text, wrapper: :with_block_label

  .fields-group
    = f.input :scheduled_at, include_blank: true, wrapper: :with_block_label, html5: true, input_html: { pattern: '[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}(:[0-9]{2}){1,2}', placeholder: Time.now.strftime('%FT%R') }
    = f.input :scheduled_at, include_blank: true, wrapper: :with_block_label, html5: true, input_html: { pattern: datetime_pattern, placeholder: datetime_placeholder }

  .actions
    = f.button :button, t('.create'), type: :submit

M app/views/admin/reports/actions/preview.html.haml => app/views/admin/reports/actions/preview.html.haml +1 -1
@@ 61,7 61,7 @@
                      = fa_icon 'link'
                      = media_attachment.file_file_name
                .strike-card__statuses-list__item__meta
                  = link_to ActivityPub::TagManager.instance.url_for(status), target: '_blank' do
                  = link_to ActivityPub::TagManager.instance.url_for(status), target: '_blank', rel: 'noopener noreferrer' do
                    %time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at)
                  - unless status.application.nil?
                    ·

M app/views/admin/statuses/show.html.haml => app/views/admin/statuses/show.html.haml +1 -1
@@ 2,7 2,7 @@
  = t('statuses.title', name: display_name(@account), quote: truncate(@status.spoiler_text.presence || @status.text, length: 50, omission: '…', escape: false))

- content_for :heading_actions do
  = link_to t('admin.statuses.open'), ActivityPub::TagManager.instance.url_for(@status), class: 'button', target: '_blank'
  = link_to t('admin.statuses.open'), ActivityPub::TagManager.instance.url_for(@status), class: 'button', target: '_blank', rel: 'noopener noreferrer'

%h3= t('admin.statuses.metadata')


M app/views/admin/tags/show.html.haml => app/views/admin/tags/show.html.haml +1 -1
@@ 9,7 9,7 @@

  .dashboard
    .dashboard__item
      = react_admin_component :counter, measure: 'tag_accounts', start_at: @time_period.first, end_at: @time_period.last, params: { id: @tag.id }, label: t('admin.trends.tags.dashboard.tag_accounts_measure'), href: tag_url(@tag), target: '_blank'
      = react_admin_component :counter, measure: 'tag_accounts', start_at: @time_period.first, end_at: @time_period.last, params: { id: @tag.id }, label: t('admin.trends.tags.dashboard.tag_accounts_measure'), href: tag_url(@tag), target: '_blank', rel: 'noopener noreferrer'
    .dashboard__item
      = react_admin_component :counter, measure: 'tag_uses', start_at: @time_period.first, end_at: @time_period.last, params: { id: @tag.id }, label: t('admin.trends.tags.dashboard.tag_uses_measure')
    .dashboard__item

M app/views/auth/registrations/new.html.haml => app/views/auth/registrations/new.html.haml +1 -1
@@ 26,7 26,7 @@
    = f.input :confirm_password, as: :string, placeholder: t('simple_form.labels.defaults.honeypot', label: t('simple_form.labels.defaults.password')), required: false, input_html: { 'aria-label': t('simple_form.labels.defaults.honeypot', label: t('simple_form.labels.defaults.password')), autocomplete: 'off' }, hint: false
    = f.input :website, as: :url, wrapper: :with_label, label: t('simple_form.labels.defaults.honeypot', label: 'Website'), required: false, input_html: { 'aria-label': t('simple_form.labels.defaults.honeypot', label: 'Website'), autocomplete: 'off' }

  - if approved_registrations? && !@invite.present?
  - if approved_registrations? && @invite.blank?
    %p.lead= t('auth.sign_up.manual_review', domain: site_hostname)

    .fields-group

M app/views/disputes/strikes/show.html.haml => app/views/disputes/strikes/show.html.haml +2 -2
@@ 25,7 25,7 @@
      - unless @strike.none_action?
        %p= t "user_mailer.warning.explanation.#{@strike.action}", instance: Rails.configuration.x.local_domain

      - unless @strike.text.blank?
      - if @strike.text.present?
        = linkify(@strike.text)

      - if @strike.report && !@strike.report.other?


@@ 57,7 57,7 @@
                      = fa_icon 'link'
                      = media_attachment.file_file_name
                .strike-card__statuses-list__item__meta
                  = link_to ActivityPub::TagManager.instance.url_for(status), target: '_blank' do
                  = link_to ActivityPub::TagManager.instance.url_for(status), target: '_blank', rel: 'noopener noreferrer' do
                    %time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at)
                  - unless status.application.nil?
                    ·

M app/views/statuses/_detailed_status.html.haml => app/views/statuses/_detailed_status.html.haml +1 -1
@@ 77,4 77,4 @@

    - if user_signed_in?
      ·
      = link_to t('statuses.open_in_web'), web_url("@#{status.account.pretty_acct}/#{status.id}"), class: 'detailed-status__application', target: '_blank'
      = link_to t('statuses.open_in_web'), web_url("@#{status.account.pretty_acct}/#{status.id}"), class: 'detailed-status__application', target: '_blank', rel: 'noopener noreferrer'

M app/views/user_mailer/warning.html.haml => app/views/user_mailer/warning.html.haml +2 -2
@@ 39,7 39,7 @@
                              - unless @warning.none_action?
                                %p= t "user_mailer.warning.explanation.#{@warning.action}", instance: @instance

                              - unless @warning.text.blank?
                              - if @warning.text.present?
                                = linkify(@warning.text)

                              - if @warning.report && !@warning.report.other?


@@ 68,7 68,7 @@
          %table.content-section{ cellspacing: 0, cellpadding: 0 }
            %tbody
              %tr
                %td.content-cell{ class: @statuses.nil? || @statuses.empty? ? '' : 'content-start' }
                %td.content-cell{ class: @statuses.blank? ? '' : 'content-start' }
                  %table.column{ cellspacing: 0, cellpadding: 0 }
                    %tbody
                      %tr

M config/application.rb => config/application.rb +5 -5
@@ 5,15 5,15 @@ require_relative 'boot'
require 'rails'

require 'active_record/railtie'
#require 'active_storage/engine'
# require 'active_storage/engine'
require 'action_controller/railtie'
require 'action_view/railtie'
require 'action_mailer/railtie'
require 'active_job/railtie'
#require 'action_cable/engine'
#require 'action_mailbox/engine'
#require 'action_text/engine'
#require 'rails/test_unit/railtie'
# require 'action_cable/engine'
# require 'action_mailbox/engine'
# require 'action_text/engine'
# require 'rails/test_unit/railtie'
require 'sprockets/railtie'

# Used to be implicitly required in action_mailbox/engine

M config/environments/production.rb => config/environments/production.rb +6 -6
@@ 44,7 44,7 @@ Rails.application.configure do
  config.force_ssl = true
  config.ssl_options = {
    redirect: {
      exclude: -> request { request.path.start_with?('/health') || request.headers["Host"].end_with?('.onion') || request.headers["Host"].end_with?('.i2p') }
      exclude: ->request { request.path.start_with?('/health') || request.headers["Host"].end_with?('.onion') || request.headers["Host"].end_with?('.i2p') }
    }
  }



@@ 148,12 148,12 @@ Rails.application.configure do
  config.action_mailer.delivery_method = ENV.fetch('SMTP_DELIVERY_METHOD', 'smtp').to_sym

  config.action_dispatch.default_headers = {
    'Server'                 => 'Mastodon',
    'X-Frame-Options'        => 'DENY',
    'Server' => 'Mastodon',
    'X-Frame-Options' => 'DENY',
    'X-Content-Type-Options' => 'nosniff',
    'X-XSS-Protection'       => '0',
    'X-Clacks-Overhead'      => 'GNU Natalie Nguyen',
    'Referrer-Policy'        => 'same-origin',
    'X-XSS-Protection' => '0',
    'X-Clacks-Overhead' => 'GNU Natalie Nguyen',
    'Referrer-Policy' => 'same-origin',
  }

  config.x.otp_secret = ENV.fetch('OTP_SECRET')

M config/initializers/3_omniauth.rb => config/initializers/3_omniauth.rb +25 -25
@@ 76,35 76,35 @@ Devise.setup do |config|
  # OpenID Connect Strategy
  if ENV['OIDC_ENABLED'] == 'true'
    oidc_options = {}
    oidc_options[:display_name] = ENV['OIDC_DISPLAY_NAME'] #OPTIONAL
    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[: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
    oidc_options[:display_name] = ENV['OIDC_DISPLAY_NAME'] # OPTIONAL
    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[: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
    scopes = scope_string.split(',')
    oidc_options[:scope] = scopes.map { |x| x.to_sym }
    oidc_options[:response_type] = ENV['OIDC_RESPONSE_TYPE'] if ENV['OIDC_RESPONSE_TYPE'] #OPTIONAL (default: code)
    oidc_options[:response_mode] = ENV['OIDC_RESPONSE_MODE'] if ENV['OIDC_RESPONSE_MODE'] #OPTIONAL (default: query)
    oidc_options[:display] = ENV['OIDC_DISPLAY'] if ENV['OIDC_DISPLAY'] #OPTIONAL (default: page)
    oidc_options[:prompt] = ENV['OIDC_PROMPT'] if ENV['OIDC_PROMPT'] #OPTIONAL
    oidc_options[:send_nonce] = ENV['OIDC_SEND_NONCE'] == 'true' if ENV['OIDC_SEND_NONCE'] #OPTIONAL (default: true)
    oidc_options[:send_scope_to_token_endpoint] = ENV['OIDC_SEND_SCOPE_TO_TOKEN_ENDPOINT'] == 'true' if ENV['OIDC_SEND_SCOPE_TO_TOKEN_ENDPOINT'] #OPTIONAL (default: true)
    oidc_options[:post_logout_redirect_uri] = ENV['OIDC_IDP_LOGOUT_REDIRECT_URI'] if ENV['OIDC_IDP_LOGOUT_REDIRECT_URI'] #OPTIONAL
    oidc_options[:uid_field] = ENV['OIDC_UID_FIELD'] if ENV['OIDC_UID_FIELD'] #NEED
    oidc_options[:response_type] = ENV['OIDC_RESPONSE_TYPE'] if ENV['OIDC_RESPONSE_TYPE'] # OPTIONAL (default: code)
    oidc_options[:response_mode] = ENV['OIDC_RESPONSE_MODE'] if ENV['OIDC_RESPONSE_MODE'] # OPTIONAL (default: query)
    oidc_options[:display] = ENV['OIDC_DISPLAY'] if ENV['OIDC_DISPLAY'] # OPTIONAL (default: page)
    oidc_options[:prompt] = ENV['OIDC_PROMPT'] if ENV['OIDC_PROMPT'] # OPTIONAL
    oidc_options[:send_nonce] = ENV['OIDC_SEND_NONCE'] == 'true' if ENV['OIDC_SEND_NONCE'] # OPTIONAL (default: true)
    oidc_options[:send_scope_to_token_endpoint] = ENV['OIDC_SEND_SCOPE_TO_TOKEN_ENDPOINT'] == 'true' if ENV['OIDC_SEND_SCOPE_TO_TOKEN_ENDPOINT'] # OPTIONAL (default: true)
    oidc_options[:post_logout_redirect_uri] = ENV['OIDC_IDP_LOGOUT_REDIRECT_URI'] if ENV['OIDC_IDP_LOGOUT_REDIRECT_URI'] # OPTIONAL
    oidc_options[:uid_field] = ENV['OIDC_UID_FIELD'] if ENV['OIDC_UID_FIELD'] # NEED
    oidc_options[:client_options] = {}
    oidc_options[:client_options][:identifier] = ENV['OIDC_CLIENT_ID'] if ENV['OIDC_CLIENT_ID'] #NEED
    oidc_options[:client_options][:secret] = ENV['OIDC_CLIENT_SECRET'] if ENV['OIDC_CLIENT_SECRET'] #NEED
    oidc_options[:client_options][:redirect_uri] = ENV['OIDC_REDIRECT_URI'] if ENV['OIDC_REDIRECT_URI'] #NEED
    oidc_options[:client_options][:scheme] = ENV['OIDC_HTTP_SCHEME'] if ENV['OIDC_HTTP_SCHEME'] #OPTIONAL (default: https)
    oidc_options[:client_options][:host] = ENV['OIDC_HOST'] if ENV['OIDC_HOST'] #OPTIONAL
    oidc_options[:client_options][:port] = ENV['OIDC_PORT'] if ENV['OIDC_PORT'] #OPTIONAL
    oidc_options[:client_options][:authorization_endpoint] = ENV['OIDC_AUTH_ENDPOINT'] if ENV['OIDC_AUTH_ENDPOINT'] #NEED when discovery != true
    oidc_options[:client_options][:token_endpoint] = ENV['OIDC_TOKEN_ENDPOINT'] if ENV['OIDC_TOKEN_ENDPOINT'] #NEED when discovery != true
    oidc_options[:client_options][:userinfo_endpoint] = ENV['OIDC_USER_INFO_ENDPOINT'] if ENV['OIDC_USER_INFO_ENDPOINT'] #NEED when discovery != true
    oidc_options[:client_options][:jwks_uri] = ENV['OIDC_JWKS_URI'] if ENV['OIDC_JWKS_URI'] #NEED when discovery != true
    oidc_options[:client_options][:end_session_endpoint] = ENV['OIDC_END_SESSION_ENDPOINT'] if ENV['OIDC_END_SESSION_ENDPOINT'] #OPTIONAL
    oidc_options[:client_options][:identifier] = ENV['OIDC_CLIENT_ID'] if ENV['OIDC_CLIENT_ID'] # NEED
    oidc_options[:client_options][:secret] = ENV['OIDC_CLIENT_SECRET'] if ENV['OIDC_CLIENT_SECRET'] # NEED
    oidc_options[:client_options][:redirect_uri] = ENV['OIDC_REDIRECT_URI'] if ENV['OIDC_REDIRECT_URI'] # NEED
    oidc_options[:client_options][:scheme] = ENV['OIDC_HTTP_SCHEME'] if ENV['OIDC_HTTP_SCHEME'] # OPTIONAL (default: https)
    oidc_options[:client_options][:host] = ENV['OIDC_HOST'] if ENV['OIDC_HOST'] # OPTIONAL
    oidc_options[:client_options][:port] = ENV['OIDC_PORT'] if ENV['OIDC_PORT'] # OPTIONAL
    oidc_options[:client_options][:authorization_endpoint] = ENV['OIDC_AUTH_ENDPOINT'] if ENV['OIDC_AUTH_ENDPOINT'] # NEED when discovery != true
    oidc_options[:client_options][:token_endpoint] = ENV['OIDC_TOKEN_ENDPOINT'] if ENV['OIDC_TOKEN_ENDPOINT'] # NEED when discovery != true
    oidc_options[:client_options][:userinfo_endpoint] = ENV['OIDC_USER_INFO_ENDPOINT'] if ENV['OIDC_USER_INFO_ENDPOINT'] # NEED when discovery != true
    oidc_options[:client_options][:jwks_uri] = ENV['OIDC_JWKS_URI'] if ENV['OIDC_JWKS_URI'] # NEED when discovery != true
    oidc_options[:client_options][:end_session_endpoint] = ENV['OIDC_END_SESSION_ENDPOINT'] if ENV['OIDC_END_SESSION_ENDPOINT'] # OPTIONAL
    oidc_options[:security] = {}
    oidc_options[:security][:assume_email_is_verified] = ENV['OIDC_SECURITY_ASSUME_EMAIL_IS_VERIFIED'] == 'true' #OPTIONAL
    oidc_options[:security][:assume_email_is_verified] = ENV['OIDC_SECURITY_ASSUME_EMAIL_IS_VERIFIED'] == 'true' # OPTIONAL
    config.omniauth :openid_connect, oidc_options
  end
end

M config/initializers/content_security_policy.rb => config/initializers/content_security_policy.rb +1 -1
@@ 75,7 75,7 @@ end
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only
# Rails.application.config.content_security_policy_report_only = true

Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) }
Rails.application.config.content_security_policy_nonce_generator = ->request { SecureRandom.base64(16) }

Rails.application.config.content_security_policy_nonce_directives = %w(style-src)


M config/initializers/rack_attack.rb => config/initializers/rack_attack.rb +3 -3
@@ 142,10 142,10 @@ class Rack::Attack
    match_data = request.env['rack.attack.match_data']

    headers = {
      'Content-Type'          => 'application/json',
      'X-RateLimit-Limit'     => match_data[:limit].to_s,
      'Content-Type' => 'application/json',
      'X-RateLimit-Limit' => match_data[:limit].to_s,
      'X-RateLimit-Remaining' => '0',
      'X-RateLimit-Reset'     => (now + (match_data[:period] - (now.to_i % match_data[:period]))).iso8601(6),
      'X-RateLimit-Reset' => (now + (match_data[:period] - (now.to_i % match_data[:period]))).iso8601(6),
    }

    [429, headers, [{ error: I18n.t('errors.429') }.to_json]]

M config/routes.rb => config/routes.rb +4 -4
@@ 85,10 85,10 @@ Rails.application.routes.draw do

  devise_for :users, path: 'auth', format: false, controllers: {
    omniauth_callbacks: 'auth/omniauth_callbacks',
    sessions:           'auth/sessions',
    registrations:      'auth/registrations',
    passwords:          'auth/passwords',
    confirmations:      'auth/confirmations',
    sessions: 'auth/sessions',
    registrations: 'auth/registrations',
    passwords: 'auth/passwords',
    confirmations: 'auth/confirmations',
  }

  get '/users/:username', to: redirect('/@%{username}'), constraints: lambda { |req| req.format.nil? || req.format.html? }

M lib/mastodon/migration_helpers.rb => lib/mastodon/migration_helpers.rb +0 -3
@@ 37,7 37,6 @@

# This is bad form, but there are enough differences that it's impractical to do
# otherwise:
# rubocop:disable all

module Mastodon
  module MigrationHelpers


@@ 989,5 988,3 @@ into similar problems in the future (e.g. when new tables are created).
    end
  end
end

# rubocop:enable all

M spec/models/account_spec.rb => spec/models/account_spec.rb +1 -1
@@ 700,7 700,7 @@ RSpec.describe Account do
      expect(subject.match('Check this out https://medium.com/@alice/some-article#.abcdef123')).to be_nil
    end

    xit 'does not match URL query string' do
    it 'does not match URL query string' do
      expect(subject.match('https://example.com/?x=@alice')).to be_nil
    end
  end