Merge commit '651e51a82eba542c4d8c3fec5edd16420ea1ff3e' into glitch-soc/merge-upstream

Conflicts:
- `yarn.lock`:
  Upstream updated a dependency textually adjacent to a glitch-soc-specific one.
  Updated the dependency as upstream did.
This commit is contained in:
Claire
2025-08-17 20:52:34 +02:00
86 changed files with 2659 additions and 1164 deletions

View File

@@ -0,0 +1,33 @@
# frozen_string_literal: true
class Api::V1::Statuses::InteractionPoliciesController < Api::V1::Statuses::BaseController
include Api::InteractionPoliciesConcern
before_action -> { doorkeeper_authorize! :write, :'write:statuses' }
before_action -> { check_feature_enabled }
def update
authorize @status, :update?
@status.update!(quote_approval_policy: quote_approval_policy)
broadcast_updates! if @status.quote_approval_policy_previously_changed?
render json: @status, serializer: REST::StatusSerializer
end
private
def status_params
params.permit(:quote_approval_policy)
end
def check_feature_enabled
raise ActionController::RoutingError unless Mastodon::Feature.outgoing_quotes_enabled?
end
def broadcast_updates!
DistributionWorker.perform_async(@status.id, { 'update' => true })
ActivityPub::StatusUpdateDistributionWorker.perform_async(@status.id)
end
end

View File

@@ -3,6 +3,7 @@
class Api::V1::StatusesController < Api::BaseController
include Authorization
include AsyncRefreshesConcern
include Api::InteractionPoliciesConcern
before_action -> { authorize_if_got_token! :read, :'read:statuses' }, except: [:create, :update, :destroy]
before_action -> { doorkeeper_authorize! :write, :'write:statuses' }, only: [:create, :update, :destroy]
@@ -208,23 +209,6 @@ class Api::V1::StatusesController < Api::BaseController
)
end
def quote_approval_policy
# TODO: handle `nil` separately
return nil unless Mastodon::Feature.outgoing_quotes_enabled? && status_params[:quote_approval_policy].present?
case status_params[:quote_approval_policy]
when 'public'
Status::QUOTE_APPROVAL_POLICY_FLAGS[:public] << 16
when 'followers'
Status::QUOTE_APPROVAL_POLICY_FLAGS[:followers] << 16
when 'nobody'
0
else
# TODO: raise more useful message
raise ActiveRecord::RecordInvalid
end
end
def serializer_for_status
@status.is_a?(ScheduledStatus) ? REST::ScheduledStatusSerializer : REST::StatusSerializer
end

View File

@@ -23,11 +23,11 @@ class Auth::RegistrationsController < Devise::RegistrationsController
super(&:build_invite_request)
end
def edit # rubocop:disable Lint/UselessMethodDefinition
def edit
super
end
def create # rubocop:disable Lint/UselessMethodDefinition
def create
super
end

View File

@@ -0,0 +1,22 @@
# frozen_string_literal: true
module Api::InteractionPoliciesConcern
extend ActiveSupport::Concern
def quote_approval_policy
# TODO: handle `nil` separately
return nil unless Mastodon::Feature.outgoing_quotes_enabled? && status_params[:quote_approval_policy].present?
case status_params[:quote_approval_policy]
when 'public'
Status::QUOTE_APPROVAL_POLICY_FLAGS[:public] << 16
when 'followers'
Status::QUOTE_APPROVAL_POLICY_FLAGS[:followers] << 16
when 'nobody'
0
else
# TODO: raise more useful message
raise ActiveRecord::RecordInvalid
end
end
end

View File

@@ -9,6 +9,8 @@ module SignatureVerification
EXPIRATION_WINDOW_LIMIT = 12.hours
CLOCK_SKEW_MARGIN = 1.hour
STOPLIGHT_COOL_OFF_TIME = 5.minutes.seconds
STOPLIGHT_THRESHOLD = 1
def require_account_signature!
render json: signature_verification_failure_reason, status: signature_verification_failure_code unless signed_request_account
@@ -107,10 +109,12 @@ module SignatureVerification
end
def stoplight_wrapper
Stoplight("source:#{request.remote_ip}")
.with_threshold(1)
.with_cool_off_time(5.minutes.seconds)
.with_error_handler { |error, handle| error.is_a?(HTTP::Error) || error.is_a?(OpenSSL::SSL::SSLError) ? handle.call(error) : raise(error) }
Stoplight(
"source:#{request.remote_ip}",
cool_off_time: STOPLIGHT_COOL_OFF_TIME,
threshold: STOPLIGHT_THRESHOLD,
tracked_errors: [HTTP::Error, OpenSSL::SSL::SSLError]
)
end
def actor_refresh_key!(actor)