mirror of
https://framagit.org/tykayn/mastodon.git
synced 2023-08-25 08:33:12 +02:00
05ef749a0f
The method is available to apps with a token obtained via the client credentials grant. It creates a user and account records, as well as an access token for the app that initiated the request. The user is unconfirmed, and an e-mail is sent as usual. The method returns the access token, which the app should save for later. The REST API is not available to users with unconfirmed accounts, so the app must be smart to wait for the user to click a link in their e-mail inbox. The method is rate-limited by IP to 5 requests per 30 minutes.
82 lines
2.2 KiB
Ruby
82 lines
2.2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'doorkeeper/grape/authorization_decorator'
|
|
|
|
class Rack::Attack
|
|
class Request
|
|
def authenticated_token
|
|
return @token if defined?(@token)
|
|
|
|
@token = Doorkeeper::OAuth::Token.authenticate(
|
|
Doorkeeper::Grape::AuthorizationDecorator.new(self),
|
|
*Doorkeeper.configuration.access_token_methods
|
|
)
|
|
end
|
|
|
|
def authenticated_user_id
|
|
authenticated_token&.resource_owner_id
|
|
end
|
|
|
|
def unauthenticated?
|
|
!authenticated_user_id
|
|
end
|
|
|
|
def api_request?
|
|
path.start_with?('/api')
|
|
end
|
|
|
|
def web_request?
|
|
!api_request?
|
|
end
|
|
end
|
|
|
|
PROTECTED_PATHS = %w(
|
|
/auth/sign_in
|
|
/auth
|
|
/auth/password
|
|
).freeze
|
|
|
|
PROTECTED_PATHS_REGEX = Regexp.union(PROTECTED_PATHS.map { |path| /\A#{Regexp.escape(path)}/ })
|
|
|
|
# Always allow requests from localhost
|
|
# (blocklist & throttles are skipped)
|
|
Rack::Attack.safelist('allow from localhost') do |req|
|
|
# Requests are allowed if the return value is truthy
|
|
req.ip == '127.0.0.1' || req.ip == '::1'
|
|
end
|
|
|
|
throttle('throttle_authenticated_api', limit: 300, period: 5.minutes) do |req|
|
|
req.api_request? && req.authenticated_user_id
|
|
end
|
|
|
|
throttle('throttle_unauthenticated_api', limit: 7_500, period: 5.minutes) do |req|
|
|
req.ip if req.api_request?
|
|
end
|
|
|
|
throttle('throttle_media', limit: 30, period: 30.minutes) do |req|
|
|
req.authenticated_user_id if req.post? && req.path.start_with?('/api/v1/media')
|
|
end
|
|
|
|
throttle('throttle_api_sign_up', limit: 5, period: 30.minutes) do |req|
|
|
req.ip if req.post? && req.path == '/api/v1/accounts'
|
|
end
|
|
|
|
throttle('protected_paths', limit: 25, period: 5.minutes) do |req|
|
|
req.ip if req.post? && req.path =~ PROTECTED_PATHS_REGEX
|
|
end
|
|
|
|
self.throttled_response = lambda do |env|
|
|
now = Time.now.utc
|
|
match_data = env['rack.attack.match_data']
|
|
|
|
headers = {
|
|
'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),
|
|
}
|
|
|
|
[429, headers, [{ error: I18n.t('errors.429') }.to_json]]
|
|
end
|
|
end
|