Merge tag 'v3.2.0' into hometown-dev
This commit is contained in:
@ -1,7 +1,8 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class AccountsController < ApplicationController
|
||||
PAGE_SIZE = 20
|
||||
PAGE_SIZE = 20
|
||||
PAGE_SIZE_MAX = 200
|
||||
|
||||
include AccountControllerConcern
|
||||
include SignatureAuthentication
|
||||
@ -10,7 +11,7 @@ class AccountsController < ApplicationController
|
||||
before_action :set_body_classes
|
||||
|
||||
skip_around_action :set_locale, if: -> { [:json, :rss].include?(request.format&.to_sym) }
|
||||
skip_before_action :require_functional!
|
||||
skip_before_action :require_functional!, unless: :whitelist_mode?
|
||||
|
||||
def show
|
||||
respond_to do |format|
|
||||
@ -44,7 +45,8 @@ class AccountsController < ApplicationController
|
||||
format.rss do
|
||||
expires_in 1.minute, public: true
|
||||
|
||||
@statuses = filtered_statuses.without_reblogs.without_local_only.limit(PAGE_SIZE)
|
||||
limit = params[:limit].present? ? [params[:limit].to_i, PAGE_SIZE_MAX].min : PAGE_SIZE
|
||||
@statuses = filtered_statuses.without_reblogs.without_local_only.limit(limit)
|
||||
@statuses = cache_collection(@statuses, Status)
|
||||
render xml: RSS::AccountSerializer.render(@account, @statuses, params[:tag])
|
||||
end
|
||||
|
21
app/controllers/activitypub/claims_controller.rb
Normal file
21
app/controllers/activitypub/claims_controller.rb
Normal file
@ -0,0 +1,21 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class ActivityPub::ClaimsController < ActivityPub::BaseController
|
||||
include SignatureVerification
|
||||
include AccountOwnedConcern
|
||||
|
||||
skip_before_action :authenticate_user!
|
||||
|
||||
before_action :require_signature!
|
||||
before_action :set_claim_result
|
||||
|
||||
def create
|
||||
render json: @claim_result, serializer: ActivityPub::OneTimeKeySerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_claim_result
|
||||
@claim_result = ::Keys::ClaimService.new.call(@account.id, params[:id])
|
||||
end
|
||||
end
|
@ -5,8 +5,9 @@ class ActivityPub::CollectionsController < ActivityPub::BaseController
|
||||
include AccountOwnedConcern
|
||||
|
||||
before_action :require_signature!, if: :authorized_fetch_mode?
|
||||
before_action :set_items
|
||||
before_action :set_size
|
||||
before_action :set_statuses
|
||||
before_action :set_type
|
||||
before_action :set_cache_headers
|
||||
|
||||
def show
|
||||
@ -16,40 +17,53 @@ class ActivityPub::CollectionsController < ActivityPub::BaseController
|
||||
|
||||
private
|
||||
|
||||
def set_statuses
|
||||
@statuses = scope_for_collection
|
||||
@statuses = cache_collection(@statuses, Status)
|
||||
end
|
||||
|
||||
def set_size
|
||||
def set_items
|
||||
case params[:id]
|
||||
when 'featured'
|
||||
@size = @account.pinned_statuses.count
|
||||
@items = begin
|
||||
# Because in public fetch mode we cache the response, there would be no
|
||||
# benefit from performing the check below, since a blocked account or domain
|
||||
# would likely be served the cache from the reverse proxy anyway
|
||||
|
||||
if authorized_fetch_mode? && !signed_request_account.nil? && (@account.blocking?(signed_request_account) || (!signed_request_account.domain.nil? && @account.domain_blocking?(signed_request_account.domain)))
|
||||
[]
|
||||
else
|
||||
cache_collection(@account.pinned_statuses, Status)
|
||||
end
|
||||
end
|
||||
when 'devices'
|
||||
@items = @account.devices
|
||||
else
|
||||
not_found
|
||||
end
|
||||
end
|
||||
|
||||
def scope_for_collection
|
||||
def set_size
|
||||
case params[:id]
|
||||
when 'featured', 'devices'
|
||||
@size = @items.size
|
||||
else
|
||||
not_found
|
||||
end
|
||||
end
|
||||
|
||||
def set_type
|
||||
case params[:id]
|
||||
when 'featured'
|
||||
# Because in public fetch mode we cache the response, there would be no
|
||||
# benefit from performing the check below, since a blocked account or domain
|
||||
# would likely be served the cache from the reverse proxy anyway
|
||||
if authorized_fetch_mode? && !signed_request_account.nil? && (@account.blocking?(signed_request_account) || (!signed_request_account.domain.nil? && @account.domain_blocking?(signed_request_account.domain)))
|
||||
Status.none
|
||||
else
|
||||
@account.pinned_statuses
|
||||
end
|
||||
@type = :ordered
|
||||
when 'devices'
|
||||
@type = :unordered
|
||||
else
|
||||
not_found
|
||||
end
|
||||
end
|
||||
|
||||
def collection_presenter
|
||||
ActivityPub::CollectionPresenter.new(
|
||||
id: account_collection_url(@account, params[:id]),
|
||||
type: :ordered,
|
||||
type: @type,
|
||||
size: @size,
|
||||
items: @statuses
|
||||
items: @items
|
||||
)
|
||||
end
|
||||
end
|
||||
|
@ -33,6 +33,8 @@ module Admin
|
||||
@form.save
|
||||
rescue ActionController::ParameterMissing
|
||||
flash[:alert] = I18n.t('admin.accounts.no_account_selected')
|
||||
rescue Mastodon::NotPermittedError
|
||||
flash[:alert] = I18n.t('admin.custom_emojis.not_permitted')
|
||||
ensure
|
||||
redirect_to admin_custom_emojis_path(filter_params)
|
||||
end
|
||||
|
@ -7,7 +7,7 @@ class Api::BaseController < ApplicationController
|
||||
include RateLimitHeaders
|
||||
|
||||
skip_before_action :store_current_location
|
||||
skip_before_action :require_functional!
|
||||
skip_before_action :require_functional!, unless: :whitelist_mode?
|
||||
|
||||
before_action :require_authenticated_user!, if: :disallow_unauthenticated_api_access?
|
||||
before_action :set_cache_headers
|
||||
|
30
app/controllers/api/v1/accounts/notes_controller.rb
Normal file
30
app/controllers/api/v1/accounts/notes_controller.rb
Normal file
@ -0,0 +1,30 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::Accounts::NotesController < Api::BaseController
|
||||
include Authorization
|
||||
|
||||
before_action -> { doorkeeper_authorize! :write, :'write:accounts' }
|
||||
before_action :require_user!
|
||||
before_action :set_account
|
||||
|
||||
def create
|
||||
if params[:comment].blank?
|
||||
AccountNote.find_by(account: current_account, target_account: @account)&.destroy
|
||||
else
|
||||
@note = AccountNote.find_or_initialize_by(account: current_account, target_account: @account)
|
||||
@note.comment = params[:comment]
|
||||
@note.save! if @note.changed?
|
||||
end
|
||||
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships_presenter
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_account
|
||||
@account = Account.find(params[:account_id])
|
||||
end
|
||||
|
||||
def relationships_presenter
|
||||
AccountRelationshipsPresenter.new([@account.id], current_user.account_id)
|
||||
end
|
||||
end
|
30
app/controllers/api/v1/crypto/deliveries_controller.rb
Normal file
30
app/controllers/api/v1/crypto/deliveries_controller.rb
Normal file
@ -0,0 +1,30 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::Crypto::DeliveriesController < Api::BaseController
|
||||
before_action -> { doorkeeper_authorize! :crypto }
|
||||
before_action :require_user!
|
||||
before_action :set_current_device
|
||||
|
||||
def create
|
||||
devices.each do |device_params|
|
||||
DeliverToDeviceService.new.call(current_account, @current_device, device_params)
|
||||
end
|
||||
|
||||
render_empty
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_current_device
|
||||
@current_device = Device.find_by!(access_token: doorkeeper_token)
|
||||
end
|
||||
|
||||
def resource_params
|
||||
params.require(:device)
|
||||
params.permit(device: [:account_id, :device_id, :type, :body, :hmac])
|
||||
end
|
||||
|
||||
def devices
|
||||
Array(resource_params[:device])
|
||||
end
|
||||
end
|
@ -0,0 +1,59 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::Crypto::EncryptedMessagesController < Api::BaseController
|
||||
LIMIT = 80
|
||||
|
||||
before_action -> { doorkeeper_authorize! :crypto }
|
||||
before_action :require_user!
|
||||
before_action :set_current_device
|
||||
|
||||
before_action :set_encrypted_messages, only: :index
|
||||
after_action :insert_pagination_headers, only: :index
|
||||
|
||||
def index
|
||||
render json: @encrypted_messages, each_serializer: REST::EncryptedMessageSerializer
|
||||
end
|
||||
|
||||
def clear
|
||||
@current_device.encrypted_messages.up_to(params[:up_to_id]).delete_all
|
||||
render_empty
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_current_device
|
||||
@current_device = Device.find_by!(access_token: doorkeeper_token)
|
||||
end
|
||||
|
||||
def set_encrypted_messages
|
||||
@encrypted_messages = @current_device.encrypted_messages.paginate_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id))
|
||||
end
|
||||
|
||||
def insert_pagination_headers
|
||||
set_pagination_headers(next_path, prev_path)
|
||||
end
|
||||
|
||||
def next_path
|
||||
api_v1_crypto_encrypted_messages_url pagination_params(max_id: pagination_max_id) if records_continue?
|
||||
end
|
||||
|
||||
def prev_path
|
||||
api_v1_crypto_encrypted_messages_url pagination_params(min_id: pagination_since_id) unless @encrypted_messages.empty?
|
||||
end
|
||||
|
||||
def pagination_max_id
|
||||
@encrypted_messages.last.id
|
||||
end
|
||||
|
||||
def pagination_since_id
|
||||
@encrypted_messages.first.id
|
||||
end
|
||||
|
||||
def records_continue?
|
||||
@encrypted_messages.size == limit_param(LIMIT)
|
||||
end
|
||||
|
||||
def pagination_params(core_params)
|
||||
params.slice(:limit).permit(:limit).merge(core_params)
|
||||
end
|
||||
end
|
25
app/controllers/api/v1/crypto/keys/claims_controller.rb
Normal file
25
app/controllers/api/v1/crypto/keys/claims_controller.rb
Normal file
@ -0,0 +1,25 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::Crypto::Keys::ClaimsController < Api::BaseController
|
||||
before_action -> { doorkeeper_authorize! :crypto }
|
||||
before_action :require_user!
|
||||
before_action :set_claim_results
|
||||
|
||||
def create
|
||||
render json: @claim_results, each_serializer: REST::Keys::ClaimResultSerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_claim_results
|
||||
@claim_results = devices.map { |device_params| ::Keys::ClaimService.new.call(current_account, device_params[:account_id], device_params[:device_id]) }.compact
|
||||
end
|
||||
|
||||
def resource_params
|
||||
params.permit(device: [:account_id, :device_id])
|
||||
end
|
||||
|
||||
def devices
|
||||
Array(resource_params[:device])
|
||||
end
|
||||
end
|
17
app/controllers/api/v1/crypto/keys/counts_controller.rb
Normal file
17
app/controllers/api/v1/crypto/keys/counts_controller.rb
Normal file
@ -0,0 +1,17 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::Crypto::Keys::CountsController < Api::BaseController
|
||||
before_action -> { doorkeeper_authorize! :crypto }
|
||||
before_action :require_user!
|
||||
before_action :set_current_device
|
||||
|
||||
def show
|
||||
render json: { one_time_keys: @current_device.one_time_keys.count }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_current_device
|
||||
@current_device = Device.find_by!(access_token: doorkeeper_token)
|
||||
end
|
||||
end
|
26
app/controllers/api/v1/crypto/keys/queries_controller.rb
Normal file
26
app/controllers/api/v1/crypto/keys/queries_controller.rb
Normal file
@ -0,0 +1,26 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::Crypto::Keys::QueriesController < Api::BaseController
|
||||
before_action -> { doorkeeper_authorize! :crypto }
|
||||
before_action :require_user!
|
||||
before_action :set_accounts
|
||||
before_action :set_query_results
|
||||
|
||||
def create
|
||||
render json: @query_results, each_serializer: REST::Keys::QueryResultSerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_accounts
|
||||
@accounts = Account.where(id: account_ids).includes(:devices)
|
||||
end
|
||||
|
||||
def set_query_results
|
||||
@query_results = @accounts.map { |account| ::Keys::QueryService.new.call(account) }.compact
|
||||
end
|
||||
|
||||
def account_ids
|
||||
Array(params[:id]).map(&:to_i)
|
||||
end
|
||||
end
|
29
app/controllers/api/v1/crypto/keys/uploads_controller.rb
Normal file
29
app/controllers/api/v1/crypto/keys/uploads_controller.rb
Normal file
@ -0,0 +1,29 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::Crypto::Keys::UploadsController < Api::BaseController
|
||||
before_action -> { doorkeeper_authorize! :crypto }
|
||||
before_action :require_user!
|
||||
|
||||
def create
|
||||
device = Device.find_or_initialize_by(access_token: doorkeeper_token)
|
||||
|
||||
device.transaction do
|
||||
device.account = current_account
|
||||
device.update!(resource_params[:device])
|
||||
|
||||
if resource_params[:one_time_keys].present? && resource_params[:one_time_keys].is_a?(Enumerable)
|
||||
resource_params[:one_time_keys].each do |one_time_key_params|
|
||||
device.one_time_keys.create!(one_time_key_params)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
render json: device, serializer: REST::Keys::DeviceSerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def resource_params
|
||||
params.permit(device: [:device_id, :name, :fingerprint_key, :identity_key], one_time_keys: [:key_id, :key, :signature])
|
||||
end
|
||||
end
|
@ -39,7 +39,7 @@ class Api::V1::MediaController < Api::BaseController
|
||||
end
|
||||
|
||||
def media_attachment_params
|
||||
params.permit(:file, :description, :focus)
|
||||
params.permit(:file, :thumbnail, :description, :focus)
|
||||
end
|
||||
|
||||
def file_type_error
|
||||
|
@ -5,7 +5,7 @@ class Api::V1::Statuses::ReblogsController < Api::BaseController
|
||||
|
||||
before_action -> { doorkeeper_authorize! :write, :'write:statuses' }
|
||||
before_action :require_user!
|
||||
before_action :set_reblog
|
||||
before_action :set_reblog, only: [:create]
|
||||
|
||||
override_rate_limit_headers :create, family: :statuses
|
||||
|
||||
@ -16,15 +16,21 @@ class Api::V1::Statuses::ReblogsController < Api::BaseController
|
||||
end
|
||||
|
||||
def destroy
|
||||
@status = current_account.statuses.find_by(reblog_of_id: @reblog.id)
|
||||
@status = current_account.statuses.find_by(reblog_of_id: params[:status_id])
|
||||
|
||||
if @status
|
||||
authorize @status, :unreblog?
|
||||
@status.discard
|
||||
RemovalWorker.perform_async(@status.id)
|
||||
@reblog = @status.reblog
|
||||
else
|
||||
@reblog = Status.find(params[:status_id])
|
||||
authorize @reblog, :show?
|
||||
end
|
||||
|
||||
render json: @reblog, serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new([@status], current_account.id, reblogs_map: { @reblog.id => false })
|
||||
rescue Mastodon::NotPermittedError
|
||||
not_found
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -58,6 +58,7 @@ class Api::V1::StatusesController < Api::BaseController
|
||||
|
||||
@status.discard
|
||||
RemovalWorker.perform_async(@status.id, redraft: true)
|
||||
@status.account.statuses_count = @status.account.statuses_count - 1
|
||||
|
||||
render json: @status, serializer: REST::StatusSerializer, source_requested: true
|
||||
end
|
||||
|
@ -55,7 +55,7 @@ class ApplicationController < ActionController::Base
|
||||
end
|
||||
|
||||
def store_current_location
|
||||
store_location_for(:user, request.url) unless request.format == :json
|
||||
store_location_for(:user, request.url) unless [:json, :rss].include?(request.format&.to_sym)
|
||||
end
|
||||
|
||||
def require_admin!
|
||||
|
@ -8,7 +8,8 @@ class Auth::SessionsController < Devise::SessionsController
|
||||
skip_before_action :require_no_authentication, only: [:create]
|
||||
skip_before_action :require_functional!
|
||||
|
||||
prepend_before_action :authenticate_with_two_factor, if: :two_factor_enabled?, only: [:create]
|
||||
include TwoFactorAuthenticationConcern
|
||||
include SignInTokenAuthenticationConcern
|
||||
|
||||
before_action :set_instance_presenter, only: [:new]
|
||||
before_action :set_body_classes
|
||||
@ -39,17 +40,18 @@ class Auth::SessionsController < Devise::SessionsController
|
||||
protected
|
||||
|
||||
def find_user
|
||||
if session[:otp_user_id]
|
||||
User.find(session[:otp_user_id])
|
||||
if session[:attempt_user_id]
|
||||
User.find(session[:attempt_user_id])
|
||||
else
|
||||
user = User.authenticate_with_ldap(user_params) if Devise.ldap_authentication
|
||||
user ||= User.authenticate_with_pam(user_params) if Devise.pam_authentication
|
||||
user ||= User.find_for_authentication(email: user_params[:email])
|
||||
user
|
||||
end
|
||||
end
|
||||
|
||||
def user_params
|
||||
params.require(:user).permit(:email, :password, :otp_attempt)
|
||||
params.require(:user).permit(:email, :password, :otp_attempt, :sign_in_token_attempt)
|
||||
end
|
||||
|
||||
def after_sign_in_path_for(resource)
|
||||
@ -70,47 +72,6 @@ class Auth::SessionsController < Devise::SessionsController
|
||||
super
|
||||
end
|
||||
|
||||
def two_factor_enabled?
|
||||
find_user&.otp_required_for_login?
|
||||
end
|
||||
|
||||
def valid_otp_attempt?(user)
|
||||
user.validate_and_consume_otp!(user_params[:otp_attempt]) ||
|
||||
user.invalidate_otp_backup_code!(user_params[:otp_attempt])
|
||||
rescue OpenSSL::Cipher::CipherError
|
||||
false
|
||||
end
|
||||
|
||||
def authenticate_with_two_factor
|
||||
user = self.resource = find_user
|
||||
|
||||
if user_params[:otp_attempt].present? && session[:otp_user_id]
|
||||
authenticate_with_two_factor_via_otp(user)
|
||||
elsif user.present? && (user.encrypted_password.blank? || user.valid_password?(user_params[:password]))
|
||||
# If encrypted_password is blank, we got the user from LDAP or PAM,
|
||||
# so credentials are already valid
|
||||
|
||||
prompt_for_two_factor(user)
|
||||
end
|
||||
end
|
||||
|
||||
def authenticate_with_two_factor_via_otp(user)
|
||||
if valid_otp_attempt?(user)
|
||||
session.delete(:otp_user_id)
|
||||
remember_me(user)
|
||||
sign_in(user)
|
||||
else
|
||||
flash.now[:alert] = I18n.t('users.invalid_otp_token')
|
||||
prompt_for_two_factor(user)
|
||||
end
|
||||
end
|
||||
|
||||
def prompt_for_two_factor(user)
|
||||
session[:otp_user_id] = user.id
|
||||
@body_classes = 'lighter'
|
||||
render :two_factor
|
||||
end
|
||||
|
||||
def require_no_authentication
|
||||
super
|
||||
# Delete flash message that isn't entirely useful and may be confusing in
|
||||
|
@ -7,8 +7,6 @@ module Localized
|
||||
around_action :set_locale
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_locale
|
||||
locale = current_user.locale if respond_to?(:user_signed_in?) && user_signed_in?
|
||||
locale ||= session[:locale] ||= default_locale
|
||||
@ -19,6 +17,8 @@ module Localized
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def default_locale
|
||||
if ENV['DEFAULT_LOCALE'].present?
|
||||
I18n.default_locale
|
||||
|
@ -0,0 +1,51 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module SignInTokenAuthenticationConcern
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
prepend_before_action :authenticate_with_sign_in_token, if: :sign_in_token_required?, only: [:create]
|
||||
end
|
||||
|
||||
def sign_in_token_required?
|
||||
find_user&.suspicious_sign_in?(request.remote_ip)
|
||||
end
|
||||
|
||||
def valid_sign_in_token_attempt?(user)
|
||||
Devise.secure_compare(user.sign_in_token, user_params[:sign_in_token_attempt])
|
||||
end
|
||||
|
||||
def authenticate_with_sign_in_token
|
||||
user = self.resource = find_user
|
||||
|
||||
if user_params[:sign_in_token_attempt].present? && session[:attempt_user_id]
|
||||
authenticate_with_sign_in_token_attempt(user)
|
||||
elsif user.present? && user.external_or_valid_password?(user_params[:password])
|
||||
prompt_for_sign_in_token(user)
|
||||
end
|
||||
end
|
||||
|
||||
def authenticate_with_sign_in_token_attempt(user)
|
||||
if valid_sign_in_token_attempt?(user)
|
||||
session.delete(:attempt_user_id)
|
||||
remember_me(user)
|
||||
sign_in(user)
|
||||
else
|
||||
flash.now[:alert] = I18n.t('users.invalid_sign_in_token')
|
||||
prompt_for_sign_in_token(user)
|
||||
end
|
||||
end
|
||||
|
||||
def prompt_for_sign_in_token(user)
|
||||
if user.sign_in_token_expired?
|
||||
user.generate_sign_in_token && user.save
|
||||
UserMailer.sign_in_token(user, request.remote_ip, request.user_agent, Time.now.utc.to_s).deliver_later!
|
||||
end
|
||||
|
||||
set_locale do
|
||||
session[:attempt_user_id] = user.id
|
||||
@body_classes = 'lighter'
|
||||
render :sign_in_token
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,49 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module TwoFactorAuthenticationConcern
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
prepend_before_action :authenticate_with_two_factor, if: :two_factor_enabled?, only: [:create]
|
||||
end
|
||||
|
||||
def two_factor_enabled?
|
||||
find_user&.otp_required_for_login?
|
||||
end
|
||||
|
||||
def valid_otp_attempt?(user)
|
||||
user.validate_and_consume_otp!(user_params[:otp_attempt]) ||
|
||||
user.invalidate_otp_backup_code!(user_params[:otp_attempt])
|
||||
rescue OpenSSL::Cipher::CipherError
|
||||
false
|
||||
end
|
||||
|
||||
def authenticate_with_two_factor
|
||||
user = self.resource = find_user
|
||||
|
||||
if user_params[:otp_attempt].present? && session[:attempt_user_id]
|
||||
authenticate_with_two_factor_attempt(user)
|
||||
elsif user.present? && user.external_or_valid_password?(user_params[:password])
|
||||
prompt_for_two_factor(user)
|
||||
end
|
||||
end
|
||||
|
||||
def authenticate_with_two_factor_attempt(user)
|
||||
if valid_otp_attempt?(user)
|
||||
session.delete(:attempt_user_id)
|
||||
remember_me(user)
|
||||
sign_in(user)
|
||||
else
|
||||
flash.now[:alert] = I18n.t('users.invalid_otp_token')
|
||||
prompt_for_two_factor(user)
|
||||
end
|
||||
end
|
||||
|
||||
def prompt_for_two_factor(user)
|
||||
set_locale do
|
||||
session[:attempt_user_id] = user.id
|
||||
@body_classes = 'lighter'
|
||||
render :two_factor
|
||||
end
|
||||
end
|
||||
end
|
@ -9,7 +9,7 @@ class DirectoriesController < ApplicationController
|
||||
before_action :set_tag, only: :show
|
||||
before_action :set_accounts
|
||||
|
||||
skip_before_action :require_functional!
|
||||
skip_before_action :require_functional!, unless: :whitelist_mode?
|
||||
|
||||
def index
|
||||
render :index
|
||||
|
@ -8,7 +8,7 @@ class FollowerAccountsController < ApplicationController
|
||||
before_action :set_cache_headers
|
||||
|
||||
skip_around_action :set_locale, if: -> { request.format == :json }
|
||||
skip_before_action :require_functional!
|
||||
skip_before_action :require_functional!, unless: :whitelist_mode?
|
||||
|
||||
def index
|
||||
respond_to do |format|
|
||||
|
@ -8,7 +8,7 @@ class FollowingAccountsController < ApplicationController
|
||||
before_action :set_cache_headers
|
||||
|
||||
skip_around_action :set_locale, if: -> { request.format == :json }
|
||||
skip_before_action :require_functional!
|
||||
skip_before_action :require_functional!, unless: :whitelist_mode?
|
||||
|
||||
def index
|
||||
respond_to do |format|
|
||||
|
@ -4,7 +4,7 @@ class MediaController < ApplicationController
|
||||
include Authorization
|
||||
|
||||
skip_before_action :store_current_location
|
||||
skip_before_action :require_functional!
|
||||
skip_before_action :require_functional!, unless: :whitelist_mode?
|
||||
|
||||
before_action :authenticate_user!, if: :whitelist_mode?
|
||||
before_action :set_media_attachment
|
||||
|
@ -31,8 +31,8 @@ class MediaProxyController < ApplicationController
|
||||
private
|
||||
|
||||
def redownload!
|
||||
@media_attachment.file_remote_url = @media_attachment.remote_url
|
||||
@media_attachment.created_at = Time.now.utc
|
||||
@media_attachment.download_file!
|
||||
@media_attachment.created_at = Time.now.utc
|
||||
@media_attachment.save!
|
||||
end
|
||||
|
||||
|
@ -10,7 +10,7 @@ class RemoteInteractionController < ApplicationController
|
||||
before_action :set_status
|
||||
before_action :set_body_classes
|
||||
|
||||
skip_before_action :require_functional!
|
||||
skip_before_action :require_functional!, unless: :whitelist_mode?
|
||||
|
||||
def new
|
||||
@remote_follow = RemoteFollow.new(session_params)
|
||||
|
@ -18,7 +18,7 @@ class Settings::Migration::RedirectsController < Settings::BaseController
|
||||
if @redirect.valid_with_challenge?(current_user)
|
||||
current_account.update!(moved_to_account: @redirect.target_account)
|
||||
ActivityPub::UpdateDistributionWorker.perform_async(current_account.id)
|
||||
redirect_to settings_migration_path, notice: I18n.t('migrations.moved_msg', acct: current_account.moved_to_account.acct)
|
||||
redirect_to settings_migration_path, notice: I18n.t('migrations.redirected_msg', acct: current_account.moved_to_account.acct)
|
||||
else
|
||||
render :new
|
||||
end
|
||||
|
@ -7,13 +7,8 @@ module Settings
|
||||
before_action :set_picture
|
||||
|
||||
def destroy
|
||||
if valid_picture
|
||||
account_params = {
|
||||
@picture => nil,
|
||||
(@picture + '_remote_url') => nil,
|
||||
}
|
||||
|
||||
msg = UpdateAccountService.new.call(@account, account_params) ? I18n.t('generic.changes_saved_msg') : nil
|
||||
if valid_picture?
|
||||
msg = I18n.t('generic.changes_saved_msg') if UpdateAccountService.new.call(@account, { @picture => nil, "#{@picture}_remote_url" => '' })
|
||||
redirect_to settings_profile_path, notice: msg, status: 303
|
||||
else
|
||||
bad_request
|
||||
@ -30,8 +25,8 @@ module Settings
|
||||
@picture = params[:id]
|
||||
end
|
||||
|
||||
def valid_picture
|
||||
@picture == 'avatar' || @picture == 'header'
|
||||
def valid_picture?
|
||||
%w(avatar header).include?(@picture)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -19,7 +19,7 @@ class StatusesController < ApplicationController
|
||||
before_action :set_autoplay, only: :embed
|
||||
|
||||
skip_around_action :set_locale, if: -> { request.format == :json }
|
||||
skip_before_action :require_functional!, only: [:show, :embed]
|
||||
skip_before_action :require_functional!, only: [:show, :embed], unless: :whitelist_mode?
|
||||
|
||||
content_security_policy only: :embed do |p|
|
||||
p.frame_ancestors(false)
|
||||
@ -42,7 +42,7 @@ class StatusesController < ApplicationController
|
||||
|
||||
def activity
|
||||
expires_in 3.minutes, public: @status.distributable? && public_fetch_mode?
|
||||
render_with_cache json: @status, content_type: 'application/activity+json', serializer: ActivityPub::ActivitySerializer, adapter: ActivityPub::Adapter
|
||||
render_with_cache json: ActivityPub::ActivityPresenter.from_status(@status), content_type: 'application/activity+json', serializer: ActivityPub::ActivitySerializer, adapter: ActivityPub::Adapter
|
||||
end
|
||||
|
||||
def embed
|
||||
|
@ -3,7 +3,8 @@
|
||||
class TagsController < ApplicationController
|
||||
include SignatureVerification
|
||||
|
||||
PAGE_SIZE = 20
|
||||
PAGE_SIZE = 20
|
||||
PAGE_SIZE_MAX = 200
|
||||
|
||||
layout 'public'
|
||||
|
||||
@ -14,7 +15,7 @@ class TagsController < ApplicationController
|
||||
before_action :set_body_classes
|
||||
before_action :set_instance_presenter
|
||||
|
||||
skip_before_action :require_functional!
|
||||
skip_before_action :require_functional!, unless: :whitelist_mode?
|
||||
|
||||
def show
|
||||
respond_to do |format|
|
||||
@ -25,7 +26,8 @@ class TagsController < ApplicationController
|
||||
format.rss do
|
||||
expires_in 0, public: true
|
||||
|
||||
@statuses = HashtagQueryService.new.call(@tag, filter_params, nil, @local).limit(PAGE_SIZE)
|
||||
limit = params[:limit].present? ? [params[:limit].to_i, PAGE_SIZE_MAX].min : PAGE_SIZE
|
||||
@statuses = HashtagQueryService.new.call(@tag, filter_params, nil, @local).limit(limit)
|
||||
@statuses = cache_collection(@statuses, Status)
|
||||
|
||||
render xml: RSS::TagSerializer.render(@tag, @statuses)
|
||||
|
@ -8,7 +8,8 @@ module WellKnown
|
||||
before_action :set_account
|
||||
before_action :check_account_suspension
|
||||
|
||||
rescue_from ActiveRecord::RecordNotFound, ActionController::ParameterMissing, with: :not_found
|
||||
rescue_from ActiveRecord::RecordNotFound, with: :not_found
|
||||
rescue_from ActionController::ParameterMissing, WebfingerResource::InvalidRequest, with: :bad_request
|
||||
|
||||
def show
|
||||
expires_in 3.days, public: true
|
||||
@ -37,6 +38,10 @@ module WellKnown
|
||||
expires_in(3.minutes, public: true) && gone if @account.suspended?
|
||||
end
|
||||
|
||||
def bad_request
|
||||
head 400
|
||||
end
|
||||
|
||||
def not_found
|
||||
head 404
|
||||
end
|
||||
|
Reference in New Issue
Block a user