diff options
Diffstat (limited to 'app/controllers')
61 files changed, 421 insertions, 313 deletions
diff --git a/app/controllers/admin/account_actions_controller.rb b/app/controllers/admin/account_actions_controller.rb index 3f2e28b6a..e89404b60 100644 --- a/app/controllers/admin/account_actions_controller.rb +++ b/app/controllers/admin/account_actions_controller.rb @@ -21,7 +21,7 @@ module Admin account_action.save! if account_action.with_report? - redirect_to admin_reports_path + redirect_to admin_reports_path, notice: I18n.t('admin.reports.processed_msg', id: params[:report_id]) else redirect_to admin_account_path(@account.id) end diff --git a/app/controllers/admin/dashboard_controller.rb b/app/controllers/admin/dashboard_controller.rb index 924b623ad..099512248 100644 --- a/app/controllers/admin/dashboard_controller.rb +++ b/app/controllers/admin/dashboard_controller.rb @@ -18,13 +18,11 @@ module Admin private def redis_info - @redis_info ||= begin - if redis.is_a?(Redis::Namespace) - redis.redis.info - else - redis.info - end - end + @redis_info ||= if redis.is_a?(Redis::Namespace) + redis.redis.info + else + redis.info + end end end end diff --git a/app/controllers/admin/domain_blocks_controller.rb b/app/controllers/admin/domain_blocks_controller.rb index 74764640b..750f5c995 100644 --- a/app/controllers/admin/domain_blocks_controller.rb +++ b/app/controllers/admin/domain_blocks_controller.rb @@ -2,7 +2,7 @@ module Admin class DomainBlocksController < BaseController - before_action :set_domain_block, only: [:show, :destroy, :edit, :update] + before_action :set_domain_block, only: [:destroy, :edit, :update] def batch authorize :domain_block, :create? @@ -90,9 +90,7 @@ module Admin end def action_from_button - if params[:save] - 'save' - end + 'save' if params[:save] end end end diff --git a/app/controllers/admin/email_domain_blocks_controller.rb b/app/controllers/admin/email_domain_blocks_controller.rb index a0a43de19..4a3228ec3 100644 --- a/app/controllers/admin/email_domain_blocks_controller.rb +++ b/app/controllers/admin/email_domain_blocks_controller.rb @@ -2,8 +2,6 @@ module Admin class EmailDomainBlocksController < BaseController - before_action :set_email_domain_block, only: [:show, :destroy] - def index authorize :email_domain_block, :index? @@ -59,10 +57,6 @@ module Admin private - def set_email_domain_block - @email_domain_block = EmailDomainBlock.find(params[:id]) - end - def set_resolved_records Resolv::DNS.open do |dns| dns.timeouts = 5 diff --git a/app/controllers/admin/export_domain_allows_controller.rb b/app/controllers/admin/export_domain_allows_controller.rb index 57fb12c62..adfc39da2 100644 --- a/app/controllers/admin/export_domain_allows_controller.rb +++ b/app/controllers/admin/export_domain_allows_controller.rb @@ -23,9 +23,7 @@ module Admin @import = Admin::Import.new(import_params) return render :new unless @import.validate - parse_import_data!(export_headers) - - @data.take(Admin::Import::ROWS_PROCESSING_LIMIT).each do |row| + @import.csv_rows.each do |row| domain = row['#domain'].strip next if DomainAllow.allowed?(domain) diff --git a/app/controllers/admin/export_domain_blocks_controller.rb b/app/controllers/admin/export_domain_blocks_controller.rb index fb0cd05d2..816422d4f 100644 --- a/app/controllers/admin/export_domain_blocks_controller.rb +++ b/app/controllers/admin/export_domain_blocks_controller.rb @@ -23,24 +23,30 @@ module Admin @import = Admin::Import.new(import_params) return render :new unless @import.validate - parse_import_data!(export_headers) - @global_private_comment = I18n.t('admin.export_domain_blocks.import.private_comment_template', source: @import.data_file_name, date: I18n.l(Time.now.utc)) @form = Form::DomainBlockBatch.new - @domain_blocks = @data.take(Admin::Import::ROWS_PROCESSING_LIMIT).filter_map do |row| + @domain_blocks = @import.csv_rows.filter_map do |row| domain = row['#domain'].strip next if DomainBlock.rule_for(domain).present? domain_block = DomainBlock.new(domain: domain, - severity: row['#severity'].strip, - reject_media: row['#reject_media'].strip, - reject_reports: row['#reject_reports'].strip, + severity: row.fetch('#severity', :suspend), + reject_media: row.fetch('#reject_media', false), + reject_reports: row.fetch('#reject_reports', false), private_comment: @global_private_comment, - public_comment: row['#public_comment']&.strip, - obfuscate: row['#obfuscate'].strip) + public_comment: row['#public_comment'], + obfuscate: row.fetch('#obfuscate', false)) + + if domain_block.invalid? + flash.now[:alert] = I18n.t('admin.export_domain_blocks.invalid_domain_block', error: domain_block.errors.full_messages.join(', ')) + next + end - domain_block if domain_block.valid? + domain_block + rescue ArgumentError => e + flash.now[:alert] = I18n.t('admin.export_domain_blocks.invalid_domain_block', error: e.message) + next end @warning_domains = Instance.where(domain: @domain_blocks.map(&:domain)).where('EXISTS (SELECT 1 FROM follows JOIN accounts ON follows.account_id = accounts.id OR follows.target_account_id = accounts.id WHERE accounts.domain = instances.domain)').pluck(:domain) diff --git a/app/controllers/admin/reports/actions_controller.rb b/app/controllers/admin/reports/actions_controller.rb index 5cb5c744f..554f7906f 100644 --- a/app/controllers/admin/reports/actions_controller.rb +++ b/app/controllers/admin/reports/actions_controller.rb @@ -3,6 +3,11 @@ class Admin::Reports::ActionsController < Admin::BaseController before_action :set_report + def preview + authorize @report, :show? + @moderation_action = action_from_button + end + def create authorize @report, :show? @@ -13,7 +18,8 @@ class Admin::Reports::ActionsController < Admin::BaseController status_ids: @report.status_ids, current_account: current_account, report_id: @report.id, - send_email_notification: !@report.spam? + send_email_notification: !@report.spam?, + text: params[:text] ) status_batch_action.save! @@ -23,13 +29,16 @@ class Admin::Reports::ActionsController < Admin::BaseController report_id: @report.id, target_account: @report.target_account, current_account: current_account, - send_email_notification: !@report.spam? + send_email_notification: !@report.spam?, + text: params[:text] ) account_action.save! + else + return redirect_to admin_report_path(@report), alert: I18n.t('admin.reports.unknown_action_msg', action: action_from_button) end - redirect_to admin_reports_path + redirect_to admin_reports_path, notice: I18n.t('admin.reports.processed_msg', id: @report.id) end private @@ -47,6 +56,8 @@ class Admin::Reports::ActionsController < Admin::BaseController 'silence' elsif params[:suspend] 'suspend' + elsif params[:moderation_action] + params[:moderation_action] end end end diff --git a/app/controllers/api/v1/accounts/credentials_controller.rb b/app/controllers/api/v1/accounts/credentials_controller.rb index 94b707771..7c7d70fd3 100644 --- a/app/controllers/api/v1/accounts/credentials_controller.rb +++ b/app/controllers/api/v1/accounts/credentials_controller.rb @@ -13,7 +13,7 @@ class Api::V1::Accounts::CredentialsController < Api::BaseController def update @account = current_account UpdateAccountService.new.call(@account, account_params, raise_error: true) - UserSettingsDecorator.new(current_user).update(user_settings_params) if user_settings_params + current_user.update(user_params) if user_params ActivityPub::UpdateDistributionWorker.perform_async(@account.id) render json: @account, serializer: REST::CredentialAccountSerializer end @@ -34,15 +34,17 @@ class Api::V1::Accounts::CredentialsController < Api::BaseController ) end - def user_settings_params + def user_params return nil if params[:source].blank? source_params = params.require(:source) { - 'setting_default_privacy' => source_params.fetch(:privacy, @account.user.setting_default_privacy), - 'setting_default_sensitive' => source_params.fetch(:sensitive, @account.user.setting_default_sensitive), - 'setting_default_language' => source_params.fetch(:language, @account.user.setting_default_language), + settings_attributes: { + default_privacy: source_params.fetch(:privacy, @account.user.setting_default_privacy), + default_sensitive: source_params.fetch(:sensitive, @account.user.setting_default_sensitive), + default_language: source_params.fetch(:language, @account.user.setting_default_language), + }, } end end diff --git a/app/controllers/api/v1/accounts/follower_accounts_controller.rb b/app/controllers/api/v1/accounts/follower_accounts_controller.rb index 208e06ed6..0daa3fe1e 100644 --- a/app/controllers/api/v1/accounts/follower_accounts_controller.rb +++ b/app/controllers/api/v1/accounts/follower_accounts_controller.rb @@ -45,15 +45,11 @@ class Api::V1::Accounts::FollowerAccountsController < Api::BaseController end def next_path - if records_continue? - api_v1_account_followers_url pagination_params(max_id: pagination_max_id) - end + api_v1_account_followers_url pagination_params(max_id: pagination_max_id) if records_continue? end def prev_path - unless @accounts.empty? - api_v1_account_followers_url pagination_params(since_id: pagination_since_id) - end + api_v1_account_followers_url pagination_params(since_id: pagination_since_id) unless @accounts.empty? end def pagination_max_id diff --git a/app/controllers/api/v1/accounts/following_accounts_controller.rb b/app/controllers/api/v1/accounts/following_accounts_controller.rb index 155ca0907..abac80557 100644 --- a/app/controllers/api/v1/accounts/following_accounts_controller.rb +++ b/app/controllers/api/v1/accounts/following_accounts_controller.rb @@ -45,15 +45,11 @@ class Api::V1::Accounts::FollowingAccountsController < Api::BaseController end def next_path - if records_continue? - api_v1_account_following_index_url pagination_params(max_id: pagination_max_id) - end + api_v1_account_following_index_url pagination_params(max_id: pagination_max_id) if records_continue? end def prev_path - unless @accounts.empty? - api_v1_account_following_index_url pagination_params(since_id: pagination_since_id) - end + api_v1_account_following_index_url pagination_params(since_id: pagination_since_id) unless @accounts.empty? end def pagination_max_id diff --git a/app/controllers/api/v1/accounts/statuses_controller.rb b/app/controllers/api/v1/accounts/statuses_controller.rb index a68d266a7..58e668dca 100644 --- a/app/controllers/api/v1/accounts/statuses_controller.rb +++ b/app/controllers/api/v1/accounts/statuses_controller.rb @@ -40,15 +40,11 @@ class Api::V1::Accounts::StatusesController < Api::BaseController end def next_path - if records_continue? - api_v1_account_statuses_url pagination_params(max_id: pagination_max_id) - end + api_v1_account_statuses_url pagination_params(max_id: pagination_max_id) if records_continue? end def prev_path - unless @statuses.empty? - api_v1_account_statuses_url pagination_params(min_id: pagination_since_id) - end + api_v1_account_statuses_url pagination_params(min_id: pagination_since_id) unless @statuses.empty? end def records_continue? diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb index be84720aa..7dff66efa 100644 --- a/app/controllers/api/v1/accounts_controller.rb +++ b/app/controllers/api/v1/accounts_controller.rb @@ -30,7 +30,7 @@ class Api::V1::AccountsController < Api::BaseController self.response_body = Oj.dump(response.body) self.status = response.status rescue ActiveRecord::RecordInvalid => e - render json: ValidationErrorFormatter.new(e, 'account.username': :username, 'invite_request.text': :reason).as_json, status: :unprocessable_entity + render json: ValidationErrorFormatter.new(e, 'account.username': :username, 'invite_request.text': :reason).as_json, status: 422 end def follow diff --git a/app/controllers/api/v1/admin/accounts_controller.rb b/app/controllers/api/v1/admin/accounts_controller.rb index f48300072..ff9cae639 100644 --- a/app/controllers/api/v1/admin/accounts_controller.rb +++ b/app/controllers/api/v1/admin/accounts_controller.rb @@ -120,9 +120,7 @@ class Api::V1::Admin::AccountsController < Api::BaseController translated_params[:status] = status.to_s if params[status].present? end - if params[:staff].present? - translated_params[:role_ids] = UserRole.that_can(:manage_reports).map(&:id) - end + translated_params[:role_ids] = UserRole.that_can(:manage_reports).map(&:id) if params[:staff].present? translated_params end diff --git a/app/controllers/api/v1/admin/trends/tags_controller.rb b/app/controllers/api/v1/admin/trends/tags_controller.rb index f3c0c4b6b..e77df3021 100644 --- a/app/controllers/api/v1/admin/trends/tags_controller.rb +++ b/app/controllers/api/v1/admin/trends/tags_controller.rb @@ -3,6 +3,14 @@ class Api::V1::Admin::Trends::TagsController < Api::V1::Trends::TagsController before_action -> { authorize_if_got_token! :'admin:read' } + def index + if current_user&.can?(:manage_taxonomies) + render json: @tags, each_serializer: REST::Admin::TagSerializer + else + super + end + end + private def enabled? diff --git a/app/controllers/api/v1/announcements_controller.rb b/app/controllers/api/v1/announcements_controller.rb index ee79fc19f..82e9cf7de 100644 --- a/app/controllers/api/v1/announcements_controller.rb +++ b/app/controllers/api/v1/announcements_controller.rb @@ -18,9 +18,7 @@ class Api::V1::AnnouncementsController < Api::BaseController private def set_announcements - @announcements = begin - Announcement.published.chronological - end + @announcements = Announcement.published.chronological end def set_announcement diff --git a/app/controllers/api/v1/blocks_controller.rb b/app/controllers/api/v1/blocks_controller.rb index a65e762c9..06a8bfa89 100644 --- a/app/controllers/api/v1/blocks_controller.rb +++ b/app/controllers/api/v1/blocks_controller.rb @@ -33,15 +33,11 @@ class Api::V1::BlocksController < Api::BaseController end def next_path - if records_continue? - api_v1_blocks_url pagination_params(max_id: pagination_max_id) - end + api_v1_blocks_url pagination_params(max_id: pagination_max_id) if records_continue? end def prev_path - unless paginated_blocks.empty? - api_v1_blocks_url pagination_params(since_id: pagination_since_id) - end + api_v1_blocks_url pagination_params(since_id: pagination_since_id) unless paginated_blocks.empty? end def pagination_max_id diff --git a/app/controllers/api/v1/conversations_controller.rb b/app/controllers/api/v1/conversations_controller.rb index 6c7583403..9034e8a2f 100644 --- a/app/controllers/api/v1/conversations_controller.rb +++ b/app/controllers/api/v1/conversations_controller.rb @@ -40,15 +40,11 @@ class Api::V1::ConversationsController < Api::BaseController end def next_path - if records_continue? - api_v1_conversations_url pagination_params(max_id: pagination_max_id) - end + api_v1_conversations_url pagination_params(max_id: pagination_max_id) if records_continue? end def prev_path - unless @conversations.empty? - api_v1_conversations_url pagination_params(min_id: pagination_since_id) - end + api_v1_conversations_url pagination_params(min_id: pagination_since_id) unless @conversations.empty? end def pagination_max_id diff --git a/app/controllers/api/v1/domain_blocks_controller.rb b/app/controllers/api/v1/domain_blocks_controller.rb index 1891261b9..34def3c44 100644 --- a/app/controllers/api/v1/domain_blocks_controller.rb +++ b/app/controllers/api/v1/domain_blocks_controller.rb @@ -43,15 +43,11 @@ class Api::V1::DomainBlocksController < Api::BaseController end def next_path - if records_continue? - api_v1_domain_blocks_url pagination_params(max_id: pagination_max_id) - end + api_v1_domain_blocks_url pagination_params(max_id: pagination_max_id) if records_continue? end def prev_path - unless @blocks.empty? - api_v1_domain_blocks_url pagination_params(since_id: pagination_since_id) - end + api_v1_domain_blocks_url pagination_params(since_id: pagination_since_id) unless @blocks.empty? end def pagination_max_id diff --git a/app/controllers/api/v1/emails/confirmations_controller.rb b/app/controllers/api/v1/emails/confirmations_controller.rb index 3faaea2fb..32fb8e39f 100644 --- a/app/controllers/api/v1/emails/confirmations_controller.rb +++ b/app/controllers/api/v1/emails/confirmations_controller.rb @@ -15,10 +15,10 @@ class Api::V1::Emails::ConfirmationsController < Api::BaseController private def require_user_owned_by_application! - render json: { error: 'This method is only available to the application the user originally signed-up with' }, status: :forbidden unless current_user && current_user.created_by_application_id == doorkeeper_token.application_id + render json: { error: 'This method is only available to the application the user originally signed-up with' }, status: 403 unless current_user && current_user.created_by_application_id == doorkeeper_token.application_id end def require_user_not_confirmed! - render json: { error: 'This method is only available while the e-mail is awaiting confirmation' }, status: :forbidden unless !current_user.confirmed? || current_user.unconfirmed_email.present? + render json: { error: 'This method is only available while the e-mail is awaiting confirmation' }, status: 403 unless !current_user.confirmed? || current_user.unconfirmed_email.present? end end diff --git a/app/controllers/api/v1/endorsements_controller.rb b/app/controllers/api/v1/endorsements_controller.rb index 9e80f468a..46e3fcd64 100644 --- a/app/controllers/api/v1/endorsements_controller.rb +++ b/app/controllers/api/v1/endorsements_controller.rb @@ -35,17 +35,13 @@ class Api::V1::EndorsementsController < Api::BaseController def next_path return if unlimited? - if records_continue? - api_v1_endorsements_url pagination_params(max_id: pagination_max_id) - end + api_v1_endorsements_url pagination_params(max_id: pagination_max_id) if records_continue? end def prev_path return if unlimited? - unless @accounts.empty? - api_v1_endorsements_url pagination_params(since_id: pagination_since_id) - end + api_v1_endorsements_url pagination_params(since_id: pagination_since_id) unless @accounts.empty? end def pagination_max_id diff --git a/app/controllers/api/v1/favourites_controller.rb b/app/controllers/api/v1/favourites_controller.rb index 2a873696c..bd7f3d775 100644 --- a/app/controllers/api/v1/favourites_controller.rb +++ b/app/controllers/api/v1/favourites_controller.rb @@ -36,15 +36,11 @@ class Api::V1::FavouritesController < Api::BaseController end def next_path - if records_continue? - api_v1_favourites_url pagination_params(max_id: pagination_max_id) - end + api_v1_favourites_url pagination_params(max_id: pagination_max_id) if records_continue? end def prev_path - unless results.empty? - api_v1_favourites_url pagination_params(min_id: pagination_since_id) - end + api_v1_favourites_url pagination_params(min_id: pagination_since_id) unless results.empty? end def pagination_max_id diff --git a/app/controllers/api/v1/follow_requests_controller.rb b/app/controllers/api/v1/follow_requests_controller.rb index 54ff0e11d..7c197ce6b 100644 --- a/app/controllers/api/v1/follow_requests_controller.rb +++ b/app/controllers/api/v1/follow_requests_controller.rb @@ -53,15 +53,11 @@ class Api::V1::FollowRequestsController < Api::BaseController end def next_path - if records_continue? - api_v1_follow_requests_url pagination_params(max_id: pagination_max_id) - end + api_v1_follow_requests_url pagination_params(max_id: pagination_max_id) if records_continue? end def prev_path - unless @accounts.empty? - api_v1_follow_requests_url pagination_params(since_id: pagination_since_id) - end + api_v1_follow_requests_url pagination_params(since_id: pagination_since_id) unless @accounts.empty? end def pagination_max_id diff --git a/app/controllers/api/v1/instances/translation_languages_controller.rb b/app/controllers/api/v1/instances/translation_languages_controller.rb new file mode 100644 index 000000000..3910a499e --- /dev/null +++ b/app/controllers/api/v1/instances/translation_languages_controller.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +class Api::V1::Instances::TranslationLanguagesController < Api::BaseController + skip_before_action :require_authenticated_user!, unless: :whitelist_mode? + + before_action :set_languages + + def show + expires_in 1.day, public: true + render json: @languages + end + + private + + def set_languages + if TranslationService.configured? + @languages = Rails.cache.fetch('translation_service/languages', expires_in: 7.days, race_condition_ttl: 1.hour) { TranslationService.configured.languages } + @languages['und'] = @languages.delete(nil) if @languages.key?(nil) + else + @languages = {} + end + end +end diff --git a/app/controllers/api/v1/lists/accounts_controller.rb b/app/controllers/api/v1/lists/accounts_controller.rb index b66ea9bfe..8e12cb7b6 100644 --- a/app/controllers/api/v1/lists/accounts_controller.rb +++ b/app/controllers/api/v1/lists/accounts_controller.rb @@ -62,17 +62,13 @@ class Api::V1::Lists::AccountsController < Api::BaseController def next_path return if unlimited? - if records_continue? - api_v1_list_accounts_url pagination_params(max_id: pagination_max_id) - end + api_v1_list_accounts_url pagination_params(max_id: pagination_max_id) if records_continue? end def prev_path return if unlimited? - unless @accounts.empty? - api_v1_list_accounts_url pagination_params(since_id: pagination_since_id) - end + api_v1_list_accounts_url pagination_params(since_id: pagination_since_id) unless @accounts.empty? end def pagination_max_id diff --git a/app/controllers/api/v1/mutes_controller.rb b/app/controllers/api/v1/mutes_controller.rb index 6cde53a2a..555485823 100644 --- a/app/controllers/api/v1/mutes_controller.rb +++ b/app/controllers/api/v1/mutes_controller.rb @@ -33,15 +33,11 @@ class Api::V1::MutesController < Api::BaseController end def next_path - if records_continue? - api_v1_mutes_url pagination_params(max_id: pagination_max_id) - end + api_v1_mutes_url pagination_params(max_id: pagination_max_id) if records_continue? end def prev_path - unless paginated_mutes.empty? - api_v1_mutes_url pagination_params(since_id: pagination_since_id) - end + api_v1_mutes_url pagination_params(since_id: pagination_since_id) unless paginated_mutes.empty? end def pagination_max_id diff --git a/app/controllers/api/v1/notifications_controller.rb b/app/controllers/api/v1/notifications_controller.rb index a6ed359c9..7a64d1300 100644 --- a/app/controllers/api/v1/notifications_controller.rb +++ b/app/controllers/api/v1/notifications_controller.rb @@ -6,7 +6,7 @@ class Api::V1::NotificationsController < Api::BaseController before_action :require_user! after_action :insert_pagination_headers, only: :index - DEFAULT_NOTIFICATIONS_LIMIT = 15 + DEFAULT_NOTIFICATIONS_LIMIT = 40 def index @notifications = load_notifications @@ -28,7 +28,7 @@ class Api::V1::NotificationsController < Api::BaseController end def dismiss - current_account.notifications.find_by!(id: params[:id]).destroy! + current_account.notifications.find(params[:id]).destroy! render_empty end @@ -67,15 +67,11 @@ class Api::V1::NotificationsController < Api::BaseController end def next_path - unless @notifications.empty? - api_v1_notifications_url pagination_params(max_id: pagination_max_id) - end + api_v1_notifications_url pagination_params(max_id: pagination_max_id) unless @notifications.empty? end def prev_path - unless @notifications.empty? - api_v1_notifications_url pagination_params(min_id: pagination_since_id) - end + api_v1_notifications_url pagination_params(min_id: pagination_since_id) unless @notifications.empty? end def pagination_max_id diff --git a/app/controllers/api/v1/scheduled_statuses_controller.rb b/app/controllers/api/v1/scheduled_statuses_controller.rb index f90642a73..2220b6d22 100644 --- a/app/controllers/api/v1/scheduled_statuses_controller.rb +++ b/app/controllers/api/v1/scheduled_statuses_controller.rb @@ -52,15 +52,11 @@ class Api::V1::ScheduledStatusesController < Api::BaseController end def next_path - if records_continue? - api_v1_scheduled_statuses_url pagination_params(max_id: pagination_max_id) - end + api_v1_scheduled_statuses_url pagination_params(max_id: pagination_max_id) if records_continue? end def prev_path - unless @statuses.empty? - api_v1_scheduled_statuses_url pagination_params(min_id: pagination_since_id) - end + api_v1_scheduled_statuses_url pagination_params(min_id: pagination_since_id) unless @statuses.empty? end def records_continue? diff --git a/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb b/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb index 2b614a837..b138fa265 100644 --- a/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb +++ b/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb @@ -41,15 +41,11 @@ class Api::V1::Statuses::FavouritedByAccountsController < Api::BaseController end def next_path - if records_continue? - api_v1_status_favourited_by_index_url pagination_params(max_id: pagination_max_id) - end + api_v1_status_favourited_by_index_url pagination_params(max_id: pagination_max_id) if records_continue? end def prev_path - unless @accounts.empty? - api_v1_status_favourited_by_index_url pagination_params(since_id: pagination_since_id) - end + api_v1_status_favourited_by_index_url pagination_params(since_id: pagination_since_id) unless @accounts.empty? end def pagination_max_id diff --git a/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb b/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb index 24db30fcc..4b545f982 100644 --- a/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb +++ b/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb @@ -37,15 +37,11 @@ class Api::V1::Statuses::RebloggedByAccountsController < Api::BaseController end def next_path - if records_continue? - api_v1_status_reblogged_by_index_url pagination_params(max_id: pagination_max_id) - end + api_v1_status_reblogged_by_index_url pagination_params(max_id: pagination_max_id) if records_continue? end def prev_path - unless @accounts.empty? - api_v1_status_reblogged_by_index_url pagination_params(since_id: pagination_since_id) - end + api_v1_status_reblogged_by_index_url pagination_params(since_id: pagination_since_id) unless @accounts.empty? end def pagination_max_id diff --git a/app/controllers/api/v1/statuses_controller.rb b/app/controllers/api/v1/statuses_controller.rb index e2e48f633..8dcf6331e 100644 --- a/app/controllers/api/v1/statuses_controller.rb +++ b/app/controllers/api/v1/statuses_controller.rb @@ -64,11 +64,18 @@ class Api::V1::StatusesController < Api::BaseController application: doorkeeper_token.application, poll: status_params[:poll], content_type: status_params[:content_type], + allowed_mentions: status_params[:allowed_mentions], idempotency: request.headers['Idempotency-Key'], with_rate_limit: true ) render json: @status, serializer: @status.is_a?(ScheduledStatus) ? REST::ScheduledStatusSerializer : REST::StatusSerializer + rescue PostStatusService::UnexpectedMentionsError => e + unexpected_accounts = ActiveModel::Serializer::CollectionSerializer.new( + e.accounts, + serializer: REST::AccountSerializer + ) + render json: { error: e.message, unexpected_accounts: unexpected_accounts }, status: 422 end def update @@ -80,6 +87,7 @@ class Api::V1::StatusesController < Api::BaseController current_account.id, text: status_params[:status], media_ids: status_params[:media_ids], + media_attributes: status_params[:media_attributes], sensitive: status_params[:sensitive], language: status_params[:language], spoiler_text: status_params[:spoiler_text], @@ -130,7 +138,14 @@ class Api::V1::StatusesController < Api::BaseController :language, :scheduled_at, :content_type, + allowed_mentions: [], media_ids: [], + media_attributes: [ + :id, + :thumbnail, + :description, + :focus, + ], poll: [ :multiple, :hide_totals, diff --git a/app/controllers/api/v1/streaming_controller.rb b/app/controllers/api/v1/streaming_controller.rb index 7cd60615a..0cdd00d62 100644 --- a/app/controllers/api/v1/streaming_controller.rb +++ b/app/controllers/api/v1/streaming_controller.rb @@ -2,10 +2,10 @@ class Api::V1::StreamingController < Api::BaseController def index - if Rails.configuration.x.streaming_api_base_url != request.host - redirect_to streaming_api_url, status: 301 - else + if Rails.configuration.x.streaming_api_base_url == request.host not_found + else + redirect_to streaming_api_url, status: 301, allow_other_host: true end end diff --git a/app/controllers/api/v1/tags_controller.rb b/app/controllers/api/v1/tags_controller.rb index 272362c31..a08fd2187 100644 --- a/app/controllers/api/v1/tags_controller.rb +++ b/app/controllers/api/v1/tags_controller.rb @@ -25,6 +25,7 @@ class Api::V1::TagsController < Api::BaseController def set_or_create_tag return not_found unless Tag::HASHTAG_NAME_RE.match?(params[:id]) + @tag = Tag.find_normalized(params[:id]) || Tag.new(name: Tag.normalize(params[:id]), display_name: params[:id]) end end diff --git a/app/controllers/api/v1/timelines/public_controller.rb b/app/controllers/api/v1/timelines/public_controller.rb index 493fe4776..4675af921 100644 --- a/app/controllers/api/v1/timelines/public_controller.rb +++ b/app/controllers/api/v1/timelines/public_controller.rb @@ -40,7 +40,7 @@ class Api::V1::Timelines::PublicController < Api::BaseController only_media: truthy_param?(:only_media), allow_local_only: truthy_param?(:allow_local_only), with_replies: Setting.show_replies_in_public_timelines, - with_reblogs: Setting.show_reblogs_in_public_timelines, + with_reblogs: Setting.show_reblogs_in_public_timelines ) end diff --git a/app/controllers/api/v1/trends/links_controller.rb b/app/controllers/api/v1/trends/links_controller.rb index 8ff3b364e..3ce20fb78 100644 --- a/app/controllers/api/v1/trends/links_controller.rb +++ b/app/controllers/api/v1/trends/links_controller.rb @@ -18,13 +18,11 @@ class Api::V1::Trends::LinksController < Api::BaseController end def set_links - @links = begin - if enabled? - links_from_trends.offset(offset_param).limit(limit_param(DEFAULT_LINKS_LIMIT)) - else - [] - end - end + @links = if enabled? + links_from_trends.offset(offset_param).limit(limit_param(DEFAULT_LINKS_LIMIT)) + else + [] + end end def links_from_trends diff --git a/app/controllers/api/v1/trends/statuses_controller.rb b/app/controllers/api/v1/trends/statuses_controller.rb index c275d5fc8..3aab92477 100644 --- a/app/controllers/api/v1/trends/statuses_controller.rb +++ b/app/controllers/api/v1/trends/statuses_controller.rb @@ -16,13 +16,11 @@ class Api::V1::Trends::StatusesController < Api::BaseController end def set_statuses - @statuses = begin - if enabled? - cache_collection(statuses_from_trends.offset(offset_param).limit(limit_param(DEFAULT_STATUSES_LIMIT)), Status) - else - [] - end - end + @statuses = if enabled? + cache_collection(statuses_from_trends.offset(offset_param).limit(limit_param(DEFAULT_STATUSES_LIMIT)), Status) + else + [] + end end def statuses_from_trends diff --git a/app/controllers/api/v1/trends/tags_controller.rb b/app/controllers/api/v1/trends/tags_controller.rb index 885a4ad7e..9dd9abdfe 100644 --- a/app/controllers/api/v1/trends/tags_controller.rb +++ b/app/controllers/api/v1/trends/tags_controller.rb @@ -18,13 +18,11 @@ class Api::V1::Trends::TagsController < Api::BaseController end def set_tags - @tags = begin - if enabled? - tags_from_trends.offset(offset_param).limit(limit_param(DEFAULT_TAGS_LIMIT)) - else - [] - end - end + @tags = if enabled? + tags_from_trends.offset(offset_param).limit(limit_param(DEFAULT_TAGS_LIMIT)) + else + [] + end end def tags_from_trends diff --git a/app/controllers/api/v2/admin/accounts_controller.rb b/app/controllers/api/v2/admin/accounts_controller.rb index b25831aa0..0c451f778 100644 --- a/app/controllers/api/v2/admin/accounts_controller.rb +++ b/app/controllers/api/v2/admin/accounts_controller.rb @@ -25,9 +25,7 @@ class Api::V2::Admin::AccountsController < Api::V1::Admin::AccountsController def translated_filter_params translated_params = filter_params.slice(*AccountFilter::KEYS) - if params[:permissions] == 'staff' - translated_params[:role_ids] = UserRole.that_can(:manage_reports).map(&:id) - end + translated_params[:role_ids] = UserRole.that_can(:manage_reports).map(&:id) if params[:permissions] == 'staff' translated_params end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index ee3c5204d..906761f6f 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -18,6 +18,8 @@ class ApplicationController < ActionController::Base helper_method :current_skin helper_method :single_user_mode? helper_method :use_seamless_external_login? + helper_method :omniauth_only? + helper_method :sso_account_settings helper_method :whitelist_mode? rescue_from ActionController::ParameterMissing, Paperclip::AdapterRegistry::NoHandlerError, with: :bad_request @@ -63,7 +65,11 @@ class ApplicationController < ActionController::Base end def after_sign_out_path_for(_resource_or_scope) - new_user_session_path + if ENV['OMNIAUTH_ONLY'] == 'true' && ENV['OIDC_ENABLED'] == 'true' + '/auth/auth/openid_connect/logout' + else + new_user_session_path + end end protected @@ -116,6 +122,14 @@ class ApplicationController < ActionController::Base Devise.pam_authentication || Devise.ldap_authentication end + def omniauth_only? + ENV['OMNIAUTH_ONLY'] == 'true' + end + + def sso_account_settings + ENV.fetch('SSO_ACCOUNT_SETTINGS') + end + def current_account return @current_account if defined?(@current_account) diff --git a/app/controllers/auth/confirmations_controller.rb b/app/controllers/auth/confirmations_controller.rb index 0817a905c..620fb621d 100644 --- a/app/controllers/auth/confirmations_controller.rb +++ b/app/controllers/auth/confirmations_controller.rb @@ -15,12 +15,6 @@ class Auth::ConfirmationsController < Devise::ConfirmationsController skip_before_action :require_functional! - def new - super - - resource.email = current_user.unconfirmed_email || current_user.email if user_signed_in? - end - def show old_session_values = session.to_hash reset_session @@ -29,6 +23,12 @@ class Auth::ConfirmationsController < Devise::ConfirmationsController super end + def new + super + + resource.email = current_user.unconfirmed_email || current_user.email if user_signed_in? + end + def confirm_captcha check_captcha! do |message| flash.now[:alert] = message @@ -51,6 +51,7 @@ class Auth::ConfirmationsController < Devise::ConfirmationsController # step. confirmation_token = params[:confirmation_token] return if confirmation_token.nil? + @confirmation_user = User.find_first_by_auth_conditions(confirmation_token: confirmation_token) end diff --git a/app/controllers/auth/omniauth_callbacks_controller.rb b/app/controllers/auth/omniauth_callbacks_controller.rb index 3d7962de5..9e0fb942a 100644 --- a/app/controllers/auth/omniauth_callbacks_controller.rb +++ b/app/controllers/auth/omniauth_callbacks_controller.rb @@ -33,7 +33,7 @@ class Auth::OmniauthCallbacksController < Devise::OmniauthCallbacksController def after_sign_in_path_for(resource) if resource.email_present? - root_path + stored_location_for(resource) || root_path else auth_setup_path(missing_email: '1') end diff --git a/app/controllers/auth/registrations_controller.rb b/app/controllers/auth/registrations_controller.rb index 40c38bc6d..d2f1bea93 100644 --- a/app/controllers/auth/registrations_controller.rb +++ b/app/controllers/auth/registrations_controller.rb @@ -31,9 +31,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController def update super do |resource| - if resource.saved_change_to_encrypted_password? - resource.clear_other_sessions(current_session.session_id) - end + resource.clear_other_sessions(current_session.session_id) if resource.saved_change_to_encrypted_password? end end @@ -49,7 +47,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController super(hash) resource.locale = I18n.locale - resource.invite_code = params[:invite_code] if resource.invite_code.blank? + resource.invite_code = @invite&.code if resource.invite_code.blank? resource.registration_form_time = session[:registration_form_time] resource.sign_up_ip = request.remote_ip diff --git a/app/controllers/auth/sessions_controller.rb b/app/controllers/auth/sessions_controller.rb index 16c18baa2..b1abb9f1d 100644 --- a/app/controllers/auth/sessions_controller.rb +++ b/app/controllers/auth/sessions_controller.rb @@ -53,9 +53,9 @@ class Auth::SessionsController < Devise::SessionsController session[:webauthn_challenge] = options_for_get.challenge - render json: options_for_get, status: :ok + render json: options_for_get, status: 200 else - render json: { error: t('webauthn_credentials.not_enabled') }, status: :unauthorized + render json: { error: t('webauthn_credentials.not_enabled') }, status: 401 end end @@ -115,9 +115,7 @@ class Auth::SessionsController < Devise::SessionsController def home_paths(resource) paths = [about_path] - if single_user_mode? && resource.is_a?(User) - paths << short_account_path(username: resource.account) - end + paths << short_account_path(username: resource.account) if single_user_mode? && resource.is_a?(User) paths end diff --git a/app/controllers/backups_controller.rb b/app/controllers/backups_controller.rb new file mode 100644 index 000000000..5891da6f6 --- /dev/null +++ b/app/controllers/backups_controller.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +class BackupsController < ApplicationController + include RoutingHelper + + skip_before_action :require_functional! + + before_action :authenticate_user! + before_action :set_backup + + def download + case Paperclip::Attachment.default_options[:storage] + when :s3 + redirect_to @backup.dump.expiring_url(10) + when :fog + if Paperclip::Attachment.default_options.dig(:fog_credentials, :openstack_temp_url_key).present? + redirect_to @backup.dump.expiring_url(Time.now.utc + 10) + else + redirect_to full_asset_url(@backup.dump.url) + end + when :filesystem + redirect_to full_asset_url(@backup.dump.url) + end + end + + private + + def set_backup + @backup = current_user.backups.find(params[:id]) + end +end diff --git a/app/controllers/concerns/account_controller_concern.rb b/app/controllers/concerns/account_controller_concern.rb index 2f7d84df0..e9cff22ca 100644 --- a/app/controllers/concerns/account_controller_concern.rb +++ b/app/controllers/concerns/account_controller_concern.rb @@ -10,7 +10,8 @@ module AccountControllerConcern included do before_action :set_instance_presenter - before_action :set_link_headers, if: -> { request.format.nil? || request.format == :html } + + after_action :set_link_headers, if: -> { request.format.nil? || request.format == :html } end private diff --git a/app/controllers/concerns/admin_export_controller_concern.rb b/app/controllers/concerns/admin_export_controller_concern.rb index b40c76557..4ac48a04b 100644 --- a/app/controllers/concerns/admin_export_controller_concern.rb +++ b/app/controllers/concerns/admin_export_controller_concern.rb @@ -26,14 +26,4 @@ module AdminExportControllerConcern def import_params params.require(:admin_import).permit(:data) end - - def import_data_path - params[:admin_import][:data].path - end - - def parse_import_data!(default_headers) - data = CSV.read(import_data_path, headers: true, encoding: 'UTF-8') - data = CSV.read(import_data_path, headers: default_headers, encoding: 'UTF-8') unless data.headers&.first&.strip&.include?(default_headers[0]) - @data = data.reject(&:blank?) - end end diff --git a/app/controllers/concerns/cache_concern.rb b/app/controllers/concerns/cache_concern.rb index 05e431b19..a5a9ba3e1 100644 --- a/app/controllers/concerns/cache_concern.rb +++ b/app/controllers/concerns/cache_concern.rb @@ -3,6 +3,158 @@ module CacheConcern extend ActiveSupport::Concern + module ActiveRecordCoder + EMPTY_HASH = {}.freeze + + class << self + def dump(record) + instances = InstanceTracker.new + serialized_associations = serialize_associations(record, instances) + serialized_records = instances.map { |r| serialize_record(r) } + [serialized_associations, *serialized_records] + end + + def load(payload) + instances = InstanceTracker.new + serialized_associations, *serialized_records = payload + serialized_records.each { |attrs| instances.push(deserialize_record(*attrs)) } + deserialize_associations(serialized_associations, instances) + end + + private + + # Records without associations, or which have already been visited before, + # are serialized by their id alone. + # + # Records with associations are serialized as a two-element array including + # their id and the record's association cache. + # + def serialize_associations(record, instances) + return unless record + + if (id = instances.lookup(record)) + payload = id + else + payload = instances.push(record) + + cached_associations = record.class.reflect_on_all_associations.select do |reflection| + record.association_cached?(reflection.name) + end + + unless cached_associations.empty? + serialized_associations = cached_associations.map do |reflection| + association = record.association(reflection.name) + + serialized_target = if reflection.collection? + association.target.map { |target_record| serialize_associations(target_record, instances) } + else + serialize_associations(association.target, instances) + end + + [reflection.name, serialized_target] + end + + payload = [payload, serialized_associations] + end + end + + payload + end + + def deserialize_associations(payload, instances) + return unless payload + + id, associations = payload + record = instances.fetch(id) + + associations&.each do |name, serialized_target| + begin + association = record.association(name) + rescue ActiveRecord::AssociationNotFoundError + raise AssociationMissingError, "undefined association: #{name}" + end + + target = if association.reflection.collection? + serialized_target.map! { |serialized_record| deserialize_associations(serialized_record, instances) } + else + deserialize_associations(serialized_target, instances) + end + + association.target = target + end + + record + end + + def serialize_record(record) + arguments = [record.class.name, attributes_for_database(record)] + arguments << true if record.new_record? + arguments + end + + if Rails.gem_version >= Gem::Version.new('7.0') + def attributes_for_database(record) + attributes = record.attributes_for_database + attributes.transform_values! { |attr| attr.is_a?(::ActiveModel::Type::Binary::Data) ? attr.to_s : attr } + attributes + end + else + def attributes_for_database(record) + attributes = record.instance_variable_get(:@attributes).send(:attributes).transform_values(&:value_for_database) + attributes.transform_values! { |attr| attr.is_a?(::ActiveModel::Type::Binary::Data) ? attr.to_s : attr } + attributes + end + end + + def deserialize_record(class_name, attributes_from_database, new_record = false) # rubocop:disable Style/OptionalBooleanParameter + begin + klass = Object.const_get(class_name) + rescue NameError + raise ClassMissingError, "undefined class: #{class_name}" + end + + # Ideally we'd like to call `klass.instantiate`, however it doesn't allow to pass + # wether the record was persisted or not. + attributes = klass.attributes_builder.build_from_database(attributes_from_database, EMPTY_HASH) + klass.allocate.init_with_attributes(attributes, new_record) + end + end + + class Error < StandardError + end + + class ClassMissingError < Error + end + + class AssociationMissingError < Error + end + + class InstanceTracker + def initialize + @instances = [] + @ids = {}.compare_by_identity + end + + def map(&block) + @instances.map(&block) + end + + def fetch(...) + @instances.fetch(...) + end + + def push(instance) + id = @ids[instance] = @instances.size + @instances << instance + id + end + + def lookup(instance) + @ids[instance] + end + end + end + def render_with_cache(**options) raise ArgumentError, 'only JSON render calls are supported' unless options.key?(:json) || block_given? @@ -34,8 +186,13 @@ module CacheConcern raw = raw.cache_ids.to_a if raw.is_a?(ActiveRecord::Relation) return [] if raw.empty? - cached_keys_with_value = Rails.cache.read_multi(*raw).transform_keys(&:id) - uncached_ids = raw.map(&:id) - cached_keys_with_value.keys + cached_keys_with_value = begin + Rails.cache.read_multi(*raw).transform_keys(&:id).transform_values { |r| ActiveRecordCoder.load(r) } + rescue ActiveRecordCoder::Error + {} # The serialization format may have changed, let's pretend it's a cache miss. + end + + uncached_ids = raw.map(&:id) - cached_keys_with_value.keys klass.reload_stale_associations!(cached_keys_with_value.values) if klass.respond_to?(:reload_stale_associations!) @@ -43,7 +200,7 @@ module CacheConcern uncached = klass.where(id: uncached_ids).with_includes.index_by(&:id) uncached.each_value do |item| - Rails.cache.write(item, item) + Rails.cache.write(item, ActiveRecordCoder.dump(item)) end end diff --git a/app/controllers/concerns/rate_limit_headers.rb b/app/controllers/concerns/rate_limit_headers.rb index b8696df73..30702f00e 100644 --- a/app/controllers/concerns/rate_limit_headers.rb +++ b/app/controllers/concerns/rate_limit_headers.rb @@ -6,13 +6,11 @@ module RateLimitHeaders class_methods do def override_rate_limit_headers(method_name, options = {}) around_action(only: method_name, if: :current_account) do |_controller, block| - begin - block.call - ensure - rate_limiter = RateLimiter.new(current_account, options) - rate_limit_headers = rate_limiter.to_headers - response.headers.merge!(rate_limit_headers) unless response.headers['X-RateLimit-Remaining'].present? && rate_limit_headers['X-RateLimit-Remaining'].to_i > response.headers['X-RateLimit-Remaining'].to_i - end + block.call + ensure + rate_limiter = RateLimiter.new(current_account, options) + rate_limit_headers = rate_limiter.to_headers + response.headers.merge!(rate_limit_headers) unless response.headers['X-RateLimit-Remaining'].present? && rate_limit_headers['X-RateLimit-Remaining'].to_i > response.headers['X-RateLimit-Remaining'].to_i end end end @@ -67,6 +65,6 @@ module RateLimitHeaders end def reset_period_offset - api_throttle_data[:period] - request_time.to_i % api_throttle_data[:period] + api_throttle_data[:period] - (request_time.to_i % api_throttle_data[:period]) end end diff --git a/app/controllers/concerns/session_tracking_concern.rb b/app/controllers/concerns/session_tracking_concern.rb index eaaa4ac59..3f56c0d02 100644 --- a/app/controllers/concerns/session_tracking_concern.rb +++ b/app/controllers/concerns/session_tracking_concern.rb @@ -13,6 +13,7 @@ module SessionTrackingConcern def set_session_activity return unless session_needs_update? + current_session.touch end diff --git a/app/controllers/concerns/signature_verification.rb b/app/controllers/concerns/signature_verification.rb index 4502da698..931725943 100644 --- a/app/controllers/concerns/signature_verification.rb +++ b/app/controllers/concerns/signature_verification.rb @@ -46,11 +46,11 @@ module SignatureVerification end def require_account_signature! - render plain: signature_verification_failure_reason, status: signature_verification_failure_code unless signed_request_account + render json: signature_verification_failure_reason, status: signature_verification_failure_code unless signed_request_account end def require_actor_signature! - render plain: signature_verification_failure_reason, status: signature_verification_failure_code unless signed_request_actor + render json: signature_verification_failure_reason, status: signature_verification_failure_code unless signed_request_actor end def signed_request? @@ -97,11 +97,11 @@ module SignatureVerification actor = stoplight_wrap_request { actor_refresh_key!(actor) } - raise SignatureVerificationError, "Public key not found for key #{signature_params['keyId']}" if actor.nil? + raise SignatureVerificationError, "Could not refresh public key #{signature_params['keyId']}" if actor.nil? return actor unless verify_signature(actor, signature, compare_signed_string).nil? - fail_with! "Verification failed for #{actor.to_log_human_identifier} #{actor.uri} using rsa-sha256 (RSASSA-PKCS1-v1_5 with SHA-256)" + fail_with! "Verification failed for #{actor.to_log_human_identifier} #{actor.uri} using rsa-sha256 (RSASSA-PKCS1-v1_5 with SHA-256)", signed_string: compare_signed_string, signature: signature_params['signature'] rescue SignatureVerificationError => e fail_with! e.message rescue HTTP::Error, OpenSSL::SSL::SSLError => e @@ -118,8 +118,8 @@ module SignatureVerification private - def fail_with!(message) - @signature_verification_failure_reason = message + def fail_with!(message, **options) + @signature_verification_failure_reason = { error: message }.merge(options) @signed_request_actor = nil end @@ -138,7 +138,7 @@ module SignatureVerification end def signed_headers - signature_params.fetch('headers', signature_algorithm == 'hs2019' ? '(created)' : 'date').downcase.split(' ') + signature_params.fetch('headers', signature_algorithm == 'hs2019' ? '(created)' : 'date').downcase.split end def verify_signature_strength! @@ -165,6 +165,7 @@ module SignatureVerification end raise SignatureVerificationError, "Invalid Digest value. The provided Digest value is not a SHA-256 digest. Given digest: #{sha256[1]}" if digest_size != 32 + raise SignatureVerificationError, "Invalid Digest value. Computed SHA-256 digest: #{body_digest}; given: #{sha256[1]}" end @@ -209,8 +210,8 @@ module SignatureVerification end expires_time = Time.at(signature_params['expires'].to_i).utc if signature_params['expires'].present? - rescue ArgumentError - return false + rescue ArgumentError => e + raise SignatureVerificationError, "Invalid Date header: #{e.message}" end expires_time ||= created_time + 5.minutes unless created_time.nil? @@ -227,7 +228,7 @@ module SignatureVerification end def to_header_name(name) - name.split(/-/).map(&:capitalize).join('-') + name.split('-').map(&:capitalize).join('-') end def missing_required_signature_parameters? diff --git a/app/controllers/concerns/two_factor_authentication_concern.rb b/app/controllers/concerns/two_factor_authentication_concern.rb index c9477a1d4..b30cd354d 100644 --- a/app/controllers/concerns/two_factor_authentication_concern.rb +++ b/app/controllers/concerns/two_factor_authentication_concern.rb @@ -57,10 +57,10 @@ module TwoFactorAuthenticationConcern if valid_webauthn_credential?(user, webauthn_credential) on_authentication_success(user, :webauthn) - render json: { redirect_path: after_sign_in_path_for(user) }, status: :ok + render json: { redirect_path: after_sign_in_path_for(user) }, status: 200 else on_authentication_failure(user, :webauthn, :invalid_credential) - render json: { error: t('webauthn_credentials.invalid_credential') }, status: :unprocessable_entity + render json: { error: t('webauthn_credentials.invalid_credential') }, status: 422 end end @@ -81,13 +81,11 @@ module TwoFactorAuthenticationConcern @body_classes = 'lighter' @webauthn_enabled = user.webauthn_enabled? - @scheme_type = begin - if user.webauthn_enabled? && user_params[:otp_attempt].blank? - 'webauthn' - else - 'totp' - end - end + @scheme_type = if user.webauthn_enabled? && user_params[:otp_attempt].blank? + 'webauthn' + else + 'totp' + end set_locale { render :two_factor } end diff --git a/app/controllers/filters/statuses_controller.rb b/app/controllers/filters/statuses_controller.rb index 4f63de7b6..86d11fcb9 100644 --- a/app/controllers/filters/statuses_controller.rb +++ b/app/controllers/filters/statuses_controller.rb @@ -43,9 +43,7 @@ class Filters::StatusesController < ApplicationController end def action_from_button - if params[:remove] - 'remove' - end + 'remove' if params[:remove] end def set_body_classes diff --git a/app/controllers/media_controller.rb b/app/controllers/media_controller.rb index f9160d8c4..37c5dcb99 100644 --- a/app/controllers/media_controller.rb +++ b/app/controllers/media_controller.rb @@ -33,7 +33,7 @@ class MediaController < ApplicationController scope = MediaAttachment.local.attached # If id is 19 characters long, it's a shortcode, otherwise it's an identifier - @media_attachment = id.size == 19 ? scope.find_by!(shortcode: id) : scope.find_by!(id: id) + @media_attachment = id.size == 19 ? scope.find_by!(shortcode: id) : scope.find(id) end def verify_permitted_status! diff --git a/app/controllers/media_proxy_controller.rb b/app/controllers/media_proxy_controller.rb index 3b228722f..f29b69a24 100644 --- a/app/controllers/media_proxy_controller.rb +++ b/app/controllers/media_proxy_controller.rb @@ -23,7 +23,7 @@ class MediaProxyController < ApplicationController redownload! if @media_attachment.needs_redownload? && !reject_media? end - redirect_to full_asset_url(@media_attachment.file.url(version)) + redirect_to full_asset_url(@media_attachment.file.url(version)), allow_other_host: true end private diff --git a/app/controllers/relationships_controller.rb b/app/controllers/relationships_controller.rb index d40770726..52cf1e0c1 100644 --- a/app/controllers/relationships_controller.rb +++ b/app/controllers/relationships_controller.rb @@ -20,6 +20,8 @@ class RelationshipsController < ApplicationController @form.save rescue ActionController::ParameterMissing # Do nothing + rescue Mastodon::NotPermittedError, ActiveRecord::RecordNotFound + flash[:alert] = I18n.t('relationships.follow_failure') if action_from_button == 'follow' ensure redirect_to relationships_path(filter_params) end @@ -61,8 +63,8 @@ class RelationshipsController < ApplicationController 'unfollow' elsif params[:remove_from_followers] 'remove_from_followers' - elsif params[:block_domains] - 'block_domains' + elsif params[:block_domains] || params[:remove_domains_from_followers] + 'remove_domains_from_followers' end end diff --git a/app/controllers/settings/applications_controller.rb b/app/controllers/settings/applications_controller.rb index d3ac268d8..e6e137c2b 100644 --- a/app/controllers/settings/applications_controller.rb +++ b/app/controllers/settings/applications_controller.rb @@ -29,7 +29,13 @@ class Settings::ApplicationsController < Settings::BaseController def update if @application.update(application_params) - redirect_to settings_applications_path, notice: I18n.t('generic.changes_saved_msg') + if @application.scopes_previously_changed? + @access_token = current_user.token_for_app(@application) + @access_token.destroy + redirect_to settings_application_path(@application), notice: I18n.t('applications.token_regenerated') + else + redirect_to settings_application_path(@application), notice: I18n.t('generic.changes_saved_msg') + end else render :show end diff --git a/app/controllers/settings/flavours_controller.rb b/app/controllers/settings/flavours_controller.rb index 62c52eee9..b179b9429 100644 --- a/app/controllers/settings/flavours_controller.rb +++ b/app/controllers/settings/flavours_controller.rb @@ -12,27 +12,15 @@ class Settings::FlavoursController < Settings::BaseController end def show - unless Themes.instance.flavours.include?(params[:flavour]) || (params[:flavour] == current_flavour) - redirect_to action: 'show', flavour: current_flavour - end + redirect_to action: 'show', flavour: current_flavour unless Themes.instance.flavours.include?(params[:flavour]) || (params[:flavour] == current_flavour) @listing = Themes.instance.flavours @selected = params[:flavour] end def update - user_settings.update(user_settings_params) + current_user.settings.update(flavour: params.require(:flavour), skin: params.dig(:user, :setting_skin)) + current_user.save redirect_to action: 'show', flavour: params[:flavour] end - - private - - def user_settings - UserSettingsDecorator.new(current_user) - end - - def user_settings_params - { setting_flavour: params.require(:flavour), - setting_skin: params.dig(:user, :setting_skin) }.with_indifferent_access - end end diff --git a/app/controllers/settings/preferences_controller.rb b/app/controllers/settings/preferences_controller.rb index 4c1336436..281deb64d 100644 --- a/app/controllers/settings/preferences_controller.rb +++ b/app/controllers/settings/preferences_controller.rb @@ -4,8 +4,6 @@ class Settings::PreferencesController < Settings::BaseController def show; end def update - user_settings.update(user_settings_params.to_h) - if current_user.update(user_params) I18n.locale = current_user.locale redirect_to after_update_redirect_path, notice: I18n.t('generic.changes_saved_msg') @@ -20,46 +18,7 @@ class Settings::PreferencesController < Settings::BaseController settings_preferences_path end - def user_settings - UserSettingsDecorator.new(current_user) - end - def user_params - params.require(:user).permit( - :locale, - chosen_languages: [] - ) - end - - def user_settings_params - params.require(:user).permit( - :setting_default_privacy, - :setting_default_sensitive, - :setting_default_language, - :setting_unfollow_modal, - :setting_boost_modal, - :setting_favourite_modal, - :setting_delete_modal, - :setting_auto_play_gif, - :setting_display_media, - :setting_expand_spoilers, - :setting_reduce_motion, - :setting_disable_swiping, - :setting_system_font_ui, - :setting_system_emoji_font, - :setting_noindex, - :setting_hide_followers_count, - :setting_aggregate_reblogs, - :setting_show_application, - :setting_advanced_layout, - :setting_default_content_type, - :setting_use_blurhash, - :setting_use_pending_items, - :setting_trends, - :setting_crop_images, - :setting_always_send_emails, - notification_emails: %i(follow follow_request reblog favourite mention report pending_account trending_tag trending_link trending_status appeal), - interactions: %i(must_be_follower must_be_following must_be_following_dm) - ) + params.require(:user).permit(:locale, chosen_languages: [], settings_attributes: UserSettings.keys) end end diff --git a/app/controllers/settings/two_factor_authentication/otp_authentication_controller.rb b/app/controllers/settings/two_factor_authentication/otp_authentication_controller.rb index cbba842a9..0bff01ec2 100644 --- a/app/controllers/settings/two_factor_authentication/otp_authentication_controller.rb +++ b/app/controllers/settings/two_factor_authentication/otp_authentication_controller.rb @@ -22,18 +22,9 @@ module Settings private - def confirmation_params - params.require(:form_two_factor_confirmation).permit(:otp_attempt) - end - def verify_otp_not_enabled redirect_to settings_two_factor_authentication_methods_path if current_user.otp_enabled? end - - def acceptable_code? - current_user.validate_and_consume_otp!(confirmation_params[:otp_attempt]) || - current_user.invalidate_otp_backup_code!(confirmation_params[:otp_attempt]) - end end end end diff --git a/app/controllers/settings/two_factor_authentication/webauthn_credentials_controller.rb b/app/controllers/settings/two_factor_authentication/webauthn_credentials_controller.rb index 7e2d43dcd..5a9029a42 100644 --- a/app/controllers/settings/two_factor_authentication/webauthn_credentials_controller.rb +++ b/app/controllers/settings/two_factor_authentication/webauthn_credentials_controller.rb @@ -27,7 +27,7 @@ module Settings session[:webauthn_challenge] = options_for_create.challenge - render json: options_for_create, status: :ok + render json: options_for_create, status: 200 end def create @@ -52,7 +52,7 @@ module Settings end else flash[:error] = I18n.t('webauthn_credentials.create.error') - status = :internal_server_error + status = :unprocessable_entity end else flash[:error] = t('webauthn_credentials.create.error') diff --git a/app/controllers/statuses_controller.rb b/app/controllers/statuses_controller.rb index e5221df3a..15c081264 100644 --- a/app/controllers/statuses_controller.rb +++ b/app/controllers/statuses_controller.rb @@ -9,11 +9,12 @@ class StatusesController < ApplicationController before_action :require_account_signature!, only: [:show, :activity], if: -> { request.format == :json && authorized_fetch_mode? } before_action :set_status before_action :set_instance_presenter - before_action :set_link_headers before_action :redirect_to_original, only: :show before_action :set_cache_headers before_action :set_body_classes, only: :embed + after_action :set_link_headers + skip_around_action :set_locale, if: -> { request.format == :json } skip_before_action :require_functional!, only: [:show, :embed], unless: :whitelist_mode? @@ -71,6 +72,6 @@ class StatusesController < ApplicationController end def redirect_to_original - redirect_to ActivityPub::TagManager.instance.url_for(@status.reblog) if @status.reblog? + redirect_to(ActivityPub::TagManager.instance.url_for(@status.reblog), allow_other_host: true) if @status.reblog? end end diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb index 65017acba..4b747c9ad 100644 --- a/app/controllers/tags_controller.rb +++ b/app/controllers/tags_controller.rb @@ -11,7 +11,7 @@ class TagsController < ApplicationController before_action :authenticate_user!, if: :whitelist_mode? before_action :set_local before_action :set_tag - before_action :set_statuses + before_action :set_statuses, if: -> { request.format == :rss } before_action :set_instance_presenter skip_before_action :require_functional!, unless: :whitelist_mode? @@ -44,12 +44,7 @@ class TagsController < ApplicationController end def set_statuses - case request.format&.to_sym - when :json - @statuses = cache_collection(TagFeed.new(@tag, current_account, local: @local).get(PAGE_SIZE, params[:max_id], params[:since_id], params[:min_id]), Status) - when :rss - @statuses = cache_collection(TagFeed.new(@tag, nil, local: @local).get(limit_param), Status) - end + @statuses = cache_collection(TagFeed.new(@tag, nil, local: @local).get(limit_param), Status) end def set_instance_presenter @@ -63,9 +58,7 @@ class TagsController < ApplicationController def collection_presenter ActivityPub::CollectionPresenter.new( id: tag_url(@tag), - type: :ordered, - size: @tag.statuses.count, - items: @statuses.map { |status| ActivityPub::TagManager.instance.uri_for(status) } + type: :ordered ) end end |